@hanzo/ui 8.0.55 → 8.0.57

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 (66) hide show
  1. package/README.md +5 -1
  2. package/dist/backends/gui/switch.cjs +43 -3
  3. package/dist/backends/gui/switch.d.ts +27 -2
  4. package/dist/backends/gui/switch.d.ts.map +1 -1
  5. package/dist/backends/gui/switch.js +43 -3
  6. package/dist/backends/gui/switch.js.map +1 -1
  7. package/dist/chat/Code.cjs +2 -36
  8. package/dist/chat/Code.d.ts +0 -13
  9. package/dist/chat/Code.d.ts.map +1 -1
  10. package/dist/chat/Code.js +2 -35
  11. package/dist/chat/Code.js.map +1 -1
  12. package/dist/chat/index.cjs +7 -2
  13. package/dist/chat/index.d.ts +7 -1
  14. package/dist/chat/index.d.ts.map +1 -1
  15. package/dist/chat/index.js +7 -1
  16. package/dist/chat/index.js.map +1 -1
  17. package/dist/product/AppHeader.cjs +8 -6
  18. package/dist/product/AppHeader.d.ts.map +1 -1
  19. package/dist/product/AppHeader.js +11 -9
  20. package/dist/product/AppHeader.js.map +1 -1
  21. package/dist/product/CopyButton.cjs +54 -0
  22. package/dist/product/CopyButton.d.ts +12 -0
  23. package/dist/product/CopyButton.d.ts.map +1 -0
  24. package/dist/product/CopyButton.js +52 -0
  25. package/dist/product/CopyButton.js.map +1 -0
  26. package/dist/product/Field.cjs +2 -1
  27. package/dist/product/Field.d.ts.map +1 -1
  28. package/dist/product/Field.js +2 -1
  29. package/dist/product/Field.js.map +1 -1
  30. package/dist/product/Fieldset.cjs +13 -0
  31. package/dist/product/Fieldset.d.ts +35 -0
  32. package/dist/product/Fieldset.d.ts.map +1 -0
  33. package/dist/product/Fieldset.js +11 -0
  34. package/dist/product/Fieldset.js.map +1 -0
  35. package/dist/product/OrgMark.cjs +39 -3
  36. package/dist/product/OrgMark.d.ts +9 -0
  37. package/dist/product/OrgMark.d.ts.map +1 -1
  38. package/dist/product/OrgMark.js +38 -3
  39. package/dist/product/OrgMark.js.map +1 -1
  40. package/dist/product/OrgSwitcher.cjs +3 -3
  41. package/dist/product/OrgSwitcher.d.ts +29 -1
  42. package/dist/product/OrgSwitcher.d.ts.map +1 -1
  43. package/dist/product/OrgSwitcher.js +3 -3
  44. package/dist/product/OrgSwitcher.js.map +1 -1
  45. package/dist/product/Pagination.cjs +72 -0
  46. package/dist/product/Pagination.d.ts +21 -0
  47. package/dist/product/Pagination.d.ts.map +1 -0
  48. package/dist/product/Pagination.js +68 -0
  49. package/dist/product/Pagination.js.map +1 -0
  50. package/dist/product/SecretInput.cjs +59 -0
  51. package/dist/product/SecretInput.d.ts +24 -0
  52. package/dist/product/SecretInput.d.ts.map +1 -0
  53. package/dist/product/SecretInput.js +55 -0
  54. package/dist/product/SecretInput.js.map +1 -0
  55. package/dist/product/UserMenu.cjs +63 -0
  56. package/dist/product/UserMenu.d.ts +56 -0
  57. package/dist/product/UserMenu.d.ts.map +1 -0
  58. package/dist/product/UserMenu.js +60 -0
  59. package/dist/product/UserMenu.js.map +1 -0
  60. package/dist/product/index.cjs +21 -2
  61. package/dist/product/index.d.ts +5 -0
  62. package/dist/product/index.d.ts.map +1 -1
  63. package/dist/product/index.js +21 -2
  64. package/dist/product/index.js.map +1 -1
  65. package/dist/styles.css +7 -1
  66. package/package.json +1 -1
package/README.md CHANGED
@@ -26,7 +26,11 @@ import { RecordsView, DataTable, BoardView, RecordDetail, registerField } from '
26
26
  - **Charts** (dependency-free inline SVG): `Sparkline`, `LineChart`, `BarChart`, `Donut`, `BarRows` — hover tooltips, axis ticks, honest `null` under two real points.
27
27
  - **Metric** tiles/panels: `MetricCard`, `MiniBars`, `UtilBar`, `LegendDot`, `Panel`, `HintButton` (+ `MetricSparkline`).
28
28
  - **Chrome**: `PageHeader`, `StatusTag`, `EmptyState` (DO/Vercel-class first-run), `PrimaryButton`, `HanzoMark`, `ProductIcon`, `ProviderLogo`.
