@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
@@ -0,0 +1,72 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.GAP = void 0;
5
+ exports.pages = pages;
6
+ exports.Pagination = Pagination;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ /**
9
+ * Pagination — page N of M, and the way to the others.
10
+ *
11
+ * Four implementations across the fleet (chat, the console's observability
12
+ * pager, and billing twice — in two spellings, in one repo), each with its own
13
+ * rule for what happens when there are eighty pages. `pages` is that rule,
14
+ * written once and testable without a browser: a fixed-width run of page numbers
15
+ * around the current one, with ellipses standing in for what was skipped and the
16
+ * first and last page always reachable.
17
+ *
18
+ * Fixed width is the requirement. A control that grows with the page count
19
+ * reflows the row it sits in every time you page, which is how a "next" button
20
+ * ends up under the cursor that was pressing "previous".
21
+ */
22
+ const gui_1 = require("@hanzo/gui");
23
+ const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
24
+ const instrument_1 = require("./instrument.cjs");
25
+ /** A gap in the run. Rendered as an ellipsis; never selectable. */
26
+ exports.GAP = '…';
27
+ /**
28
+ * The page numbers to show for `page` of `count`, 1-based.
29
+ *
30
+ * `around` is how many neighbours flank the current page (default 1 → at most
31
+ * 7 slots: first, gap, p-1, p, p+1, gap, last). Returns every page when they
32
+ * all fit, so a short list never grows an ellipsis it does not need.
33
+ */
34
+ function pages(page, count, around = 1) {
35
+ if (count <= 0)
36
+ return [];
37
+ const width = around * 2 + 5; // first + gap + run + gap + last
38
+ if (count <= width)
39
+ return Array.from({ length: count }, (_, i) => i + 1);
40
+ const current = Math.min(Math.max(page, 1), count);
41
+ // First and last are always present, so the middle carries `width - 2` slots
42
+ // and each end that needs no ellipsis spends that slot on another page
43
+ // instead. Solving for the run that way is what keeps the total constant;
44
+ // clamping the run with Math.max/min alone lets it shrink near the edges, and
45
+ // then the control changes width as you page.
46
+ const middle = width - 2;
47
+ const nearStart = current <= around + 2;
48
+ const nearEnd = current >= count - around - 1;
49
+ const start = nearStart ? 2 : nearEnd ? count - middle + 1 : current - around;
50
+ const end = nearStart ? middle : nearEnd ? count - 1 : current + around;
51
+ const out = [1];
52
+ if (!nearStart)
53
+ out.push(exports.GAP);
54
+ for (let p = start; p <= end; p++)
55
+ out.push(p);
56
+ if (!nearEnd)
57
+ out.push(exports.GAP);
58
+ out.push(count);
59
+ return out;
60
+ }
61
+ function Pagination({ page, count, onChange, around = 1 }) {
62
+ const track = (0, instrument_1.useEmit)();
63
+ if (count <= 1)
64
+ return null;
65
+ const go = (to) => {
66
+ if (to === page || to < 1 || to > count)
67
+ return;
68
+ track({ component: 'Pagination', action: 'select', value: to });
69
+ onChange(to);
70
+ };
71
+ return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", justify: "center", gap: "$1", flexWrap: "wrap", children: [(0, jsx_runtime_1.jsx)(gui_1.Button, { size: "$2", chromeless: true, icon: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronLeft, { size: 15 }), onPress: () => go(page - 1), disabled: page <= 1, "aria-label": "Previous page" }), pages(page, count, around).map((slot, i) => slot === exports.GAP ? ((0, jsx_runtime_1.jsx)(gui_1.Text, { px: "$1.5", fontSize: "$2", color: "$color10", "aria-hidden": true, children: exports.GAP }, `gap-${i}`)) : ((0, jsx_runtime_1.jsx)(gui_1.Button, { size: "$2", chromeless: slot !== page, onPress: () => go(slot), "aria-label": `Page ${slot}`, "aria-current": slot === page ? 'page' : undefined, bg: slot === page ? '$color4' : undefined, children: String(slot) }, slot))), (0, jsx_runtime_1.jsx)(gui_1.Button, { size: "$2", chromeless: true, icon: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronRight, { size: 15 }), onPress: () => go(page + 1), disabled: page >= count, "aria-label": "Next page" })] }));
72
+ }
@@ -0,0 +1,21 @@
1
+ /** A gap in the run. Rendered as an ellipsis; never selectable. */
2
+ export declare const GAP: "\u2026";
3
+ /**
4
+ * The page numbers to show for `page` of `count`, 1-based.
5
+ *
6
+ * `around` is how many neighbours flank the current page (default 1 → at most
7
+ * 7 slots: first, gap, p-1, p, p+1, gap, last). Returns every page when they
8
+ * all fit, so a short list never grows an ellipsis it does not need.
9
+ */
10
+ export declare function pages(page: number, count: number, around?: number): (number | typeof GAP)[];
11
+ export type PaginationProps = {
12
+ /** Current page, 1-based. */
13
+ page: number;
14
+ /** Total pages. 1 or 0 renders nothing — there is nowhere to go. */
15
+ count: number;
16
+ onChange: (page: number) => void;
17
+ /** Neighbours flanking the current page. Default 1. */
18
+ around?: number;
19
+ };
20
+ export declare function Pagination({ page, count, onChange, around }: PaginationProps): import("react/jsx-runtime").JSX.Element | null;
21
+ //# sourceMappingURL=Pagination.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../src/product/Pagination.tsx"],"names":[],"mappings":"AAqBA,mEAAmE;AACnE,eAAO,MAAM,GAAG,EAAG,QAAY,CAAA;AAE/B;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,CAAC,MAAM,GAAG,OAAO,GAAG,CAAC,EAAE,CAwBtF;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAU,EAAE,EAAE,eAAe,kDAiDhF"}
@@ -0,0 +1,68 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * Pagination — page N of M, and the way to the others.
5
+ *
6
+ * Four implementations across the fleet (chat, the console's observability
7
+ * pager, and billing twice — in two spellings, in one repo), each with its own
8
+ * rule for what happens when there are eighty pages. `pages` is that rule,
9
+ * written once and testable without a browser: a fixed-width run of page numbers
10
+ * around the current one, with ellipses standing in for what was skipped and the
11
+ * first and last page always reachable.
12
+ *
13
+ * Fixed width is the requirement. A control that grows with the page count
14
+ * reflows the row it sits in every time you page, which is how a "next" button
15
+ * ends up under the cursor that was pressing "previous".
16
+ */
17
+ import { Button, Text, XStack } from '@hanzo/gui';
18
+ import { ChevronLeft, ChevronRight } from '@hanzogui/lucide-icons-2';
19
+ import { useEmit } from './instrument.js';
20
+ /** A gap in the run. Rendered as an ellipsis; never selectable. */
21
+ export const GAP = '…';
22
+ /**
23
+ * The page numbers to show for `page` of `count`, 1-based.
24
+ *
25
+ * `around` is how many neighbours flank the current page (default 1 → at most
26
+ * 7 slots: first, gap, p-1, p, p+1, gap, last). Returns every page when they
27
+ * all fit, so a short list never grows an ellipsis it does not need.
28
+ */
29
+ export function pages(page, count, around = 1) {
30
+ if (count <= 0)
31
+ return [];
32
+ const width = around * 2 + 5; // first + gap + run + gap + last
33
+ if (count <= width)
34
+ return Array.from({ length: count }, (_, i) => i + 1);
35
+ const current = Math.min(Math.max(page, 1), count);
36
+ // First and last are always present, so the middle carries `width - 2` slots
37
+ // and each end that needs no ellipsis spends that slot on another page
38
+ // instead. Solving for the run that way is what keeps the total constant;
39
+ // clamping the run with Math.max/min alone lets it shrink near the edges, and
40
+ // then the control changes width as you page.
41
+ const middle = width - 2;
42
+ const nearStart = current <= around + 2;
43
+ const nearEnd = current >= count - around - 1;
44
+ const start = nearStart ? 2 : nearEnd ? count - middle + 1 : current - around;
45
+ const end = nearStart ? middle : nearEnd ? count - 1 : current + around;
46
+ const out = [1];
47
+ if (!nearStart)
48
+ out.push(GAP);
49
+ for (let p = start; p <= end; p++)
50
+ out.push(p);
51
+ if (!nearEnd)
52
+ out.push(GAP);
53
+ out.push(count);
54
+ return out;
55
+ }
56
+ export function Pagination({ page, count, onChange, around = 1 }) {
57
+ const track = useEmit();
58
+ if (count <= 1)
59
+ return null;
60
+ const go = (to) => {
61
+ if (to === page || to < 1 || to > count)
62
+ return;
63
+ track({ component: 'Pagination', action: 'select', value: to });
64
+ onChange(to);
65
+ };
66
+ return (_jsxs(XStack, { items: "center", justify: "center", gap: "$1", flexWrap: "wrap", children: [_jsx(Button, { size: "$2", chromeless: true, icon: _jsx(ChevronLeft, { size: 15 }), onPress: () => go(page - 1), disabled: page <= 1, "aria-label": "Previous page" }), pages(page, count, around).map((slot, i) => slot === GAP ? (_jsx(Text, { px: "$1.5", fontSize: "$2", color: "$color10", "aria-hidden": true, children: GAP }, `gap-${i}`)) : (_jsx(Button, { size: "$2", chromeless: slot !== page, onPress: () => go(slot), "aria-label": `Page ${slot}`, "aria-current": slot === page ? 'page' : undefined, bg: slot === page ? '$color4' : undefined, children: String(slot) }, slot))), _jsx(Button, { size: "$2", chromeless: true, icon: _jsx(ChevronRight, { size: 15 }), onPress: () => go(page + 1), disabled: page >= count, "aria-label": "Next page" })] }));
67
+ }
68
+ //# sourceMappingURL=Pagination.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Pagination.js","sourceRoot":"","sources":["../../src/product/Pagination.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.masked = void 0;
5
+ exports.SecretInput = SecretInput;
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ /**
8
+ * SecretInput — a secret you can check, copy, and not leak over someone's
9
+ * shoulder.
10
+ *
11
+ * An API key, a token, a webhook signing secret. Masked by default, revealed
12
+ * deliberately, and copyable without ever being revealed — which is the point:
13
+ * the usual reason a person unmasks a key is to select it by hand, so a copy
14
+ * control that works while masked removes the reason to show it at all.
15
+ *
16
+ * Copying is `CopyButton`, not a second implementation. This component owns
17
+ * exactly one thing the others do not: the reveal.
18
+ *
19
+ * Nothing here reports the secret. The analytics event carries the LENGTH and
20
+ * whether it was revealed — never a character of the value, and it is never
21
+ * written to the console, which is where the previous implementation sent its
22
+ * clipboard failures.
23
+ */
24
+ const react_1 = require("react");
25
+ const gui_1 = require("@hanzo/gui");
26
+ const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
27
+ const slot_1 = require("../backends/gui/slot.cjs");
28
+ const CopyButton_1 = require("./CopyButton.cjs");
29
+ const instrument_1 = require("./instrument.cjs");
30
+ /**
31
+ * Masking, on both platforms.
32
+ *
33
+ * `secureTextEntry` is React Native's spelling and gui DROPS it on web — an
34
+ * input carrying only that prop renders the secret in plain text, which is the
35
+ * exact opposite of what the caller asked for. `type="password"` is the web
36
+ * spelling and gui forwards it, being an unrecognised prop. Native ignores
37
+ * `type` for the same reason. So masking needs BOTH names, and neither alone is
38
+ * safe. `readOnly` is the same story: `editable={false}` is dropped on web.
39
+ */
40
+ const masked = (on) => (on ? { secureTextEntry: true, type: 'password' } : { secureTextEntry: false, type: 'text' });
41
+ exports.masked = masked;
42
+ function SecretInput({ value, onChange, placeholder, disabled, copy = true, id, }) {
43
+ const [shown, setShown] = (0, react_1.useState)(false);
44
+ const track = (0, instrument_1.useEmit)();
45
+ const toggle = () => {
46
+ track({ component: 'SecretInput', action: shown ? 'close' : 'open', id });
47
+ setShown((s) => !s);
48
+ };
49
+ return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$1", px: "$2", rounded: "$3", borderWidth: 1, borderColor: "$borderColor", bg: "$background", opacity: disabled ? 0.5 : 1, children: [(0, jsx_runtime_1.jsx)(gui_1.Input, { flex: 1, minW: 0, borderWidth: 0, bg: "transparent", value: value, onChangeText: onChange
50
+ ? (v) => {
51
+ track({ component: 'SecretInput', action: 'change', id, value: v.length });
52
+ onChange(v);
53
+ }
54
+ : undefined,
55
+ // No handler means the caller is displaying a minted secret, not
56
+ // collecting one; a field that accepts keystrokes it then discards
57
+ // reads as broken. `readOnly`, not `editable` — see `masked`.
58
+ readOnly: !onChange, disabled: disabled, ...(0, exports.masked)(!shown), placeholder: placeholder, autoCapitalize: "none", autoCorrect: false, spellCheck: false }), copy && value ? (0, jsx_runtime_1.jsx)(CopyButton_1.CopyButton, { value: value, label: "Copy secret", id: id }) : null, (0, jsx_runtime_1.jsx)(gui_1.XStack, { width: 24, height: 24, items: "center", justify: "center", rounded: "$2", cursor: disabled ? 'not-allowed' : 'pointer', opacity: 0.7, onPress: disabled ? undefined : toggle, role: "button", tabIndex: 0, "aria-label": shown ? 'Hide secret' : 'Show secret', ...(0, slot_1.tip)(shown ? 'Hide' : 'Show'), hoverStyle: disabled ? undefined : { bg: '$color4', opacity: 1 }, pressStyle: disabled ? undefined : { bg: '$color5' }, children: shown ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.EyeOff, { size: 14 }) : (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Eye, { size: 14 }) })] }));
59
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Masking, on both platforms.
3
+ *
4
+ * `secureTextEntry` is React Native's spelling and gui DROPS it on web — an
5
+ * input carrying only that prop renders the secret in plain text, which is the
6
+ * exact opposite of what the caller asked for. `type="password"` is the web
7
+ * spelling and gui forwards it, being an unrecognised prop. Native ignores
8
+ * `type` for the same reason. So masking needs BOTH names, and neither alone is
9
+ * safe. `readOnly` is the same story: `editable={false}` is dropped on web.
10
+ */
11
+ export declare const masked: (on: boolean) => object;
12
+ export type SecretInputProps = {
13
+ value: string;
14
+ /** Omit to render read-only — the common case for a key the server minted. */
15
+ onChange?: (v: string) => void;
16
+ placeholder?: string;
17
+ disabled?: boolean;
18
+ /** Show the copy control. Default true — copying is why the field exists. */
19
+ copy?: boolean;
20
+ /** Names the secret in analytics ("openai-key"). Never the value. */
21
+ id?: string;
22
+ };
23
+ export declare function SecretInput({ value, onChange, placeholder, disabled, copy, id, }: SecretInputProps): import("react/jsx-runtime").JSX.Element;
24
+ //# sourceMappingURL=SecretInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecretInput.d.ts","sourceRoot":"","sources":["../../src/product/SecretInput.tsx"],"names":[],"mappings":"AA2BA;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM,GAAI,IAAI,OAAO,KACiE,MAAM,CAAA;AAEzG,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,qEAAqE;IACrE,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,IAAW,EACX,EAAE,GACH,EAAE,gBAAgB,2CAkElB"}
@@ -0,0 +1,55 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * SecretInput — a secret you can check, copy, and not leak over someone's
5
+ * shoulder.
6
+ *
7
+ * An API key, a token, a webhook signing secret. Masked by default, revealed
8
+ * deliberately, and copyable without ever being revealed — which is the point:
9
+ * the usual reason a person unmasks a key is to select it by hand, so a copy
10
+ * control that works while masked removes the reason to show it at all.
11
+ *
12
+ * Copying is `CopyButton`, not a second implementation. This component owns
13
+ * exactly one thing the others do not: the reveal.
14
+ *
15
+ * Nothing here reports the secret. The analytics event carries the LENGTH and
16
+ * whether it was revealed — never a character of the value, and it is never
17
+ * written to the console, which is where the previous implementation sent its
18
+ * clipboard failures.
19
+ */
20
+ import { useState } from 'react';
21
+ import { Input, XStack } from '@hanzo/gui';
22
+ import { Eye, EyeOff } from '@hanzogui/lucide-icons-2';
23
+ import { tip } from '../backends/gui/slot.js';
24
+ import { CopyButton } from './CopyButton.js';
25
+ import { useEmit } from './instrument.js';
26
+ /**
27
+ * Masking, on both platforms.
28
+ *
29
+ * `secureTextEntry` is React Native's spelling and gui DROPS it on web — an
30
+ * input carrying only that prop renders the secret in plain text, which is the
31
+ * exact opposite of what the caller asked for. `type="password"` is the web
32
+ * spelling and gui forwards it, being an unrecognised prop. Native ignores
33
+ * `type` for the same reason. So masking needs BOTH names, and neither alone is
34
+ * safe. `readOnly` is the same story: `editable={false}` is dropped on web.
35
+ */
36
+ export const masked = (on) => (on ? { secureTextEntry: true, type: 'password' } : { secureTextEntry: false, type: 'text' });
37
+ export function SecretInput({ value, onChange, placeholder, disabled, copy = true, id, }) {
38
+ const [shown, setShown] = useState(false);
39
+ const track = useEmit();
40
+ const toggle = () => {
41
+ track({ component: 'SecretInput', action: shown ? 'close' : 'open', id });
42
+ setShown((s) => !s);
43
+ };
44
+ return (_jsxs(XStack, { items: "center", gap: "$1", px: "$2", rounded: "$3", borderWidth: 1, borderColor: "$borderColor", bg: "$background", opacity: disabled ? 0.5 : 1, children: [_jsx(Input, { flex: 1, minW: 0, borderWidth: 0, bg: "transparent", value: value, onChangeText: onChange
45
+ ? (v) => {
46
+ track({ component: 'SecretInput', action: 'change', id, value: v.length });
47
+ onChange(v);
48
+ }
49
+ : undefined,
50
+ // No handler means the caller is displaying a minted secret, not
51
+ // collecting one; a field that accepts keystrokes it then discards
52
+ // reads as broken. `readOnly`, not `editable` — see `masked`.
53
+ readOnly: !onChange, disabled: disabled, ...masked(!shown), placeholder: placeholder, autoCapitalize: "none", autoCorrect: false, spellCheck: false }), copy && value ? _jsx(CopyButton, { value: value, label: "Copy secret", id: id }) : null, _jsx(XStack, { width: 24, height: 24, items: "center", justify: "center", rounded: "$2", cursor: disabled ? 'not-allowed' : 'pointer', opacity: 0.7, onPress: disabled ? undefined : toggle, role: "button", tabIndex: 0, "aria-label": shown ? 'Hide secret' : 'Show secret', ...tip(shown ? 'Hide' : 'Show'), hoverStyle: disabled ? undefined : { bg: '$color4', opacity: 1 }, pressStyle: disabled ? undefined : { bg: '$color5' }, children: shown ? _jsx(EyeOff, { size: 14 }) : _jsx(Eye, { size: 14 }) })] }));
54
+ }
55
+ //# sourceMappingURL=SecretInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecretInput.js","sourceRoot":"","sources":["../../src/product/SecretInput.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.displayName = displayName;
5
+ exports.UserMenu = UserMenu;
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ /**
8
+ * UserMenu — the account control: who I am, and the things I do to my account.
9
+ *
10
+ * It was written inside `AppHeader` and could not be reached from anywhere else,
11
+ * so every surface that wanted an account menu without adopting the whole header
12
+ * wrote one: hanzo.app twice, chat, console, billing. Five implementations of one
13
+ * menu, disagreeing on the trigger, the row order and the sign-out copy. This is
14
+ * that menu, extracted whole — `AppHeader` now renders it instead of owning it,
15
+ * so the header and a standalone account control cannot drift apart.
16
+ *
17
+ * Host-agnostic: identity is a value, every row is an injected handler, and a row
18
+ * renders only when its handler is provided — an honest menu, never a dead item.
19
+ * The surface keeps its own `useUser`/router in a thin wrapper; that wrapper is
20
+ * the seam the charter asks for, not a duplicate.
21
+ *
22
+ * The trigger is sized as the PEER of `OrgSwitcher` — same height, same mark,
23
+ * same type — so "which workspace" and "who I am" read as two halves of one
24
+ * identity rather than a caption over a control.
25
+ */
26
+ const react_1 = require("react");
27
+ const gui_1 = require("@hanzo/gui");
28
+ const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
29
+ const instrument_1 = require("./instrument.cjs");
30
+ const OrgMark_1 = require("./OrgMark.cjs");
31
+ const ThemeToggle_1 = require("./ThemeToggle.cjs");
32
+ function Row({ item, onDone }) {
33
+ const track = (0, instrument_1.useEmit)();
34
+ return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { onPress: () => {
35
+ track({ component: 'UserMenu', action: 'select', id: item.id });
36
+ onDone();
37
+ item.onPress();
38
+ }, cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$2", rounded: "$3", hoverStyle: { bg: '$color5' }, children: [item.icon, (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", color: item.danger ? '$red10' : '$color12', children: item.label })] }));
39
+ }
40
+ /** The name to show: the given one, else the email's local part, else nothing
41
+ * fabricated — "User" is not a name and reads as a bug to the person it names. */
42
+ function displayName(name, email) {
43
+ if (name?.trim())
44
+ return name.trim();
45
+ const local = email?.split('@')[0];
46
+ return local?.trim() || '';
47
+ }
48
+ function UserMenu({ name, email, avatar, groups = [], theme, onSignOut, signOutLabel = 'Sign out', children, label = true, height = 44, }) {
49
+ const [open, setOpen] = (0, react_1.useState)(false);
50
+ const track = (0, instrument_1.useEmit)();
51
+ const shown = displayName(name, email);
52
+ const filled = groups.filter((g) => g.length > 0);
53
+ const close = () => setOpen(false);
54
+ return ((0, jsx_runtime_1.jsxs)(gui_1.Popover, { open: open, onOpenChange: (next) => {
55
+ track({ component: 'UserMenu', action: next ? 'open' : 'close' });
56
+ setOpen(next);
57
+ }, placement: "bottom-end", children: [(0, jsx_runtime_1.jsx)(gui_1.Popover.Trigger, { asChild: true, children: (0, jsx_runtime_1.jsxs)(gui_1.XStack, { cursor: "pointer", items: "center", gap: "$2.5", height: height, px: "$2", rounded: "$3", minW: 0, hoverStyle: { bg: '$color4' }, role: "button", tabIndex: 0, "aria-label": shown ? `${shown} · account` : 'Account', children: [avatar || shown ? ((0, jsx_runtime_1.jsx)(OrgMark_1.OrgMark, { org: { name: shown || 'Account', logo: avatar }, size: 30 })) : ((0, jsx_runtime_1.jsx)(lucide_icons_2_1.UserRound, { size: 18 })), label && shown ? ((0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$3", fontWeight: "600", color: "$color12", numberOfLines: 1, maxW: 160, children: shown })) : null] }) }), (0, jsx_runtime_1.jsx)(gui_1.Popover.Content, { bordered: true, elevate: true, p: "$2", width: 240, bg: "$color2", borderColor: "$borderColor", children: children ?? ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { gap: "$1", children: [shown || email ? ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { gap: "$0.5", px: "$2", py: "$1.5", children: [shown ? ((0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", fontWeight: "700", color: "$color12", numberOfLines: 1, children: shown })) : null, email && email !== shown ? ((0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$1", color: "$color10", numberOfLines: 1, children: email })) : null] })) : null, filled.map((group, i) => ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { gap: "$1", children: [(i > 0 || shown || email) ? (0, jsx_runtime_1.jsx)(gui_1.Separator, { borderColor: "$borderColor", my: "$1" }) : null, group.map((item) => ((0, jsx_runtime_1.jsx)(Row, { item: item, onDone: close }, item.id)))] }, i))), theme !== null ? ((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.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, 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)(Row, { item: {
58
+ id: 'sign-out',
59
+ label: signOutLabel,
60
+ icon: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.LogOut, { size: 15 }),
61
+ onPress: onSignOut,
62
+ }, onDone: close })] })) : null] })) })] }));
63
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * UserMenu — the account control: who I am, and the things I do to my account.
3
+ *
4
+ * It was written inside `AppHeader` and could not be reached from anywhere else,
5
+ * so every surface that wanted an account menu without adopting the whole header
6
+ * wrote one: hanzo.app twice, chat, console, billing. Five implementations of one
7
+ * menu, disagreeing on the trigger, the row order and the sign-out copy. This is
8
+ * that menu, extracted whole — `AppHeader` now renders it instead of owning it,
9
+ * so the header and a standalone account control cannot drift apart.
10
+ *
11
+ * Host-agnostic: identity is a value, every row is an injected handler, and a row
12
+ * renders only when its handler is provided — an honest menu, never a dead item.
13
+ * The surface keeps its own `useUser`/router in a thin wrapper; that wrapper is
14
+ * the seam the charter asks for, not a duplicate.
15
+ *
16
+ * The trigger is sized as the PEER of `OrgSwitcher` — same height, same mark,
17
+ * same type — so "which workspace" and "who I am" read as two halves of one
18
+ * identity rather than a caption over a control.
19
+ */
20
+ import { type ReactNode } from 'react';
21
+ /** One row. `id` names it in analytics; the label is what the person reads. */
22
+ export type UserMenuItem = {
23
+ id: string;
24
+ label: string;
25
+ icon?: ReactNode;
26
+ onPress: () => void;
27
+ /** Draws the row in the destructive tone (sign out, delete account). */
28
+ danger?: boolean;
29
+ };
30
+ export type UserMenuProps = {
31
+ /** The signed-in person's display name. Falls back to the email's local part. */
32
+ name?: string;
33
+ email?: string;
34
+ /** Avatar URL. Absent → the monogram of the name, like an org's mark. */
35
+ avatar?: string;
36
+ /** Grouped rows — each group is separated by a rule, empty groups are dropped. */
37
+ groups?: UserMenuItem[][];
38
+ /** Theme row content — default `<ThemeToggle/>`; `null` hides the row (a
39
+ * single-theme surface has nothing to toggle and should not pretend to). */
40
+ theme?: ReactNode;
41
+ /** Sign out. Omit on a surface that cannot sign out. */
42
+ onSignOut?: () => void;
43
+ /** Sign-out copy — "Sign out" everywhere unless a surface has a reason. */
44
+ signOutLabel?: string;
45
+ /** Replace the whole menu body, keeping the trigger. */
46
+ children?: ReactNode;
47
+ /** Show the name beside the avatar in the trigger. Default true. */
48
+ label?: boolean;
49
+ /** Trigger height. Default 44 — the peer of `OrgSwitcher`. */
50
+ height?: number;
51
+ };
52
+ /** The name to show: the given one, else the email's local part, else nothing
53
+ * fabricated — "User" is not a name and reads as a bug to the person it names. */
54
+ export declare function displayName(name?: string, email?: string): string;
55
+ export declare function UserMenu({ name, email, avatar, groups, theme, onSignOut, signOutLabel, children, label, height, }: UserMenuProps): import("react/jsx-runtime").JSX.Element;
56
+ //# sourceMappingURL=UserMenu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserMenu.d.ts","sourceRoot":"","sources":["../../src/product/UserMenu.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAQhD,+EAA+E;AAC/E,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kFAAkF;IAClF,MAAM,CAAC,EAAE,YAAY,EAAE,EAAE,CAAA;IACzB;iFAC6E;IAC7E,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,oEAAoE;IACpE,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AA2BD;mFACmF;AACnF,wBAAgB,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAIjE;AAED,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,KAAK,EACL,MAAM,EACN,MAAW,EACX,KAAK,EACL,SAAS,EACT,YAAyB,EACzB,QAAQ,EACR,KAAY,EACZ,MAAW,GACZ,EAAE,aAAa,2CAyGf"}
@@ -0,0 +1,60 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ /**
4
+ * UserMenu — the account control: who I am, and the things I do to my account.
5
+ *
6
+ * It was written inside `AppHeader` and could not be reached from anywhere else,
7
+ * so every surface that wanted an account menu without adopting the whole header
8
+ * wrote one: hanzo.app twice, chat, console, billing. Five implementations of one
9
+ * menu, disagreeing on the trigger, the row order and the sign-out copy. This is
10
+ * that menu, extracted whole — `AppHeader` now renders it instead of owning it,
11
+ * so the header and a standalone account control cannot drift apart.
12
+ *
13
+ * Host-agnostic: identity is a value, every row is an injected handler, and a row
14
+ * renders only when its handler is provided — an honest menu, never a dead item.
15
+ * The surface keeps its own `useUser`/router in a thin wrapper; that wrapper is
16
+ * the seam the charter asks for, not a duplicate.
17
+ *
18
+ * The trigger is sized as the PEER of `OrgSwitcher` — same height, same mark,
19
+ * same type — so "which workspace" and "who I am" read as two halves of one
20
+ * identity rather than a caption over a control.
21
+ */
22
+ import { useState } from 'react';
23
+ import { Popover, Separator, Text, XStack, YStack } from '@hanzo/gui';
24
+ import { LogOut, UserRound } from '@hanzogui/lucide-icons-2';
25
+ import { useEmit } from './instrument.js';
26
+ import { OrgMark } from './OrgMark.js';
27
+ import { ThemeToggle } from './ThemeToggle.js';
28
+ function Row({ item, onDone }) {
29
+ const track = useEmit();
30
+ return (_jsxs(XStack, { onPress: () => {
31
+ track({ component: 'UserMenu', action: 'select', id: item.id });
32
+ onDone();
33
+ item.onPress();
34
+ }, cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$2", rounded: "$3", hoverStyle: { bg: '$color5' }, children: [item.icon, _jsx(Text, { fontSize: "$2", color: item.danger ? '$red10' : '$color12', children: item.label })] }));
35
+ }
36
+ /** The name to show: the given one, else the email's local part, else nothing
37
+ * fabricated — "User" is not a name and reads as a bug to the person it names. */
38
+ export function displayName(name, email) {
39
+ if (name?.trim())
40
+ return name.trim();
41
+ const local = email?.split('@')[0];
42
+ return local?.trim() || '';
43
+ }
44
+ export function UserMenu({ name, email, avatar, groups = [], theme, onSignOut, signOutLabel = 'Sign out', children, label = true, height = 44, }) {
45
+ const [open, setOpen] = useState(false);
46
+ const track = useEmit();
47
+ const shown = displayName(name, email);
48
+ const filled = groups.filter((g) => g.length > 0);
49
+ const close = () => setOpen(false);
50
+ return (_jsxs(Popover, { open: open, onOpenChange: (next) => {
51
+ track({ component: 'UserMenu', action: next ? 'open' : 'close' });
52
+ setOpen(next);
53
+ }, placement: "bottom-end", children: [_jsx(Popover.Trigger, { asChild: true, children: _jsxs(XStack, { cursor: "pointer", items: "center", gap: "$2.5", height: height, px: "$2", rounded: "$3", minW: 0, hoverStyle: { bg: '$color4' }, role: "button", tabIndex: 0, "aria-label": shown ? `${shown} · account` : 'Account', children: [avatar || shown ? (_jsx(OrgMark, { org: { name: shown || 'Account', logo: avatar }, size: 30 })) : (_jsx(UserRound, { size: 18 })), label && shown ? (_jsx(Text, { fontSize: "$3", fontWeight: "600", color: "$color12", numberOfLines: 1, maxW: 160, children: shown })) : null] }) }), _jsx(Popover.Content, { bordered: true, elevate: true, p: "$2", width: 240, bg: "$color2", borderColor: "$borderColor", children: children ?? (_jsxs(YStack, { gap: "$1", children: [shown || email ? (_jsxs(YStack, { gap: "$0.5", px: "$2", py: "$1.5", children: [shown ? (_jsx(Text, { fontSize: "$2", fontWeight: "700", color: "$color12", numberOfLines: 1, children: shown })) : null, email && email !== shown ? (_jsx(Text, { fontSize: "$1", color: "$color10", numberOfLines: 1, children: email })) : null] })) : null, filled.map((group, i) => (_jsxs(YStack, { gap: "$1", children: [(i > 0 || shown || email) ? _jsx(Separator, { borderColor: "$borderColor", my: "$1" }) : null, group.map((item) => (_jsx(Row, { item: item, onDone: close }, item.id)))] }, i))), theme !== null ? (_jsxs(_Fragment, { children: [_jsx(Separator, { borderColor: "$borderColor", my: "$1" }), _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, onSignOut ? (_jsxs(_Fragment, { children: [_jsx(Separator, { borderColor: "$borderColor", my: "$1" }), _jsx(Row, { item: {
54
+ id: 'sign-out',
55
+ label: signOutLabel,
56
+ icon: _jsx(LogOut, { size: 15 }),
57
+ onPress: onSignOut,
58
+ }, onDone: close })] })) : null] })) })] }));
59
+ }
60
+ //# sourceMappingURL=UserMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserMenu.js","sourceRoot":"","sources":["../../src/product/UserMenu.tsx"],"names":[],"mappings":"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"}
@@ -51,14 +51,19 @@ Object.defineProperty(exports, "DonutRing", { enumerable: true, get: function ()
51
51
  var ComboBox_1 = require("./ComboBox.cjs");
52
52
  Object.defineProperty(exports, "ComboBox", { enumerable: true, get: function () { return ComboBox_1.ComboBox; } });
53
53
  __exportStar(require("./combobox/filter.cjs"), exports);
54
- // The shared shell — brand mark, org scope + switcher, app header (the
55
- // console's org-scope contract + switcher hoisted here; hanzoai/ui#36).
54
+ // The shared shell — brand mark, org scope + switcher, account menu, app header
55
+ // (the console's org-scope contract + switcher hoisted here; hanzoai/ui#36).
56
56
  // `surfaces.data` is the ONE canonical cross-surface list every launcher consumes.
57
+ //
58
+ // `UserMenu` is the account half of the chrome trio (org · apps · account). It
59
+ // was written inside `AppHeader` and unreachable from anywhere else, so five
60
+ // surfaces wrote their own; `AppHeader` now renders this one.
57
61
  __exportStar(require("./surfaces.data.cjs"), exports);
58
62
  __exportStar(require("./AppHeader.cjs"), exports);
59
63
  __exportStar(require("./BrandMark.cjs"), exports);
60
64
  __exportStar(require("./OrgMark.cjs"), exports);
61
65
  __exportStar(require("./OrgSwitcher.cjs"), exports);
66
+ __exportStar(require("./UserMenu.cjs"), exports);
62
67
  __exportStar(require("./scope.cjs"), exports);
63
68
  // Menu — the ONE menu system: portal-theme-safe DropdownMenu (click) + ContextMenu
64
69
  // (right-click), both rendering the SAME item spec (MenuPanel/MenuItemView) so every
@@ -83,6 +88,20 @@ __exportStar(require("./Filters.cjs"), exports);
83
88
  // `<InstrumentSurface value="billing">` to name the area, and `emit` for the
84
89
  // one-off moments no shared component can observe.
85
90
  __exportStar(require("./instrument.cjs"), exports);
91
+ // Settings — `Fieldset` is the titled group the `Field*` rows sit in. It is not
92
+ // `Panel` (a dashboard metric tile): a settings group runs full width, carries a
93
+ // legend and has a destructive register. Every settings page drew its own.
94
+ __exportStar(require("./Fieldset.cjs"), exports);
95
+ // `CopyButton` and `SecretInput` — copying a value, and revealing one. CopyButton
96
+ // lived in `chat/Code.tsx`, reachable only as `@hanzo/ui/chat`, so ~30 hand-rolled
97
+ // copies grew across six surfaces; `Code` now imports it from here. SecretInput
98
+ // composes it, because copying a key while it is still masked is the whole reason
99
+ // the field exists.
100
+ __exportStar(require("./CopyButton.cjs"), exports);
101
+ __exportStar(require("./SecretInput.cjs"), exports);
102
+ // `Pagination` — the fixed-width page run (`pages` is the pure rule, testable
103
+ // without a browser).
104
+ __exportStar(require("./Pagination.cjs"), exports);
86
105
  // The rest — every exported name below is unique across the layer.
87
106
  __exportStar(require("./AnimatedLogo.cjs"), exports);
88
107
  __exportStar(require("./brand.cjs"), exports);
@@ -8,6 +8,7 @@ export * from './AppHeader.js';
8
8
  export * from './BrandMark.js';
9
9
  export * from './OrgMark.js';
10
10
  export * from './OrgSwitcher.js';
11
+ export * from './UserMenu.js';
11
12
  export * from './scope.js';
12
13
  export * from './menu/index.js';
13
14
  export * from './SiteNav.js';
@@ -18,6 +19,10 @@ export * from './CommerceResource.js';
18
19
  export * from './ConfirmDelete.js';
19
20
  export * from './Filters.js';
20
21
  export * from './instrument.js';
22
+ export * from './Fieldset.js';
23
+ export * from './CopyButton.js';
24
+ export * from './SecretInput.js';
25
+ export * from './Pagination.js';
21
26
  export * from './AnimatedLogo.js';
22
27
  export * from './brand.js';
23
28
  export * from './DataTable.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/product/index.ts"],"names":[],"mappings":"AAaA,cAAc,UAAU,CAAA;AAKxB,OAAO,EACL,MAAM,EACN,aAAa,EACb,SAAS,EACT,SAAS,IAAI,eAAe,EAC5B,QAAQ,EACR,OAAO,EACP,SAAS,EACT,UAAU,EACV,UAAU,EACV,KAAK,GACN,MAAM,UAAU,CAAA;AAGjB,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAA;AAK/D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,cAAc,mBAAmB,CAAA;AAKjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,SAAS,CAAA;AAKvB,cAAc,QAAQ,CAAA;AAKtB,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAK5B,cAAc,QAAQ,CAAA;AACtB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,oBAAoB,CAAA;AAClC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,WAAW,CAAA;AAOzB,cAAc,cAAc,CAAA;AAG5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AASvB,cAAc,UAAU,CAAA;AAKxB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/product/index.ts"],"names":[],"mappings":"AAaA,cAAc,UAAU,CAAA;AAKxB,OAAO,EACL,MAAM,EACN,aAAa,EACb,SAAS,EACT,SAAS,IAAI,eAAe,EAC5B,QAAQ,EACR,OAAO,EACP,SAAS,EACT,UAAU,EACV,UAAU,EACV,KAAK,GACN,MAAM,UAAU,CAAA;AAGjB,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAA;AAK/D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,cAAc,mBAAmB,CAAA;AASjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AAKvB,cAAc,QAAQ,CAAA;AAKtB,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAK5B,cAAc,QAAQ,CAAA;AACtB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,oBAAoB,CAAA;AAClC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,WAAW,CAAA;AAOzB,cAAc,cAAc,CAAA;AAK5B,cAAc,YAAY,CAAA;AAO1B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAI7B,cAAc,cAAc,CAAA;AAG5B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AASvB,cAAc,UAAU,CAAA;AAKxB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,aAAa,CAAA"}