29
- - **Interaction**: `ComboBox` (typeable, ReDoS-safe filter), `SelectMenu`, `SlideOver` (a11y drawer), `Toast` (`useToast`), `Reorder` (pointer DnD), `Field*` rows, `FadeIn`, `ThemeToggle`, generic `DataTable<T>`.
29
+ - **The identity trio** one row of chrome, three switchers: `OrgSwitcher` (which workspace, `direction` up or down, `footer` for a surface's own rows), the app switcher inside `AppHeader`, and `UserMenu` (who I am). `AppHeader` composes all three; each is importable alone, so a surface that wants an account menu without the whole header does not write a sixth one.
30
+ - **Settings**: `Fieldset` — the titled, optionally destructive group the `Field*` rows sit in. Not `Panel`: that is a dashboard metric tile.
31
+ - **Interaction**: `ComboBox` (typeable, ReDoS-safe filter), `SelectMenu`, `SlideOver` (a11y drawer), `Toast` (`useToast`), `Reorder` (pointer DnD), `Field*` rows, `CopyButton`, `SecretInput` (mask · reveal · copy), `Pagination` (+ the pure `pages` rule), `FadeIn`, `ThemeToggle`, generic `DataTable<T>`.
32
+
33
+ > **Masking needs both spellings.** `secureTextEntry` is React Native's and gui **drops it on web**, so an input carrying only that prop renders the secret in plain text; `type="password"` is the web one and native ignores it. `masked(on)` sets both and is what `SecretInput` and `<FieldText secure>` use. Never pass `secureTextEntry` alone.
30
34
  - **Tokens**: `tokens`, `TAG_TONES`, `tagTone` — the calm, dark-first, zinc-on-black identity.
31
35
  - **`@hanzo/ui/data`** — the metadata-driven record layer (source of truth: `@hanzo/data`): `RecordsView` (table ⇆ board, filter/sort/search/group, inline edit, saved views), the record-grid `DataTable`, `BoardView`, `RecordDetail`/`RecordForm`, every typed field editor, the field registry, and the pure view/sort/filter logic.
32
36
 
@@ -3,13 +3,53 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.Switch = void 0;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
- /** Switch — 36×20 track, 16px thumb, `touch()` to the 44px floor everywhere. */
6
+ /**
7
+ * Switch — a 36×20 pill, 16px thumb, `touch()` to the 44px floor everywhere.
8
+ *
9
+ * `minHeight` is NOT redundant beside `height`, and omitting it was the bug.
10
+ * gui's own `size` variant returns `{ height, minHeight, width }` for the
11
+ * default `$true` size, and setting `height` here overrode only two of the
12
+ * three — min-height beats height, always — so the 29px floor survived and
13
+ * every switch in every app rendered 36×29 instead of 36×20. At that ratio the
14
+ * browser clamps `borderRadius: 1000` to 10px, so it was not even a pill: a
15
+ * rounded rectangle with a small dot adrift inside it.
16
+ *
17
+ * State is carried by COLOUR, not by the thumb's 14px of travel alone. gui's
18
+ * default checked treatment is `$backgroundActive`, which in this theme resolves
19
+ * to the same value the unchecked track already has — measured live, on and off
20
+ * were pixel-identical apart from that translation. A state expressed only as
21
+ * position is one a screenshot, a narrow column and a low-vision reader all fail
22
+ * to read. `activeStyle` is the hook gui honours for exactly this: it is pulled
23
+ * out of props before Tamagui can mistake it for the press pseudo-style, and it
24
+ * REPLACES `$backgroundActive` rather than layering over it.
25
+ *
26
+ * The white is spent on ON and nowhere else. A resting page is mostly switches
27
+ * that are off, and a near-white thumb on every one of them is a field of lights
28
+ * with no signal in it — which is what a full page of these actually looked
29
+ * like. Off is muted, on is filled, and the loudest treatment is the one that
30
+ * means something.
31
+ */
7
32
  const gui_1 = require("@hanzo/gui");
8
33
  const slot_1 = require("./slot.cjs");
9
34
  const gesture_1 = require("./gesture.cjs");
35
+ const TRACK_W = 36;
10
36
  const TRACK_H = 20;
11
37
  const THUMB = 16;
12
- const Switch = (props) => ((0, jsx_runtime_1.jsx)(gui_1.Switch, { ...(0, slot_1.slot)('switch'), width: 36, height: TRACK_H, padding: 2, flexShrink: 0,
38
+ const Switch = ({ disabled, ...props }) => ((0, jsx_runtime_1.jsx)(gui_1.Switch, { ...(0, slot_1.slot)('switch'), width: TRACK_W, height: TRACK_H, minHeight: TRACK_H, padding: 2, flexShrink: 0, backgroundColor: "$color3",
13
39
  // Without an explicit border the UA's 2px outset button border shows.
14
- borderWidth: 1, borderColor: "$borderColor", ...(0, gesture_1.touch)(TRACK_H, 44, 'y'), ...props, children: (0, jsx_runtime_1.jsx)(gui_1.Switch.Thumb, { ...(0, slot_1.slot)('switch-thumb'), width: THUMB, height: THUMB }) }));
40
+ borderWidth: 1, borderColor: "$borderColor", activeStyle: { backgroundColor: '$color12', borderColor: '$color12' },
41
+ // Stated rather than left to a `disabledStyle` this backend uses nowhere
42
+ // else: a control that ignores its own disabled prop looks identical to a
43
+ // live one, and the page this was found on had a disabled switch sitting
44
+ // beside eight enabled ones with nothing to tell them apart.
45
+ disabled: disabled, opacity: disabled ? 0.5 : 1, cursor: disabled ? 'not-allowed' : 'pointer', ...(0, gesture_1.touch)(TRACK_H, 44, 'y'), ...props, children: (0, jsx_runtime_1.jsx)(gui_1.Switch.Thumb, { ...(0, slot_1.slot)('switch-thumb'), width: THUMB, height: THUMB, backgroundColor: "$color10",
46
+ // `bg`, and it is the only one of the three spellings that is both typed
47
+ // and correct. The Thumb's activeStyle is typed as the SHORTHAND style set:
48
+ // `backgroundColor` paints but is not in that type; `background` is in it
49
+ // and compiles to a SEPARATE `_background-` class that races the base
50
+ // `_bg-` one on load order rather than replacing it; `bg` replaces it.
51
+ // Consumers build with ignoreBuildErrors, so the first would have shipped
52
+ // an error nobody sees and the second a colour that lands or does not
53
+ // depending on stylesheet order.
54
+ activeStyle: { bg: '$color1' } }) }));
15
55
  exports.Switch = Switch;
@@ -1,7 +1,32 @@
1
- /** Switch — 36×20 track, 16px thumb, `touch()` to the 44px floor everywhere. */
1
+ /**
2
+ * Switch — a 36×20 pill, 16px thumb, `touch()` to the 44px floor everywhere.
3
+ *
4
+ * `minHeight` is NOT redundant beside `height`, and omitting it was the bug.
5
+ * gui's own `size` variant returns `{ height, minHeight, width }` for the
6
+ * default `$true` size, and setting `height` here overrode only two of the
7
+ * three — min-height beats height, always — so the 29px floor survived and
8
+ * every switch in every app rendered 36×29 instead of 36×20. At that ratio the
9
+ * browser clamps `borderRadius: 1000` to 10px, so it was not even a pill: a
10
+ * rounded rectangle with a small dot adrift inside it.
11
+ *
12
+ * State is carried by COLOUR, not by the thumb's 14px of travel alone. gui's
13
+ * default checked treatment is `$backgroundActive`, which in this theme resolves
14
+ * to the same value the unchecked track already has — measured live, on and off
15
+ * were pixel-identical apart from that translation. A state expressed only as
16
+ * position is one a screenshot, a narrow column and a low-vision reader all fail
17
+ * to read. `activeStyle` is the hook gui honours for exactly this: it is pulled
18
+ * out of props before Tamagui can mistake it for the press pseudo-style, and it
19
+ * REPLACES `$backgroundActive` rather than layering over it.
20
+ *
21
+ * The white is spent on ON and nowhere else. A resting page is mostly switches
22
+ * that are off, and a near-white thumb on every one of them is a field of lights
23
+ * with no signal in it — which is what a full page of these actually looked
24
+ * like. Off is muted, on is filled, and the loudest treatment is the one that
25
+ * means something.
26
+ */
2
27
  import { Switch as GuiSwitch } from '@hanzo/gui';
3
28
  import type { ComponentProps } from 'react';
4
29
  export type SwitchProps = ComponentProps<typeof GuiSwitch>;
5
- declare const Switch: (props: SwitchProps) => import("react/jsx-runtime").JSX.Element;
30
+ declare const Switch: ({ disabled, ...props }: SwitchProps) => import("react/jsx-runtime").JSX.Element;
6
31
  export { Switch };
7
32
  //# sourceMappingURL=switch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"switch.d.ts","sourceRoot":"","sources":["../../../src/backends/gui/switch.tsx"],"names":[],"mappings":"AAEA,gFAAgF;AAChF,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAO3C,MAAM,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,SAAS,CAAC,CAAA;AAE1D,QAAA,MAAM,MAAM,GAAI,OAAO,WAAW,4CAmBjC,CAAA;AAED,OAAO,EAAE,MAAM,EAAE,CAAA"}
1
+ {"version":3,"file":"switch.d.ts","sourceRoot":"","sources":["../../../src/backends/gui/switch.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAQ3C,MAAM,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,SAAS,CAAC,CAAA;AAE1D,QAAA,MAAM,MAAM,GAAI,wBAAwB,WAAW,4CAuClD,CAAA;AAED,OAAO,EAAE,MAAM,EAAE,CAAA"}
@@ -1,13 +1,53 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- /** Switch — 36×20 track, 16px thumb, `touch()` to the 44px floor everywhere. */
3
+ /**
4
+ * Switch — a 36×20 pill, 16px thumb, `touch()` to the 44px floor everywhere.
5
+ *
6
+ * `minHeight` is NOT redundant beside `height`, and omitting it was the bug.
7
+ * gui's own `size` variant returns `{ height, minHeight, width }` for the
8
+ * default `$true` size, and setting `height` here overrode only two of the
9
+ * three — min-height beats height, always — so the 29px floor survived and
10
+ * every switch in every app rendered 36×29 instead of 36×20. At that ratio the
11
+ * browser clamps `borderRadius: 1000` to 10px, so it was not even a pill: a
12
+ * rounded rectangle with a small dot adrift inside it.
13
+ *
14
+ * State is carried by COLOUR, not by the thumb's 14px of travel alone. gui's
15
+ * default checked treatment is `$backgroundActive`, which in this theme resolves
16
+ * to the same value the unchecked track already has — measured live, on and off
17
+ * were pixel-identical apart from that translation. A state expressed only as
18
+ * position is one a screenshot, a narrow column and a low-vision reader all fail
19
+ * to read. `activeStyle` is the hook gui honours for exactly this: it is pulled
20
+ * out of props before Tamagui can mistake it for the press pseudo-style, and it
21
+ * REPLACES `$backgroundActive` rather than layering over it.
22
+ *
23
+ * The white is spent on ON and nowhere else. A resting page is mostly switches
24
+ * that are off, and a near-white thumb on every one of them is a field of lights
25
+ * with no signal in it — which is what a full page of these actually looked
26
+ * like. Off is muted, on is filled, and the loudest treatment is the one that
27
+ * means something.
28
+ */
4
29
  import { Switch as GuiSwitch } from '@hanzo/gui';
5
30
  import { slot } from './slot.js';
6
31
  import { touch } from './gesture.js';
32
+ const TRACK_W = 36;
7
33
  const TRACK_H = 20;
8
34
  const THUMB = 16;
9
- const Switch = (props) => (_jsx(GuiSwitch, { ...slot('switch'), width: 36, height: TRACK_H, padding: 2, flexShrink: 0,
35
+ const Switch = ({ disabled, ...props }) => (_jsx(GuiSwitch, { ...slot('switch'), width: TRACK_W, height: TRACK_H, minHeight: TRACK_H, padding: 2, flexShrink: 0, backgroundColor: "$color3",
10
36
  // Without an explicit border the UA's 2px outset button border shows.
11
- borderWidth: 1, borderColor: "$borderColor", ...touch(TRACK_H, 44, 'y'), ...props, children: _jsx(GuiSwitch.Thumb, { ...slot('switch-thumb'), width: THUMB, height: THUMB }) }));
37
+ borderWidth: 1, borderColor: "$borderColor", activeStyle: { backgroundColor: '$color12', borderColor: '$color12' },
38
+ // Stated rather than left to a `disabledStyle` this backend uses nowhere
39
+ // else: a control that ignores its own disabled prop looks identical to a
40
+ // live one, and the page this was found on had a disabled switch sitting
41
+ // beside eight enabled ones with nothing to tell them apart.
42
+ disabled: disabled, opacity: disabled ? 0.5 : 1, cursor: disabled ? 'not-allowed' : 'pointer', ...touch(TRACK_H, 44, 'y'), ...props, children: _jsx(GuiSwitch.Thumb, { ...slot('switch-thumb'), width: THUMB, height: THUMB, backgroundColor: "$color10",
43
+ // `bg`, and it is the only one of the three spellings that is both typed
44
+ // and correct. The Thumb's activeStyle is typed as the SHORTHAND style set:
45
+ // `backgroundColor` paints but is not in that type; `background` is in it
46
+ // and compiles to a SEPARATE `_background-` class that races the base
47
+ // `_bg-` one on load order rather than replacing it; `bg` replaces it.
48
+ // Consumers build with ignoreBuildErrors, so the first would have shipped
49
+ // an error nobody sees and the second a colour that lands or does not
50
+ // depending on stylesheet order.
51
+ activeStyle: { bg: '$color1' } }) }));
12
52
  export { Switch };
13
53
  //# sourceMappingURL=switch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"switch.js","sourceRoot":"","sources":["../../../src/backends/gui/switch.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,gFAAgF;AAChF,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,YAAY,CAAA;AAEhD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AAEjC,MAAM,OAAO,GAAG,EAAE,CAAA;AAClB,MAAM,KAAK,GAAG,EAAE,CAAA;AAIhB,MAAM,MAAM,GAAG,CAAC,KAAkB,EAAE,EAAE,CAAC,CACrC,KAAC,SAAS,OACJ,IAAI,CAAC,QAAQ,CAAC,EAClB,KAAK,EAAE,EAAE,EACT,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,CAAC,EACV,UAAU,EAAE,CAAC;IACb,sEAAsE;IACtE,WAAW,EAAE,CAAC,EACd,WAAW,EAAC,cAAc,KACtB,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,KACvB,KAAK,YAET,KAAC,SAAS,CAAC,KAAK,OACV,IAAI,CAAC,cAAc,CAAC,EACxB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,KAAK,GACb,GACQ,CACb,CAAA;AAED,OAAO,EAAE,MAAM,EAAE,CAAA"}
1
+ {"version":3,"file":"switch.js","sourceRoot":"","sources":["../../../src/backends/gui/switch.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,YAAY,CAAA;AAEhD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AAEjC,MAAM,OAAO,GAAG,EAAE,CAAA;AAClB,MAAM,OAAO,GAAG,EAAE,CAAA;AAClB,MAAM,KAAK,GAAG,EAAE,CAAA;AAIhB,MAAM,MAAM,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAe,EAAE,EAAE,CAAC,CACtD,KAAC,SAAS,OACJ,IAAI,CAAC,QAAQ,CAAC,EAClB,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,OAAO,EAClB,OAAO,EAAE,CAAC,EACV,UAAU,EAAE,CAAC,EACb,eAAe,EAAC,SAAS;IACzB,sEAAsE;IACtE,WAAW,EAAE,CAAC,EACd,WAAW,EAAC,cAAc,EAC1B,WAAW,EAAE,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE;IACrE,yEAAyE;IACzE,0EAA0E;IAC1E,yEAAyE;IACzE,6DAA6D;IAC7D,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAC3B,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,KACxC,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,KACvB,KAAK,YAET,KAAC,SAAS,CAAC,KAAK,OACV,IAAI,CAAC,cAAc,CAAC,EACxB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,KAAK,EACb,eAAe,EAAC,UAAU;QAC1B,yEAAyE;QACzE,4EAA4E;QAC5E,0EAA0E;QAC1E,sEAAsE;QACtE,uEAAuE;QACvE,0EAA0E;QAC1E,sEAAsE;QACtE,iCAAiC;QACjC,WAAW,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,GAC9B,GACQ,CACb,CAAA;AAED,OAAO,EAAE,MAAM,EAAE,CAAA"}
@@ -2,7 +2,6 @@
2
2
  'use client';
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.Code = Code;
5
- exports.CopyButton = CopyButton;
6
5
  const jsx_runtime_1 = require("react/jsx-runtime");
7
6
  /**
8
7
  * Code — a labelled, copyable code region.
@@ -17,11 +16,8 @@ const jsx_runtime_1 = require("react/jsx-runtime");
17
16
  * plain text or its own highlighted nodes.
18
17
  */
19
18
  const gui_1 = require("@hanzo/gui");
20
- const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
21
- const react_1 = require("react");
22
19
  const slot_1 = require("../backends/gui/slot.cjs");
23
- /** How long the copy control shows its confirmation, in ms. */
24
- const CONFIRM = 2000;
20
+ const CopyButton_1 = require("../product/CopyButton.cjs");
25
21
  /**
26
22
  * Monospace stack, applied through `style` rather than a `$mono` token.
27
23
  *
@@ -36,35 +32,5 @@ const MONO = {
36
32
  };
37
33
  function Code({ children, language = 'text', value, actions }) {
38
34
  const text = value ?? (typeof children === 'string' ? children : '');
39
- return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('code'), width: "100%", rounded: "$4", borderWidth: 1, borderColor: "$borderColor", bg: "$color2", overflow: "hidden", children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$1", px: "$3", py: "$1.5", borderBottomWidth: 1, borderColor: "$borderColor", children: [(0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", style: MONO, color: "$color10", children: language }), (0, jsx_runtime_1.jsx)(gui_1.XStack, { flex: 1 }), actions, text ? (0, jsx_runtime_1.jsx)(CopyButton, { value: text }) : null] }), (0, jsx_runtime_1.jsx)(gui_1.YStack, { px: "$3", py: "$2.5", children: (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", style: MONO, lineHeight: 20, children: children }) })] }));
40
- }
41
- /**
42
- * CopyButton — copy with a confirmation tick.
43
- *
44
- * The tick is the point. A control that looks identical before and after leaves
45
- * the reader unsure whether it fired, and the usual response is to press it
46
- * again. Reverts after `CONFIRM`, and clears its timer on unmount so it cannot
47
- * set state on a component that is gone.
48
- */
49
- function CopyButton({ value, label = 'Copy' }) {
50
- const [copied, setCopied] = (0, react_1.useState)(false);
51
- const timer = (0, react_1.useRef)(undefined);
52
- (0, react_1.useEffect)(() => () => clearTimeout(timer.current), []);
53
- const copy = () => {
54
- // Optional-chained rather than assumed: `navigator.clipboard` is undefined
55
- // in insecure contexts and absent entirely on native, and these components
56
- // are meant to run on both.
57
- navigator?.clipboard
58
- ?.writeText(value)
59
- .then(() => {
60
- setCopied(true);
61
- clearTimeout(timer.current);
62
- timer.current = setTimeout(() => setCopied(false), CONFIRM);
63
- })
64
- .catch(() => {
65
- // A refused clipboard needs no toast — the missing tick already says it,
66
- // and an error dialog for a failed copy is louder than the failure.
67
- });
68
- };
69
- return ((0, jsx_runtime_1.jsx)(gui_1.XStack, { width: 24, height: 24, items: "center", justify: "center", rounded: "$2", cursor: "pointer", opacity: 0.7, onPress: copy, role: "button", tabIndex: 0, "aria-label": copied ? 'Copied' : label, ...(0, slot_1.tip)(copied ? 'Copied' : label), hoverStyle: { bg: '$color4', opacity: 1 }, pressStyle: { bg: '$color5' }, children: copied ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Check, { size: 14 }) : (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Copy, { size: 14 }) }));
35
+ return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('code'), width: "100%", rounded: "$4", borderWidth: 1, borderColor: "$borderColor", bg: "$color2", overflow: "hidden", children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$1", px: "$3", py: "$1.5", borderBottomWidth: 1, borderColor: "$borderColor", children: [(0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", style: MONO, color: "$color10", children: language }), (0, jsx_runtime_1.jsx)(gui_1.XStack, { flex: 1 }), actions, text ? (0, jsx_runtime_1.jsx)(CopyButton_1.CopyButton, { value: text }) : null] }), (0, jsx_runtime_1.jsx)(gui_1.YStack, { px: "$3", py: "$2.5", children: (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", style: MONO, lineHeight: 20, children: children }) })] }));
70
36
  }
@@ -9,17 +9,4 @@ export interface CodeProps {
9
9
  actions?: ReactNode;
10
10
  }
11
11
  export declare function Code({ children, language, value, actions }: CodeProps): import("react/jsx-runtime").JSX.Element;
12
- export interface CopyButtonProps {
13
- value: string;
14
- label?: string;
15
- }
16
- /**
17
- * CopyButton — copy with a confirmation tick.
18
- *
19
- * The tick is the point. A control that looks identical before and after leaves
20
- * the reader unsure whether it fired, and the usual response is to press it
21
- * again. Reverts after `CONFIRM`, and clears its timer on unmount so it cannot
22
- * set state on a component that is gone.
23
- */
24
- export declare function CopyButton({ value, label }: CopyButtonProps): import("react/jsx-runtime").JSX.Element;
25
12
  //# sourceMappingURL=Code.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Code.d.ts","sourceRoot":"","sources":["../../src/chat/Code.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAoBnE,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,oDAAoD;IACpD,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAiB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,SAAS,2CAoC9E;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,KAAc,EAAE,EAAE,eAAe,2CA2CpE"}
1
+ {"version":3,"file":"Code.d.ts","sourceRoot":"","sources":["../../src/chat/Code.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAkBtC,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,oDAAoD;IACpD,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAiB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,SAAS,2CAoC9E"}
package/dist/chat/Code.js CHANGED
@@ -13,11 +13,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  * plain text or its own highlighted nodes.
14
14
  */
15
15
  import { SizableText, XStack, YStack } from '@hanzo/gui';
16
- import { Check, Copy } from '@hanzogui/lucide-icons-2';
17
- import { useEffect, useRef, useState } from 'react';
18
- import { slot, tip } from '../backends/gui/slot.js';
19
- /** How long the copy control shows its confirmation, in ms. */
20
- const CONFIRM = 2000;
16
+ import { slot } from '../backends/gui/slot.js';
17
+ import { CopyButton } from '../product/CopyButton.js';
21
18
  /**
22
19
  * Monospace stack, applied through `style` rather than a `$mono` token.
23
20
  *
@@ -34,34 +31,4 @@ export function Code({ children, language = 'text', value, actions }) {
34
31
  const text = value ?? (typeof children === 'string' ? children : '');
35
32
  return (_jsxs(YStack, { ...slot('code'), width: "100%", rounded: "$4", borderWidth: 1, borderColor: "$borderColor", bg: "$color2", overflow: "hidden", children: [_jsxs(XStack, { items: "center", gap: "$1", px: "$3", py: "$1.5", borderBottomWidth: 1, borderColor: "$borderColor", children: [_jsx(SizableText, { size: "$1", style: MONO, color: "$color10", children: language }), _jsx(XStack, { flex: 1 }), actions, text ? _jsx(CopyButton, { value: text }) : null] }), _jsx(YStack, { px: "$3", py: "$2.5", children: _jsx(SizableText, { size: "$1", style: MONO, lineHeight: 20, children: children }) })] }));
36
33
  }
37
- /**
38
- * CopyButton — copy with a confirmation tick.
39
- *
40
- * The tick is the point. A control that looks identical before and after leaves
41
- * the reader unsure whether it fired, and the usual response is to press it
42
- * again. Reverts after `CONFIRM`, and clears its timer on unmount so it cannot
43
- * set state on a component that is gone.
44
- */
45
- export function CopyButton({ value, label = 'Copy' }) {
46
- const [copied, setCopied] = useState(false);
47
- const timer = useRef(undefined);
48
- useEffect(() => () => clearTimeout(timer.current), []);
49
- const copy = () => {
50
- // Optional-chained rather than assumed: `navigator.clipboard` is undefined
51
- // in insecure contexts and absent entirely on native, and these components
52
- // are meant to run on both.
53
- navigator?.clipboard
54
- ?.writeText(value)
55
- .then(() => {
56
- setCopied(true);
57
- clearTimeout(timer.current);
58
- timer.current = setTimeout(() => setCopied(false), CONFIRM);
59
- })
60
- .catch(() => {
61
- // A refused clipboard needs no toast — the missing tick already says it,
62
- // and an error dialog for a failed copy is louder than the failure.
63
- });
64
- };
65
- return (_jsx(XStack, { width: 24, height: 24, items: "center", justify: "center", rounded: "$2", cursor: "pointer", opacity: 0.7, onPress: copy, role: "button", tabIndex: 0, "aria-label": copied ? 'Copied' : label, ...tip(copied ? 'Copied' : label), hoverStyle: { bg: '$color4', opacity: 1 }, pressStyle: { bg: '$color5' }, children: copied ? _jsx(Check, { size: 14 }) : _jsx(Copy, { size: 14 }) }));
66
- }
67
34
  //# sourceMappingURL=Code.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Code.js","sourceRoot":"","sources":["../../src/chat/Code.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Code.js","sourceRoot":"","sources":["../../src/chat/Code.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAGxD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAElD;;;;;;;;GAQG;AACH,MAAM,IAAI,GAAG;IACX,UAAU,EAAE,wEAAwE;CAC5E,CAAA;AAYV,MAAM,UAAU,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,GAAG,MAAM,EAAE,KAAK,EAAE,OAAO,EAAa;IAC7E,MAAM,IAAI,GAAG,KAAK,IAAI,CAAC,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAEpE,OAAO,CACL,MAAC,MAAM,OACD,IAAI,CAAC,MAAM,CAAC,EAChB,KAAK,EAAC,MAAM,EACZ,OAAO,EAAC,IAAI,EACZ,WAAW,EAAE,CAAC,EACd,WAAW,EAAC,cAAc,EAC1B,EAAE,EAAC,SAAS,EACZ,QAAQ,EAAC,QAAQ,aAEjB,MAAC,MAAM,IACL,KAAK,EAAC,QAAQ,EACd,GAAG,EAAC,IAAI,EACR,EAAE,EAAC,IAAI,EACP,EAAE,EAAC,MAAM,EACT,iBAAiB,EAAE,CAAC,EACpB,WAAW,EAAC,cAAc,aAE1B,KAAC,WAAW,IAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAC,UAAU,YACjD,QAAQ,GACG,EACd,KAAC,MAAM,IAAC,IAAI,EAAE,CAAC,GAAI,EAClB,OAAO,EACP,IAAI,CAAC,CAAC,CAAC,KAAC,UAAU,IAAC,KAAK,EAAE,IAAI,GAAI,CAAC,CAAC,CAAC,IAAI,IACnC,EAET,KAAC,MAAM,IAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,MAAM,YACvB,KAAC,WAAW,IAAC,IAAI,EAAC,IAAI,EAAC,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,YAC/C,QAAQ,GACG,GACP,IACF,CACV,CAAA;AACH,CAAC"}
@@ -1,6 +1,6 @@
1
1
  'use client';"use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SourceChip = exports.Sources = exports.CopyButton = exports.Code = exports.Aside = exports.AsideToggle = exports.ShareButton = exports.HeaderButton = exports.Header = exports.SidebarUser = exports.SidebarFolder = exports.SidebarItem = exports.SidebarSection = exports.SidebarScroll = exports.SidebarNewChat = exports.SidebarIconButton = exports.SidebarHeader = exports.Sidebar = exports.SLACK = exports.pinned = exports.sends = exports.ready = exports.Thread = exports.Message = exports.ASK = exports.Composer = void 0;
3
+ exports.SourceChip = exports.Sources = exports.Code = exports.Aside = exports.AsideToggle = exports.ShareButton = exports.HeaderButton = exports.Header = exports.SidebarUser = exports.SidebarFolder = exports.SidebarItem = exports.SidebarSection = exports.SidebarScroll = exports.SidebarNewChat = exports.SidebarIconButton = exports.SidebarHeader = exports.Sidebar = exports.SLACK = exports.pinned = exports.sends = exports.ready = exports.Thread = exports.Message = exports.ASK = exports.Composer = void 0;
4
4
  /**
5
5
  * @hanzo/ui/chat — the one chat shell, on @hanzo/gui primitives.
6
6
  *
@@ -20,6 +20,12 @@ exports.SourceChip = exports.Sources = exports.CopyButton = exports.Code = expor
20
20
  *
21
21
  * The model picker is not here: it already ships at `@hanzo/ui/models`, and it
22
22
  * is not chat-specific.
23
+ *
24
+ * `CopyButton` is not here either, for the same reason and after the same
25
+ * mistake: it lived in `Code.tsx`, so the only way to reach it was
26
+ * `@hanzo/ui/chat`, and no one hunting for a copy button looks in a chat module.
27
+ * Six surfaces wrote their own instead. It now ships at `@hanzo/ui/product`;
28
+ * `Code` imports it from there.
23
29
  */
24
30
  var Composer_1 = require("./Composer.cjs");
25
31
  Object.defineProperty(exports, "Composer", { enumerable: true, get: function () { return Composer_1.Composer; } });
@@ -52,7 +58,6 @@ Object.defineProperty(exports, "AsideToggle", { enumerable: true, get: function
52
58
  Object.defineProperty(exports, "Aside", { enumerable: true, get: function () { return Header_1.Aside; } });
53
59
  var Code_1 = require("./Code.cjs");
54
60
  Object.defineProperty(exports, "Code", { enumerable: true, get: function () { return Code_1.Code; } });
55
- Object.defineProperty(exports, "CopyButton", { enumerable: true, get: function () { return Code_1.CopyButton; } });
56
61
  var Sources_1 = require("./Sources.cjs");
57
62
  Object.defineProperty(exports, "Sources", { enumerable: true, get: function () { return Sources_1.Sources; } });
58
63
  Object.defineProperty(exports, "SourceChip", { enumerable: true, get: function () { return Sources_1.SourceChip; } });
@@ -17,6 +17,12 @@
17
17
  *
18
18
  * The model picker is not here: it already ships at `@hanzo/ui/models`, and it
19
19
  * is not chat-specific.
20
+ *
21
+ * `CopyButton` is not here either, for the same reason and after the same
22
+ * mistake: it lived in `Code.tsx`, so the only way to reach it was
23
+ * `@hanzo/ui/chat`, and no one hunting for a copy button looks in a chat module.
24
+ * Six surfaces wrote their own instead. It now ships at `@hanzo/ui/product`;
25
+ * `Code` imports it from there.
20
26
  */
21
27
  export { Composer, ASK, type ComposerProps } from './Composer.js';
22
28
  export { Message, type MessageProps, type Role } from './Message.js';
@@ -25,6 +31,6 @@ export { ready, sends, type Mods } from './send.js';
25
31
  export { pinned, SLACK, type Track } from './stick.js';
26
32
  export { Sidebar, SidebarHeader, SidebarIconButton, SidebarNewChat, SidebarScroll, SidebarSection, SidebarItem, SidebarFolder, SidebarUser, type SidebarProps, type SidebarHeaderProps, type SidebarIconButtonProps, type SidebarNewChatProps, type SidebarSectionProps, type SidebarItemProps, type SidebarFolderProps, type SidebarUserProps, } from './Sidebar.js';
27
33
  export { Header, HeaderButton, ShareButton, AsideToggle, Aside, type HeaderProps, type HeaderButtonProps, type ShareButtonProps, type AsideToggleProps, type AsideProps, } from './Header.js';
28
- export { Code, CopyButton, type CodeProps, type CopyButtonProps } from './Code.js';
34
+ export { Code, type CodeProps } from './Code.js';
29
35
  export { Sources, SourceChip, type Source, type SourcesProps, type SourceChipProps, } from './Sources.js';
30
36
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,IAAI,EAAE,MAAM,WAAW,CAAA;AACjE,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA;AAEnD,OAAO,EACL,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,EACX,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,MAAM,EACN,YAAY,EACZ,WAAW,EACX,WAAW,EACX,KAAK,EACL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,UAAU,GAChB,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,QAAQ,CAAA;AAE/E,OAAO,EACL,OAAO,EACP,UAAU,EACV,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,eAAe,GACrB,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,IAAI,EAAE,MAAM,WAAW,CAAA;AACjE,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA;AAEnD,OAAO,EACL,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,EACX,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,MAAM,EACN,YAAY,EACZ,WAAW,EACX,WAAW,EACX,KAAK,EACL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,UAAU,GAChB,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAA;AAE7C,OAAO,EACL,OAAO,EACP,UAAU,EACV,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,eAAe,GACrB,MAAM,WAAW,CAAA"}
@@ -17,6 +17,12 @@
17
17
  *
18
18
  * The model picker is not here: it already ships at `@hanzo/ui/models`, and it
19
19
  * is not chat-specific.
20
+ *
21
+ * `CopyButton` is not here either, for the same reason and after the same
22
+ * mistake: it lived in `Code.tsx`, so the only way to reach it was
23
+ * `@hanzo/ui/chat`, and no one hunting for a copy button looks in a chat module.
24
+ * Six surfaces wrote their own instead. It now ships at `@hanzo/ui/product`;
25
+ * `Code` imports it from there.
20
26
  */
21
27
  export { Composer, ASK } from './Composer.js';
22
28
  export { Message } from './Message.js';
@@ -25,6 +31,6 @@ export { ready, sends } from './send.js';
25
31
  export { pinned, SLACK } from './stick.js';
26
32
  export { Sidebar, SidebarHeader, SidebarIconButton, SidebarNewChat, SidebarScroll, SidebarSection, SidebarItem, SidebarFolder, SidebarUser, } from './Sidebar.js';
27
33
  export { Header, HeaderButton, ShareButton, AsideToggle, Aside, } from './Header.js';
28
- export { Code, CopyButton } from './Code.js';
34
+ export { Code } from './Code.js';
29
35
  export { Sources, SourceChip, } from './Sources.js';
30
36
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAsB,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,OAAO,EAAgC,MAAM,WAAW,CAAA;AACjE,OAAO,EAAE,MAAM,EAAoB,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAa,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAc,MAAM,SAAS,CAAA;AAEnD,OAAO,EACL,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,GASZ,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,MAAM,EACN,YAAY,EACZ,WAAW,EACX,WAAW,EACX,KAAK,GAMN,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAwC,MAAM,QAAQ,CAAA;AAE/E,OAAO,EACL,OAAO,EACP,UAAU,GAIX,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/chat/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAsB,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAE,OAAO,EAAgC,MAAM,WAAW,CAAA;AACjE,OAAO,EAAE,MAAM,EAAoB,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAa,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAc,MAAM,SAAS,CAAA;AAEnD,OAAO,EACL,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,WAAW,GASZ,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,MAAM,EACN,YAAY,EACZ,WAAW,EACX,WAAW,EACX,KAAK,GAMN,MAAM,UAAU,CAAA;AAEjB,OAAO,EAAE,IAAI,EAAkB,MAAM,QAAQ,CAAA;AAE7C,OAAO,EACL,OAAO,EACP,UAAU,GAIX,MAAM,WAAW,CAAA"}
@@ -18,7 +18,7 @@ const react_1 = require("react");
18
18
  const gui_1 = require("@hanzo/gui");
19
19
  const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
20
20
  const BrandMark_1 = require("./BrandMark.cjs");
21
- const ThemeToggle_1 = require("./ThemeToggle.cjs");
21
+ const UserMenu_1 = require("./UserMenu.cjs");
22
22
  const surfaces_data_1 = require("./surfaces.data.cjs");
23
23
  /** The per-surface glyph — keyed by `Surface.id`, so each surface reads distinctly. */
24
24
  const SURFACE_ICON = {
@@ -34,12 +34,8 @@ const openHref = (href) => {
34
34
  if (typeof window !== 'undefined')
35
35
  window.open(href, '_blank', 'noopener');
36
36
  };
37
- function MenuRow({ icon, label, onPress }) {
38
- return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { onPress: onPress, cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$2", rounded: "$3", hoverStyle: { bg: '$color5' }, children: [icon, (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", color: "$color12", children: label })] }));
39
- }
40
37
  function AppHeader({ brand, wordmark = 'Hanzo', onBrand, org, children, current, surfaces, open, user, menu, theme, onProfile, onTeam, onBilling, onSignOut, }) {
41
38
  const [appsOpen, setAppsOpen] = (0, react_1.useState)(false);
42
- const [menuOpen, setMenuOpen] = (0, react_1.useState)(false);
43
39
  const items = surfaces ?? (0, surfaces_data_1.otherSurfaces)(current);
44
40
  const launch = (s) => {
45
41
  setAppsOpen(false);
@@ -51,5 +47,11 @@ function AppHeader({ brand, wordmark = 'Hanzo', onBrand, org, children, current,
51
47
  return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$2", px: "$3", height: 52, borderBottomWidth: 1, borderColor: "$borderColor", bg: "$background", children: [(0, jsx_runtime_1.jsx)(gui_1.XStack, { items: "center", cursor: onBrand ? 'pointer' : undefined, onPress: onBrand, children: brand ?? (0, jsx_runtime_1.jsx)(BrandMark_1.BrandMark, { wordmark: wordmark }) }), org ? ((0, jsx_runtime_1.jsx)(gui_1.XStack, { items: "center", minW: 0, children: org })) : null, (0, jsx_runtime_1.jsx)(gui_1.XStack, { flex: 1, items: "center", minW: 0, children: children }), items.length > 0 ? ((0, jsx_runtime_1.jsxs)(gui_1.Popover, { open: appsOpen, onOpenChange: setAppsOpen, placement: "bottom-end", children: [(0, jsx_runtime_1.jsx)(gui_1.Popover.Trigger, { asChild: true, children: (0, jsx_runtime_1.jsx)(gui_1.Button, { size: "$2", chromeless: true, icon: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Grip, { size: 16 }), "aria-label": "Apps" }) }), (0, jsx_runtime_1.jsx)(gui_1.Popover.Content, { bordered: true, elevate: true, p: "$2", width: 230, bg: "$color2", borderColor: "$borderColor", children: (0, jsx_runtime_1.jsx)(gui_1.YStack, { gap: "$1", children: items.map((s) => {
52
48
  const Icon = SURFACE_ICON[s.id];
53
49
  return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { onPress: () => launch(s), cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$2", rounded: "$3", hoverStyle: { bg: '$color5' }, children: [(0, jsx_runtime_1.jsx)(Icon, { size: 16 }), (0, jsx_runtime_1.jsx)(gui_1.Text, { flex: 1, fontSize: "$2", fontWeight: "600", color: "$color12", children: s.label }), s.hint ? ((0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$1", color: "$color10", children: s.hint })) : null] }, s.id));
54
- }) }) })] })) : null, (0, jsx_runtime_1.jsxs)(gui_1.Popover, { open: menuOpen, onOpenChange: setMenuOpen, placement: "bottom-end", children: [(0, jsx_runtime_1.jsx)(gui_1.Popover.Trigger, { asChild: true, children: (0, jsx_runtime_1.jsx)(gui_1.Button, { size: "$2", chromeless: true, icon: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.UserRound, { size: 16 }), "aria-label": "Account", children: user ? ((0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", color: "$color12", numberOfLines: 1, maxW: 140, children: user })) : null }) }), (0, jsx_runtime_1.jsx)(gui_1.Popover.Content, { bordered: true, elevate: true, p: "$2", width: 220, bg: "$color2", borderColor: "$borderColor", children: menu ?? ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { gap: "$1", children: [onProfile ? (0, jsx_runtime_1.jsx)(MenuRow, { icon: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.UserRound, { size: 15 }), label: "Profile", onPress: () => (setMenuOpen(false), onProfile()) }) : null, theme !== null ? ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$2.5", px: "$2", py: "$1", rounded: "$3", children: [(0, jsx_runtime_1.jsx)(gui_1.Text, { flex: 1, fontSize: "$2", color: "$color12", children: "Theme" }), theme ?? (0, jsx_runtime_1.jsx)(ThemeToggle_1.ThemeToggle, {})] })) : null, onTeam ? (0, jsx_runtime_1.jsx)(MenuRow, { icon: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Settings2, { size: 15 }), label: "Team settings", onPress: () => (setMenuOpen(false), onTeam()) }) : null, onBilling ? (0, jsx_runtime_1.jsx)(MenuRow, { icon: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.CreditCard, { size: 15 }), label: "Billing", onPress: () => (setMenuOpen(false), onBilling()) }) : null, onSignOut ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(gui_1.Separator, { borderColor: "$borderColor", my: "$1" }), (0, jsx_runtime_1.jsx)(MenuRow, { icon: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.LogOut, { size: 15 }), label: "Sign out", onPress: () => (setMenuOpen(false), onSignOut()) })] })) : null] })) })] })] }));
50
+ }) }) })] })) : null, (0, jsx_runtime_1.jsx)(UserMenu_1.UserMenu, { name: user, groups: [
51
+ [
52
+ onProfile ? { id: 'profile', label: 'Profile', icon: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.UserRound, { size: 15 }), onPress: onProfile } : null,
53
+ onTeam ? { id: 'team', label: 'Team settings', icon: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Settings2, { size: 15 }), onPress: onTeam } : null,
54
+ onBilling ? { id: 'billing', label: 'Billing', icon: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.CreditCard, { size: 15 }), onPress: onBilling } : null,
55
+ ].filter((r) => r !== null),
56
+ ], theme: theme, onSignOut: onSignOut, height: 36, children: menu })] }));
55
57
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AppHeader.d.ts","sourceRoot":"","sources":["../../src/product/AppHeader.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAMhD,OAAO,EAAiB,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAA;AA4B7E,MAAM,MAAM,cAAc,GAAG;IAC3B,4DAA4D;IAC5D,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,0EAA0E;IAC1E,GAAG,CAAC,EAAE,SAAS,CAAA;IACf,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,qFAAqF;IACrF,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;IACpB,wDAAwD;IACxD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IACjC,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,+CAA+C;IAC/C,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB,CAAA;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAkB,EAClB,OAAO,EACP,GAAG,EACH,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,SAAS,EACT,MAAM,EACN,SAAS,EACT,SAAS,GACV,EAAE,cAAc,2CA0FhB"}
1
+ {"version":3,"file":"AppHeader.d.ts","sourceRoot":"","sources":["../../src/product/AppHeader.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAMhD,OAAO,EAAiB,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAiB7E,MAAM,MAAM,cAAc,GAAG;IAC3B,4DAA4D;IAC5D,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,0EAA0E;IAC1E,GAAG,CAAC,EAAE,SAAS,CAAA;IACf,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,qFAAqF;IACrF,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;IACpB,wDAAwD;IACxD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IACjC,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,+CAA+C;IAC/C,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB,CAAA;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAkB,EAClB,OAAO,EACP,GAAG,EACH,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,SAAS,EACT,MAAM,EACN,SAAS,EACT,SAAS,GACV,EAAE,cAAc,2CAwEhB"}
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  /**
4
4
  * AppHeader — the shared shell header every Hanzo surface renders: the brand
5
5
  * mark top-left (from @hanzo/logo, white-label via `wordmark`/`brand`), an
@@ -12,10 +12,10 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
12
12
  * flex + truncation, the wordmark collapse is the brand motion itself.
13
13
  */
14
14
  import { useState } from 'react';
15
- import { Button, Popover, Separator, Text, XStack, YStack } from '@hanzo/gui';
16
- import { AppWindow, Bot, CreditCard, Grip, LayoutGrid, LogOut, MessageCircle, Settings2, Sparkles, UserRound, Users } from '@hanzogui/lucide-icons-2';
15
+ import { Button, Popover, Text, XStack, YStack } from '@hanzo/gui';
16
+ import { AppWindow, Bot, CreditCard, Grip, LayoutGrid, MessageCircle, Settings2, Sparkles, UserRound, Users } from '@hanzogui/lucide-icons-2';
17
17
  import { BrandMark } from './BrandMark.js';
18
- import { ThemeToggle } from './ThemeToggle.js';
18
+ import { UserMenu } from './UserMenu.js';
19
19
  import { otherSurfaces } from './surfaces.data.js';
20
20
  /** The per-surface glyph — keyed by `Surface.id`, so each surface reads distinctly. */
21
21
  const SURFACE_ICON = {
@@ -31,12 +31,8 @@ const openHref = (href) => {
31
31
  if (typeof window !== 'undefined')
32
32
  window.open(href, '_blank', 'noopener');
33
33
  };
34
- function MenuRow({ icon, label, onPress }) {
35
- return (_jsxs(XStack, { onPress: onPress, cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$2", rounded: "$3", hoverStyle: { bg: '$color5' }, children: [icon, _jsx(Text, { fontSize: "$2", color: "$color12", children: label })] }));
36
- }
37
34
  export function AppHeader({ brand, wordmark = 'Hanzo', onBrand, org, children, current, surfaces, open, user, menu, theme, onProfile, onTeam, onBilling, onSignOut, }) {
38
35
  const [appsOpen, setAppsOpen] = useState(false);
39
- const [menuOpen, setMenuOpen] = useState(false);
40
36
  const items = surfaces ?? otherSurfaces(current);
41
37
  const launch = (s) => {
42
38
  setAppsOpen(false);
@@ -48,6 +44,12 @@ export function AppHeader({ brand, wordmark = 'Hanzo', onBrand, org, children, c
48
44
  return (_jsxs(XStack, { items: "center", gap: "$2", px: "$3", height: 52, borderBottomWidth: 1, borderColor: "$borderColor", bg: "$background", children: [_jsx(XStack, { items: "center", cursor: onBrand ? 'pointer' : undefined, onPress: onBrand, children: brand ?? _jsx(BrandMark, { wordmark: wordmark }) }), org ? (_jsx(XStack, { items: "center", minW: 0, children: org })) : null, _jsx(XStack, { flex: 1, items: "center", minW: 0, children: children }), items.length > 0 ? (_jsxs(Popover, { open: appsOpen, onOpenChange: setAppsOpen, placement: "bottom-end", children: [_jsx(Popover.Trigger, { asChild: true, children: _jsx(Button, { size: "$2", chromeless: true, icon: _jsx(Grip, { size: 16 }), "aria-label": "Apps" }) }), _jsx(Popover.Content, { bordered: true, elevate: true, p: "$2", width: 230, bg: "$color2", borderColor: "$borderColor", children: _jsx(YStack, { gap: "$1", children: items.map((s) => {
49
45
  const Icon = SURFACE_ICON[s.id];
50
46
  return (_jsxs(XStack, { onPress: () => launch(s), cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$2", rounded: "$3", hoverStyle: { bg: '$color5' }, children: [_jsx(Icon, { size: 16 }), _jsx(Text, { flex: 1, fontSize: "$2", fontWeight: "600", color: "$color12", children: s.label }), s.hint ? (_jsx(Text, { fontSize: "$1", color: "$color10", children: s.hint })) : null] }, s.id));
51
- }) }) })] })) : null, _jsxs(Popover, { open: menuOpen, onOpenChange: setMenuOpen, placement: "bottom-end", children: [_jsx(Popover.Trigger, { asChild: true, children: _jsx(Button, { size: "$2", chromeless: true, icon: _jsx(UserRound, { size: 16 }), "aria-label": "Account", children: user ? (_jsx(Text, { fontSize: "$2", color: "$color12", numberOfLines: 1, maxW: 140, children: user })) : null }) }), _jsx(Popover.Content, { bordered: true, elevate: true, p: "$2", width: 220, bg: "$color2", borderColor: "$borderColor", children: menu ?? (_jsxs(YStack, { gap: "$1", children: [onProfile ? _jsx(MenuRow, { icon: _jsx(UserRound, { size: 15 }), label: "Profile", onPress: () => (setMenuOpen(false), onProfile()) }) : null, theme !== null ? (_jsxs(XStack, { items: "center", gap: "$2.5", px: "$2", py: "$1", rounded: "$3", children: [_jsx(Text, { flex: 1, fontSize: "$2", color: "$color12", children: "Theme" }), theme ?? _jsx(ThemeToggle, {})] })) : null, onTeam ? _jsx(MenuRow, { icon: _jsx(Settings2, { size: 15 }), label: "Team settings", onPress: () => (setMenuOpen(false), onTeam()) }) : null, onBilling ? _jsx(MenuRow, { icon: _jsx(CreditCard, { size: 15 }), label: "Billing", onPress: () => (setMenuOpen(false), onBilling()) }) : null, onSignOut ? (_jsxs(_Fragment, { children: [_jsx(Separator, { borderColor: "$borderColor", my: "$1" }), _jsx(MenuRow, { icon: _jsx(LogOut, { size: 15 }), label: "Sign out", onPress: () => (setMenuOpen(false), onSignOut()) })] })) : null] })) })] })] }));
47
+ }) }) })] })) : null, _jsx(UserMenu, { name: user, groups: [
48
+ [
49
+ onProfile ? { id: 'profile', label: 'Profile', icon: _jsx(UserRound, { size: 15 }), onPress: onProfile } : null,
50
+ onTeam ? { id: 'team', label: 'Team settings', icon: _jsx(Settings2, { size: 15 }), onPress: onTeam } : null,
51
+ onBilling ? { id: 'billing', label: 'Billing', icon: _jsx(CreditCard, { size: 15 }), onPress: onBilling } : null,
52
+ ].filter((r) => r !== null),
53
+ ], theme: theme, onSignOut: onSignOut, height: 36, children: menu })] }));
52
54
  }
53
55
  //# sourceMappingURL=AppHeader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppHeader.js","sourceRoot":"","sources":["../../src/product/AppHeader.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AppHeader.js","sourceRoot":"","sources":["../../src/product/AppHeader.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.CopyButton = CopyButton;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ /**
7
+ * CopyButton — copy with a confirmation tick.
8
+ *
9
+ * The tick is the point. A control that looks identical before and after leaves
10
+ * the reader unsure whether it fired, and the usual response is to press it
11
+ * again. Reverts after `CONFIRM`, and clears its timer on unmount so it cannot
12
+ * set state on a component that is gone.
13
+ *
14
+ * It lived inside `chat/Code.tsx` and was reachable only as `@hanzo/ui/chat`.
15
+ * Nobody looks in a chat module for a copy button, so every surface wrote its
16
+ * own — an API key here, a deposit address there, a referral link, a wire
17
+ * instruction — each with its own confirmation window, or none. Copying text is
18
+ * not a chat idea; it belongs to the product layer, and `Code` now imports it
19
+ * from here rather than owning it.
20
+ */
21
+ const react_1 = require("react");
22
+ const gui_1 = require("@hanzo/gui");
23
+ const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
24
+ const slot_1 = require("../backends/gui/slot.cjs");
25
+ const instrument_1 = require("./instrument.cjs");
26
+ /** How long the control shows its confirmation, in ms. */
27
+ const CONFIRM = 2000;
28
+ function CopyButton({ value, label = 'Copy', size = 24, id }) {
29
+ const [copied, setCopied] = (0, react_1.useState)(false);
30
+ const timer = (0, react_1.useRef)(undefined);
31
+ const track = (0, instrument_1.useEmit)();
32
+ (0, react_1.useEffect)(() => () => clearTimeout(timer.current), []);
33
+ const copy = () => {
34
+ // Optional-chained rather than assumed: `navigator.clipboard` is undefined
35
+ // in insecure contexts and absent entirely on native, and these components
36
+ // are meant to run on both.
37
+ navigator?.clipboard
38
+ ?.writeText(value)
39
+ .then(() => {
40
+ // The LENGTH, never the text — a copied value is a password as often as
41
+ // it is a URL.
42
+ track({ component: 'CopyButton', action: 'click', id, value: value.length });
43
+ setCopied(true);
44
+ clearTimeout(timer.current);
45
+ timer.current = setTimeout(() => setCopied(false), CONFIRM);
46
+ })
47
+ .catch(() => {
48
+ // A refused clipboard needs no toast — the missing tick already says it,
49
+ // and an error dialog for a failed copy is louder than the failure.
50
+ track({ component: 'CopyButton', action: 'error', id });
51
+ });
52
+ };
53
+ return ((0, jsx_runtime_1.jsx)(gui_1.XStack, { width: size, height: size, items: "center", justify: "center", rounded: "$2", cursor: "pointer", opacity: 0.7, onPress: copy, role: "button", tabIndex: 0, "aria-label": copied ? 'Copied' : label, ...(0, slot_1.tip)(copied ? 'Copied' : label), hoverStyle: { bg: '$color4', opacity: 1 }, pressStyle: { bg: '$color5' }, children: copied ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Check, { size: Math.round(size * 0.58) }) : (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Copy, { size: Math.round(size * 0.58) }) }));
54
+ }