@stackone/malachite 2.37.1 → 2.38.0

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 (94) hide show
  1. package/COMPONENTS.md +7 -2
  2. package/dist/assets/icons/account.svg.js +2 -2
  3. package/dist/assets/icons/account.svg.js.map +1 -1
  4. package/dist/assets/icons/building.svg.js +6 -0
  5. package/dist/assets/icons/building.svg.js.map +1 -0
  6. package/dist/assets/icons/chevrons_up_down.svg.js +6 -0
  7. package/dist/assets/icons/chevrons_up_down.svg.js.map +1 -0
  8. package/dist/assets/icons/connector.svg.js +6 -0
  9. package/dist/assets/icons/connector.svg.js.map +1 -0
  10. package/dist/assets/icons/external_link.svg.js +6 -0
  11. package/dist/assets/icons/external_link.svg.js.map +1 -0
  12. package/dist/assets/icons/field_coverage.svg.js +6 -0
  13. package/dist/assets/icons/field_coverage.svg.js.map +1 -0
  14. package/dist/assets/icons/layout.svg.js +6 -0
  15. package/dist/assets/icons/layout.svg.js.map +1 -0
  16. package/dist/assets/icons/link.svg.js +6 -0
  17. package/dist/assets/icons/link.svg.js.map +1 -0
  18. package/dist/assets/icons/playground.svg.js +6 -0
  19. package/dist/assets/icons/playground.svg.js.map +1 -0
  20. package/dist/components/ActionMenu.js +139 -170
  21. package/dist/components/ActionMenu.js.map +1 -1
  22. package/dist/components/Chat/ChatModelPicker.js +64 -60
  23. package/dist/components/Chat/ChatModelPicker.js.map +1 -1
  24. package/dist/components/CustomIcons/BuildingIcon.js +16 -0
  25. package/dist/components/CustomIcons/BuildingIcon.js.map +1 -0
  26. package/dist/components/CustomIcons/ChevronsUpDownIcon.js +16 -0
  27. package/dist/components/CustomIcons/ChevronsUpDownIcon.js.map +1 -0
  28. package/dist/components/CustomIcons/ConnectorIcon.js +16 -0
  29. package/dist/components/CustomIcons/ConnectorIcon.js.map +1 -0
  30. package/dist/components/CustomIcons/ExternalLinkIcon.js +16 -0
  31. package/dist/components/CustomIcons/ExternalLinkIcon.js.map +1 -0
  32. package/dist/components/CustomIcons/FieldCoverageIcon.js +16 -0
  33. package/dist/components/CustomIcons/FieldCoverageIcon.js.map +1 -0
  34. package/dist/components/CustomIcons/LayoutIcon.js +16 -0
  35. package/dist/components/CustomIcons/LayoutIcon.js.map +1 -0
  36. package/dist/components/CustomIcons/LinkIcon.js +16 -0
  37. package/dist/components/CustomIcons/LinkIcon.js.map +1 -0
  38. package/dist/components/CustomIcons/PlaygroundIcon.js +16 -0
  39. package/dist/components/CustomIcons/PlaygroundIcon.js.map +1 -0
  40. package/dist/components/CustomIcons/index.js +303 -279
  41. package/dist/components/CustomIcons/index.js.map +1 -1
  42. package/dist/components/NavItem.js +158 -0
  43. package/dist/components/NavItem.js.map +1 -0
  44. package/dist/components/Popover.js +262 -0
  45. package/dist/components/Popover.js.map +1 -0
  46. package/dist/components/PopoverParts.js +46 -0
  47. package/dist/components/PopoverParts.js.map +1 -0
  48. package/dist/components/QueryInput.js +103 -97
  49. package/dist/components/QueryInput.js.map +1 -1
  50. package/dist/components/SearchTrigger.js +37 -0
  51. package/dist/components/SearchTrigger.js.map +1 -0
  52. package/dist/components/Sidebar.js +174 -0
  53. package/dist/components/Sidebar.js.map +1 -0
  54. package/dist/components/Tooltip.js +97 -92
  55. package/dist/components/Tooltip.js.map +1 -1
  56. package/dist/components/UsageCard.js +44 -0
  57. package/dist/components/UsageCard.js.map +1 -0
  58. package/dist/components/actionMenuKeyboard.js +23 -0
  59. package/dist/components/actionMenuKeyboard.js.map +1 -0
  60. package/dist/components/actionMenuStyles.js +83 -0
  61. package/dist/components/actionMenuStyles.js.map +1 -0
  62. package/dist/components/ariaState.js +5 -0
  63. package/dist/components/ariaState.js.map +1 -0
  64. package/dist/components/chromeStyles.js +6 -0
  65. package/dist/components/chromeStyles.js.map +1 -0
  66. package/dist/components/composeRefs.js +27 -0
  67. package/dist/components/composeRefs.js.map +1 -0
  68. package/dist/components/floatingMenuGeometry.js +74 -35
  69. package/dist/components/floatingMenuGeometry.js.map +1 -1
  70. package/dist/components/overlayBehaviour.js +90 -84
  71. package/dist/components/overlayBehaviour.js.map +1 -1
  72. package/dist/components/popoverTree.js +14 -0
  73. package/dist/components/popoverTree.js.map +1 -0
  74. package/dist/components/portalOverlay.js +28 -22
  75. package/dist/components/portalOverlay.js.map +1 -1
  76. package/dist/components/sidebarContext.js +9 -0
  77. package/dist/components/sidebarContext.js.map +1 -0
  78. package/dist/components/topLayer.js +18 -18
  79. package/dist/components/topLayer.js.map +1 -1
  80. package/dist/components/useActionMenuPosition.js +73 -0
  81. package/dist/components/useActionMenuPosition.js.map +1 -0
  82. package/dist/components/useHoverClose.js +18 -0
  83. package/dist/components/useHoverClose.js.map +1 -0
  84. package/dist/components/useLatestRef.js +11 -0
  85. package/dist/components/useLatestRef.js.map +1 -0
  86. package/dist/components/usePopoverPosition.js +62 -0
  87. package/dist/components/usePopoverPosition.js.map +1 -0
  88. package/dist/components/usePopoverTree.js +34 -0
  89. package/dist/components/usePopoverTree.js.map +1 -0
  90. package/dist/index.d.ts +387 -100
  91. package/dist/index.js +365 -335
  92. package/dist/index.js.map +1 -1
  93. package/dist/tailwind.css.js +1 -1
  94. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchTrigger.js","sources":["../../src/components/SearchTrigger.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport SearchIcon from './CustomIcons/SearchIcon';\nimport { FOCUS_RING } from './focusRing';\n\nexport interface SearchTriggerProps\n extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'children' | 'className' | 'style' | 'color' | 'type'\n > {\n label?: string;\n shortcut?: React.ReactNode[];\n iconOnly?: boolean;\n className?: string;\n}\n\nconst BASE = `group flex items-center shrink-0 border border-solid border-transparent m-0 cursor-pointer font-sans font-normal text-left rounded-[var(--malachite-radius-xl,12px)] bg-[var(--malachite-pillbutton-background,rgb(241,241,241))] text-[var(--malachite-pillbutton-foreground,rgb(123,123,123))] enabled:hover:bg-[var(--malachite-pillbutton-hover-background,rgb(232,232,232))] disabled:cursor-not-allowed disabled:opacity-50 transition-[background-color] duration-200 ${FOCUS_RING}`;\n\nconst KEY =\n 'inline-flex items-center justify-center h-[25px] px-2 rounded-lg border border-solid border-[var(--malachite-card-border,rgb(232,232,232))] bg-[var(--malachite-card-sunken-background,rgb(250,250,250))] font-mono text-[length:var(--malachite-font-size-small,13px)] font-normal leading-none text-[var(--malachite-text-placeholder,rgb(187,187,187))]';\n\nconst SHAPE = {\n field: 'w-full h-10 gap-2 px-3 text-[length:var(--malachite-font-size-medium,14px)]',\n icon: 'w-9 h-[37px] justify-center p-0',\n} as const;\n\nexport const SearchTrigger = forwardRef<HTMLButtonElement, SearchTriggerProps>(\n (\n {\n label = 'Search',\n shortcut,\n iconOnly = false,\n 'aria-label': ariaLabel,\n className = '',\n ...rest\n },\n ref,\n ) => (\n <button\n ref={ref}\n type=\"button\"\n {...rest}\n aria-label={iconOnly ? (ariaLabel ?? label) : ariaLabel}\n className={`${BASE} ${iconOnly ? SHAPE.icon : SHAPE.field} ${className}`.trim()}\n >\n <SearchIcon size={16} className=\"shrink-0\" />\n {!iconOnly && <span className=\"min-w-0 flex-1 truncate\">{label}</span>}\n {!iconOnly && shortcut && shortcut.length > 0 && (\n <span aria-hidden=\"true\" className=\"flex shrink-0 items-center gap-[5px]\">\n {shortcut.map((key, index) => (\n <kbd key={index} className={KEY}>\n {key}\n </kbd>\n ))}\n </span>\n )}\n </button>\n ),\n);\n\nSearchTrigger.displayName = 'SearchTrigger';\n\nexport default SearchTrigger;\n"],"names":["BASE","FOCUS_RING","KEY","SHAPE","SearchTrigger","forwardRef","label","shortcut","iconOnly","ariaLabel","className","rest","ref","jsxs","jsx","SearchIcon","key","index"],"mappings":";;;;AAeA,MAAMA,IAAO,gdAAgdC,CAAU,IAEjeC,IACF,8VAEEC,IAAQ;AAAA,EACV,OAAO;AAAA,EACP,MAAM;AACV,GAEaC,IAAgBC;AAAA,EACzB,CACI;AAAA,IACI,OAAAC,IAAQ;AAAA,IACR,UAAAC;AAAA,IACA,UAAAC,IAAW;AAAA,IACX,cAAcC;AAAA,IACd,WAAAC,IAAY;AAAA,IACZ,GAAGC;AAAA,EAAA,GAEPC,MAEA,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,KAAAD;AAAA,MACA,MAAK;AAAA,MACJ,GAAGD;AAAA,MACJ,cAAYH,IAAYC,KAAaH,IAASG;AAAA,MAC9C,WAAW,GAAGT,CAAI,IAAIQ,IAAWL,EAAM,OAAOA,EAAM,KAAK,IAAIO,CAAS,GAAG,KAAA;AAAA,MAEzE,UAAA;AAAA,QAAA,gBAAAI,EAACC,GAAA,EAAW,MAAM,IAAI,WAAU,YAAW;AAAA,QAC1C,CAACP,KAAY,gBAAAM,EAAC,QAAA,EAAK,WAAU,2BAA2B,UAAAR,GAAM;AAAA,QAC9D,CAACE,KAAYD,KAAYA,EAAS,SAAS,KACxC,gBAAAO,EAAC,QAAA,EAAK,eAAY,QAAO,WAAU,wCAC9B,YAAS,IAAI,CAACE,GAAKC,MAChB,gBAAAH,EAAC,OAAA,EAAgB,WAAWZ,GACvB,UAAAc,KADKC,CAEV,CACH,EAAA,CACL;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIhB;AAEAb,EAAc,cAAc;"}
@@ -0,0 +1,174 @@
1
+ import { jsx as r, jsxs as l } from "react/jsx-runtime";
2
+ import { useMemo as N, forwardRef as u } from "react";
3
+ import w from "./CustomIcons/CaretLeftIcon.js";
4
+ import _ from "./CustomIcons/CaretRightIcon.js";
5
+ import h from "./CustomIcons/ChevronsUpDownIcon.js";
6
+ import f from "./Tooltip.js";
7
+ import { UsageCard as S } from "./UsageCard.js";
8
+ import { isExpanded as $ } from "./ariaState.js";
9
+ import { BORDER as d, NO_SCROLLBAR as R } from "./chromeStyles.js";
10
+ import { FOCUS_RING as m } from "./focusRing.js";
11
+ import { SIDEBAR_WIDTH_PX as b, SidebarContext as k, SIDEBAR_POPOVER_WIDTH_PX as j, useSidebarCollapsed as E } from "./sidebarContext.js";
12
+ const i = () => ({ collapsed: E() }), I = 1, O = 24, g = { width: 8, height: 14 }, z = "fixed top-[25px] z-[101] invisible opacity-0 [will-change:opacity] transition-[left,opacity,visibility] duration-200 ease-in-out group-hover/sidebar:visible group-hover/sidebar:opacity-100 group-has-[:focus-visible]/sidebar:visible group-has-[:focus-visible]/sidebar:opacity-100", C = ({
13
+ collapsed: e = !1,
14
+ onToggleCollapse: t,
15
+ expandLabel: o = "Expand menu",
16
+ collapseLabel: n = "Collapse menu",
17
+ "aria-label": s = "Main",
18
+ children: c
19
+ }) => {
20
+ const a = e ? o : n, p = N(() => ({ collapsed: e }), [e]), x = e ? b.collapsed : b.expanded;
21
+ return /* @__PURE__ */ r(k.Provider, { value: p, children: /* @__PURE__ */ l(
22
+ "aside",
23
+ {
24
+ className: "group/sidebar fixed top-0 bottom-0 left-0 z-[100] box-border pt-[9px] bg-[var(--malachite-card-sunken-background,rgb(250,250,250))] transition-[width] duration-200 ease-in-out",
25
+ style: { width: x },
26
+ children: [
27
+ /* @__PURE__ */ r("nav", { "aria-label": s, className: "flex h-full flex-col", children: c }),
28
+ t && /* @__PURE__ */ r("div", { className: z, style: { left: x - O / 2 }, children: /* @__PURE__ */ r(f, { text: a, placement: "right", describesTrigger: !1, children: /* @__PURE__ */ r(
29
+ "button",
30
+ {
31
+ type: "button",
32
+ "aria-label": a,
33
+ onClick: t,
34
+ className: `m-0 inline-flex size-6 cursor-pointer items-center justify-center rounded-lg border border-solid p-0 ${d} bg-[var(--malachite-card-background,rgb(255,255,255))] text-[var(--malachite-text-secondary,rgb(123,123,123))] [box-shadow:var(--malachite-shadow-default,0px_1px_0px_0px_rgba(0,0,0,0.15))] transition-colors duration-200 hover:border-[var(--malachite-text-placeholder,rgb(187,187,187))] hover:text-[var(--malachite-text-primary,rgb(10,10,10))] ${m}`,
35
+ children: e ? /* @__PURE__ */ r(_, { size: 12 }) : /* @__PURE__ */ r(w, { size: 12 })
36
+ }
37
+ ) }) })
38
+ ]
39
+ }
40
+ ) });
41
+ }, P = ({ children: e }) => {
42
+ const { collapsed: t } = i();
43
+ return /* @__PURE__ */ r(
44
+ "div",
45
+ {
46
+ className: `box-border flex h-14 shrink-0 items-center border-0 border-b border-solid ${d} py-[6px] ${t ? "px-1" : "px-2"}`,
47
+ children: e
48
+ }
49
+ );
50
+ }, D = ({ children: e }) => /* @__PURE__ */ r("div", { className: `min-h-0 flex-1 overflow-x-hidden overflow-y-auto ${R}`, children: e }), L = ({ children: e }) => {
51
+ const { collapsed: t } = i();
52
+ return /* @__PURE__ */ r(
53
+ "div",
54
+ {
55
+ className: `flex flex-col gap-[2px] py-[2px] ${t ? "items-center px-3" : "px-4"}`,
56
+ children: e
57
+ }
58
+ );
59
+ }, A = ({ children: e }) => /* @__PURE__ */ r("div", { className: "my-[2px] flex flex-col gap-[6px]", children: e }), G = ({ children: e }) => /* @__PURE__ */ r("div", { className: "flex flex-col gap-[6px]", children: e }), T = ({ children: e }) => {
60
+ const { collapsed: t } = i();
61
+ return /* @__PURE__ */ r("div", { className: `flex pt-5 pb-[18px] ${t ? "justify-center px-3" : "px-4"}`, children: e });
62
+ }, B = ({
63
+ children: e,
64
+ "aria-label": t
65
+ }) => {
66
+ const { collapsed: o } = i();
67
+ return o ? null : /* @__PURE__ */ r("div", { role: "status", "aria-label": t, className: "flex flex-col gap-2 px-3 pt-4", children: e });
68
+ }, H = () => {
69
+ const { collapsed: e } = i();
70
+ return e ? null : /* @__PURE__ */ r("hr", { className: `m-0 my-2 h-0 shrink-0 border-0 border-t border-solid ${d}` });
71
+ }, U = ({ children: e }) => {
72
+ const { collapsed: t } = i();
73
+ return /* @__PURE__ */ r(
74
+ "div",
75
+ {
76
+ className: `mt-1 flex shrink-0 border-0 border-t border-solid ${d} py-3 ${t ? "justify-center px-2" : "px-4"}`,
77
+ children: e
78
+ }
79
+ );
80
+ }, v = u(
81
+ ({ logo: e, title: t, subtitle: o, className: n = "", ...s }, c) => {
82
+ const { collapsed: a } = i();
83
+ return /* @__PURE__ */ l(
84
+ "button",
85
+ {
86
+ ref: c,
87
+ type: "button",
88
+ "aria-label": a ? t : void 0,
89
+ ...s,
90
+ className: `group/switcher m-0 box-border flex h-full w-full min-w-0 cursor-pointer items-center gap-3 rounded-lg border-0 bg-transparent font-sans text-left ${a ? "justify-center p-1" : "justify-between px-4 py-[6px]"} ${m} ${n}`.trim(),
91
+ children: [
92
+ /* @__PURE__ */ l("span", { className: "flex min-w-0 items-center gap-4", children: [
93
+ /* @__PURE__ */ r(
94
+ "span",
95
+ {
96
+ "aria-hidden": "true",
97
+ className: "relative top-[-2.5px] flex size-6 shrink-0 items-center justify-center overflow-hidden rounded-md [&_img]:size-6 [&_img]:object-contain",
98
+ children: e
99
+ }
100
+ ),
101
+ !a && /* @__PURE__ */ l("span", { className: "flex min-w-0 flex-col gap-1", children: [
102
+ /* @__PURE__ */ r("span", { className: "block truncate text-[length:var(--malachite-font-size-medium,14px)] leading-[14px] font-medium text-[var(--malachite-text-primary,rgb(10,10,10))]", children: t }),
103
+ o && /* @__PURE__ */ r("span", { className: "block truncate text-[12px] leading-[12px] font-normal text-[var(--malachite-text-secondary,rgb(123,123,123))]", children: o })
104
+ ] })
105
+ ] }),
106
+ !a && /* @__PURE__ */ r("span", { className: "flex shrink-0 text-[var(--malachite-text-secondary,rgb(123,123,123))] transition-colors group-hover/switcher:text-[var(--malachite-text-primary,rgb(10,10,10))]", children: /* @__PURE__ */ r(h, { style: g }) })
107
+ ]
108
+ }
109
+ );
110
+ }
111
+ );
112
+ v.displayName = "Sidebar.Switcher";
113
+ const X = `inline-flex items-center justify-center rounded-[var(--malachite-radius-md,6px)] border border-solid ${d} bg-[var(--malachite-pillbutton-background,rgb(241,241,241))] supports-[color:color-mix(in_srgb,red,red)]:border-[color-mix(in_srgb,var(--malachite-text-placeholder,rgb(187,187,187))_20%,transparent)] supports-[color:color-mix(in_srgb,red,red)]:bg-[color-mix(in_srgb,var(--malachite-text-placeholder,rgb(187,187,187))_10%,transparent)] px-1 py-[3px] text-[length:var(--malachite-font-size-small,13px)] leading-[12px] font-semibold text-[var(--malachite-text-secondary,rgb(123,123,123))]`, y = u(
114
+ ({ avatar: e, initials: t, name: o, className: n = "", ...s }, c) => {
115
+ const { collapsed: a } = i(), p = /* @__PURE__ */ l(
116
+ "button",
117
+ {
118
+ ref: c,
119
+ type: "button",
120
+ "aria-label": a ? o : void 0,
121
+ ...s,
122
+ className: `group/account m-0 box-border flex min-h-8 w-full cursor-pointer items-center gap-3 rounded-lg border-0 bg-transparent font-sans ${a ? "justify-center p-0" : "justify-between px-2"} ${m} ${n}`.trim(),
123
+ children: [
124
+ /* @__PURE__ */ l("span", { className: "flex min-w-0 items-center gap-3", children: [
125
+ /* @__PURE__ */ r("span", { "aria-hidden": a ? void 0 : !0, className: "flex shrink-0", children: e ?? (t ? /* @__PURE__ */ r("span", { className: X, children: t }) : null) }),
126
+ !a && /* @__PURE__ */ r("span", { className: "truncate text-[length:var(--malachite-font-size-medium,14px)] leading-[22px] font-semibold text-[var(--malachite-text-primary,rgb(10,10,10))]", children: o })
127
+ ] }),
128
+ !a && /* @__PURE__ */ r("span", { className: "flex shrink-0 text-[var(--malachite-text-secondary,rgb(123,123,123))] transition-colors group-hover/account:text-[var(--malachite-text-primary,rgb(10,10,10))]", children: /* @__PURE__ */ r(h, { style: g }) })
129
+ ]
130
+ }
131
+ );
132
+ return a ? /* @__PURE__ */ r(
133
+ f,
134
+ {
135
+ text: o,
136
+ placement: "right",
137
+ describesTrigger: !1,
138
+ suppressed: $(s["aria-expanded"]),
139
+ children: p
140
+ }
141
+ ) : p;
142
+ }
143
+ );
144
+ y.displayName = "Sidebar.Account";
145
+ const V = (e) => {
146
+ const { collapsed: t } = i();
147
+ return t ? null : /* @__PURE__ */ r("div", { className: "shrink-0 px-3 pt-3 pb-4", children: /* @__PURE__ */ r(S, { ...e }) });
148
+ }, F = ({ children: e }) => /* @__PURE__ */ r(
149
+ "div",
150
+ {
151
+ className: "flex flex-col",
152
+ style: { width: j - 2 * I },
153
+ children: e
154
+ }
155
+ ), ae = Object.assign(C, {
156
+ Header: P,
157
+ Body: D,
158
+ Section: L,
159
+ Group: A,
160
+ GroupItems: G,
161
+ Search: T,
162
+ Notices: B,
163
+ Divider: H,
164
+ Footer: U,
165
+ Switcher: v,
166
+ Account: y,
167
+ Usage: V,
168
+ Panel: F
169
+ });
170
+ export {
171
+ ae as Sidebar,
172
+ ae as default
173
+ };
174
+ //# sourceMappingURL=Sidebar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Sidebar.js","sources":["../../src/components/Sidebar.tsx"],"sourcesContent":["import React, { forwardRef, useMemo } from 'react';\nimport CaretLeftIcon from './CustomIcons/CaretLeftIcon';\nimport CaretRightIcon from './CustomIcons/CaretRightIcon';\nimport ChevronsUpDownIcon from './CustomIcons/ChevronsUpDownIcon';\nimport Tooltip from './Tooltip';\nimport UsageCard, { type UsageCardProps } from './UsageCard';\nimport { isExpanded } from './ariaState';\nimport { BORDER, NO_SCROLLBAR } from './chromeStyles';\nimport { FOCUS_RING } from './focusRing';\nimport {\n SIDEBAR_POPOVER_WIDTH_PX,\n SIDEBAR_WIDTH_PX,\n SidebarContext,\n useSidebarCollapsed,\n} from './sidebarContext';\n\nconst useSidebar = () => ({ collapsed: useSidebarCollapsed() });\n\nconst POPOVER_BORDER_PX = 1;\nconst TOGGLE_SIZE_PX = 24;\nconst CHEVRONS = { width: 8, height: 14 } as const;\n\nexport interface SidebarProps {\n collapsed?: boolean;\n onToggleCollapse?: () => void;\n expandLabel?: string;\n collapseLabel?: string;\n 'aria-label'?: string;\n children: React.ReactNode;\n}\n\nconst TOGGLE_LAYER =\n 'fixed top-[25px] z-[101] invisible opacity-0 [will-change:opacity] transition-[left,opacity,visibility] duration-200 ease-in-out group-hover/sidebar:visible group-hover/sidebar:opacity-100 group-has-[:focus-visible]/sidebar:visible group-has-[:focus-visible]/sidebar:opacity-100';\n\nconst SidebarRoot: React.FC<SidebarProps> = ({\n collapsed = false,\n onToggleCollapse,\n expandLabel = 'Expand menu',\n collapseLabel = 'Collapse menu',\n 'aria-label': ariaLabel = 'Main',\n children,\n}) => {\n const toggleLabel = collapsed ? expandLabel : collapseLabel;\n const context = useMemo(() => ({ collapsed }), [collapsed]);\n const width = collapsed ? SIDEBAR_WIDTH_PX.collapsed : SIDEBAR_WIDTH_PX.expanded;\n\n return (\n <SidebarContext.Provider value={context}>\n <aside\n className=\"group/sidebar fixed top-0 bottom-0 left-0 z-[100] box-border pt-[9px] bg-[var(--malachite-card-sunken-background,rgb(250,250,250))] transition-[width] duration-200 ease-in-out\"\n style={{ width }}\n >\n <nav aria-label={ariaLabel} className=\"flex h-full flex-col\">\n {children}\n </nav>\n {onToggleCollapse && (\n <div className={TOGGLE_LAYER} style={{ left: width - TOGGLE_SIZE_PX / 2 }}>\n <Tooltip text={toggleLabel} placement=\"right\" describesTrigger={false}>\n <button\n type=\"button\"\n aria-label={toggleLabel}\n onClick={onToggleCollapse}\n className={`m-0 inline-flex size-6 cursor-pointer items-center justify-center rounded-lg border border-solid p-0 ${BORDER} bg-[var(--malachite-card-background,rgb(255,255,255))] text-[var(--malachite-text-secondary,rgb(123,123,123))] [box-shadow:var(--malachite-shadow-default,0px_1px_0px_0px_rgba(0,0,0,0.15))] transition-colors duration-200 hover:border-[var(--malachite-text-placeholder,rgb(187,187,187))] hover:text-[var(--malachite-text-primary,rgb(10,10,10))] ${FOCUS_RING}`}\n >\n {collapsed ? (\n <CaretRightIcon size={12} />\n ) : (\n <CaretLeftIcon size={12} />\n )}\n </button>\n </Tooltip>\n </div>\n )}\n </aside>\n </SidebarContext.Provider>\n );\n};\n\nconst Header: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const { collapsed } = useSidebar();\n return (\n <div\n className={`box-border flex h-14 shrink-0 items-center border-0 border-b border-solid ${BORDER} py-[6px] ${collapsed ? 'px-1' : 'px-2'}`}\n >\n {children}\n </div>\n );\n};\n\nconst Body: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className={`min-h-0 flex-1 overflow-x-hidden overflow-y-auto ${NO_SCROLLBAR}`}>\n {children}\n </div>\n);\n\nconst Section: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const { collapsed } = useSidebar();\n return (\n <div\n className={`flex flex-col gap-[2px] py-[2px] ${collapsed ? 'items-center px-3' : 'px-4'}`}\n >\n {children}\n </div>\n );\n};\n\nconst Group: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"my-[2px] flex flex-col gap-[6px]\">{children}</div>\n);\n\nconst GroupItems: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div className=\"flex flex-col gap-[6px]\">{children}</div>\n);\n\nconst Search: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const { collapsed } = useSidebar();\n return (\n <div className={`flex pt-5 pb-[18px] ${collapsed ? 'justify-center px-3' : 'px-4'}`}>\n {children}\n </div>\n );\n};\n\nconst Notices: React.FC<{ children: React.ReactNode; 'aria-label': string }> = ({\n children,\n 'aria-label': ariaLabel,\n}) => {\n const { collapsed } = useSidebar();\n if (collapsed) {\n return null;\n }\n return (\n <div role=\"status\" aria-label={ariaLabel} className=\"flex flex-col gap-2 px-3 pt-4\">\n {children}\n </div>\n );\n};\n\nconst Divider: React.FC = () => {\n const { collapsed } = useSidebar();\n if (collapsed) {\n return null;\n }\n return <hr className={`m-0 my-2 h-0 shrink-0 border-0 border-t border-solid ${BORDER}`} />;\n};\n\nconst Footer: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const { collapsed } = useSidebar();\n return (\n <div\n className={`mt-1 flex shrink-0 border-0 border-t border-solid ${BORDER} py-3 ${collapsed ? 'justify-center px-2' : 'px-4'}`}\n >\n {children}\n </div>\n );\n};\n\ntype SidebarButtonAttributes = Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'style' | 'color' | 'children' | 'title' | 'name'\n>;\n\nexport interface SidebarSwitcherProps extends SidebarButtonAttributes {\n logo: React.ReactNode;\n title: string;\n subtitle?: string;\n}\n\nconst Switcher = forwardRef<HTMLButtonElement, SidebarSwitcherProps>(\n ({ logo, title, subtitle, className = '', ...rest }, ref) => {\n const { collapsed } = useSidebar();\n return (\n <button\n ref={ref}\n type=\"button\"\n aria-label={collapsed ? title : undefined}\n {...rest}\n className={`group/switcher m-0 box-border flex h-full w-full min-w-0 cursor-pointer items-center gap-3 rounded-lg border-0 bg-transparent font-sans text-left ${collapsed ? 'justify-center p-1' : 'justify-between px-4 py-[6px]'} ${FOCUS_RING} ${className}`.trim()}\n >\n <span className=\"flex min-w-0 items-center gap-4\">\n <span\n aria-hidden=\"true\"\n className=\"relative top-[-2.5px] flex size-6 shrink-0 items-center justify-center overflow-hidden rounded-md [&_img]:size-6 [&_img]:object-contain\"\n >\n {logo}\n </span>\n {!collapsed && (\n <span className=\"flex min-w-0 flex-col gap-1\">\n <span className=\"block truncate text-[length:var(--malachite-font-size-medium,14px)] leading-[14px] font-medium text-[var(--malachite-text-primary,rgb(10,10,10))]\">\n {title}\n </span>\n {subtitle && (\n <span className=\"block truncate text-[12px] leading-[12px] font-normal text-[var(--malachite-text-secondary,rgb(123,123,123))]\">\n {subtitle}\n </span>\n )}\n </span>\n )}\n </span>\n {!collapsed && (\n <span className=\"flex shrink-0 text-[var(--malachite-text-secondary,rgb(123,123,123))] transition-colors group-hover/switcher:text-[var(--malachite-text-primary,rgb(10,10,10))]\">\n <ChevronsUpDownIcon style={CHEVRONS} />\n </span>\n )}\n </button>\n );\n },\n);\nSwitcher.displayName = 'Sidebar.Switcher';\n\nexport interface SidebarAccountProps extends SidebarButtonAttributes {\n avatar?: React.ReactNode;\n initials?: string;\n name: string;\n}\n\nconst INITIALS = `inline-flex items-center justify-center rounded-[var(--malachite-radius-md,6px)] border border-solid ${BORDER} bg-[var(--malachite-pillbutton-background,rgb(241,241,241))] supports-[color:color-mix(in_srgb,red,red)]:border-[color-mix(in_srgb,var(--malachite-text-placeholder,rgb(187,187,187))_20%,transparent)] supports-[color:color-mix(in_srgb,red,red)]:bg-[color-mix(in_srgb,var(--malachite-text-placeholder,rgb(187,187,187))_10%,transparent)] px-1 py-[3px] text-[length:var(--malachite-font-size-small,13px)] leading-[12px] font-semibold text-[var(--malachite-text-secondary,rgb(123,123,123))]`;\n\nconst Account = forwardRef<HTMLButtonElement, SidebarAccountProps>(\n ({ avatar, initials, name, className = '', ...rest }, ref) => {\n const { collapsed } = useSidebar();\n const button = (\n <button\n ref={ref}\n type=\"button\"\n aria-label={collapsed ? name : undefined}\n {...rest}\n className={`group/account m-0 box-border flex min-h-8 w-full cursor-pointer items-center gap-3 rounded-lg border-0 bg-transparent font-sans ${collapsed ? 'justify-center p-0' : 'justify-between px-2'} ${FOCUS_RING} ${className}`.trim()}\n >\n <span className=\"flex min-w-0 items-center gap-3\">\n <span aria-hidden={collapsed ? undefined : true} className=\"flex shrink-0\">\n {avatar ?? (initials ? <span className={INITIALS}>{initials}</span> : null)}\n </span>\n {!collapsed && (\n <span className=\"truncate text-[length:var(--malachite-font-size-medium,14px)] leading-[22px] font-semibold text-[var(--malachite-text-primary,rgb(10,10,10))]\">\n {name}\n </span>\n )}\n </span>\n {!collapsed && (\n <span className=\"flex shrink-0 text-[var(--malachite-text-secondary,rgb(123,123,123))] transition-colors group-hover/account:text-[var(--malachite-text-primary,rgb(10,10,10))]\">\n <ChevronsUpDownIcon style={CHEVRONS} />\n </span>\n )}\n </button>\n );\n return collapsed ? (\n <Tooltip\n text={name}\n placement=\"right\"\n describesTrigger={false}\n suppressed={isExpanded(rest['aria-expanded'])}\n >\n {button}\n </Tooltip>\n ) : (\n button\n );\n },\n);\nAccount.displayName = 'Sidebar.Account';\n\nconst Usage: React.FC<UsageCardProps> = (props) => {\n const { collapsed } = useSidebar();\n if (collapsed) {\n return null;\n }\n return (\n <div className=\"shrink-0 px-3 pt-3 pb-4\">\n <UsageCard {...props} />\n </div>\n );\n};\n\nconst Panel: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <div\n className=\"flex flex-col\"\n style={{ width: SIDEBAR_POPOVER_WIDTH_PX - 2 * POPOVER_BORDER_PX }}\n >\n {children}\n </div>\n);\n\nexport const Sidebar = Object.assign(SidebarRoot, {\n Header,\n Body,\n Section,\n Group,\n GroupItems,\n Search,\n Notices,\n Divider,\n Footer,\n Switcher,\n Account,\n Usage,\n Panel,\n});\n\nexport default Sidebar;\n"],"names":["useSidebar","useSidebarCollapsed","POPOVER_BORDER_PX","TOGGLE_SIZE_PX","CHEVRONS","TOGGLE_LAYER","SidebarRoot","collapsed","onToggleCollapse","expandLabel","collapseLabel","ariaLabel","children","toggleLabel","context","useMemo","width","SIDEBAR_WIDTH_PX","jsx","SidebarContext","jsxs","Tooltip","BORDER","FOCUS_RING","CaretRightIcon","CaretLeftIcon","Header","Body","NO_SCROLLBAR","Section","Group","GroupItems","Search","Notices","Divider","Footer","Switcher","forwardRef","logo","title","subtitle","className","rest","ref","ChevronsUpDownIcon","INITIALS","Account","avatar","initials","name","button","isExpanded","Usage","props","UsageCard","Panel","SIDEBAR_POPOVER_WIDTH_PX","Sidebar"],"mappings":"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"}
@@ -1,72 +1,77 @@
1
- import { jsx as l, jsxs as H, Fragment as D } from "react/jsx-runtime";
2
- import E, { useState as x, useRef as f, useCallback as J, useId as Q, useEffect as P, useInsertionEffect as Z } from "react";
3
- import { createPortal as ee } from "react-dom";
4
- import { ensureOverlayStyles as te, overlayIdentity as ne } from "./portalOverlay.js";
5
- import { useTopLayer as re } from "./topLayer.js";
6
- const oe = new RegExp("(?<=[/\\\\.\\-_?&#=:@])"), ie = (n) => n.split(oe).map((i, p) => /* @__PURE__ */ H(E.Fragment, { children: [
7
- i,
8
- /* @__PURE__ */ l("wbr", {})
9
- ] }, p)), se = {
1
+ import { jsx as c, jsxs as j, Fragment as Z } from "react/jsx-runtime";
2
+ import L, { useState as p, useRef as h, useCallback as ee, useId as te, useEffect as R, useInsertionEffect as ne } from "react";
3
+ import { createPortal as re } from "react-dom";
4
+ import { ensureOverlayStyles as oe, overlayIdentity as ie } from "./portalOverlay.js";
5
+ import { useTopLayer as ae } from "./topLayer.js";
6
+ const se = new RegExp("(?<=[/\\\\.\\-_?&#=:@])"), le = (n) => n.split(se).map((a, g) => /* @__PURE__ */ j(L.Fragment, { children: [
7
+ a,
8
+ /* @__PURE__ */ c("wbr", {})
9
+ ] }, g)), ce = {
10
10
  minWidth: 0,
11
11
  overflow: "hidden"
12
- }, C = {
12
+ }, V = {
13
13
  flex: 1,
14
14
  minWidth: 0
15
- }, V = 8, pe = ({
15
+ }, H = 8, ge = ({
16
16
  text: n,
17
- children: i,
18
- delay: p = 1,
19
- wrapChildren: j = !1,
20
- triggerAs: k = "div",
21
- inline: R = !1,
22
- placement: z = "top",
23
- isShrinkable: L = !1,
24
- maxWidth: m = "320px",
25
- fill: h = !1,
26
- shouldShow: c,
27
- describesTrigger: T = !0
17
+ children: a,
18
+ delay: g = 1,
19
+ wrapChildren: k = !1,
20
+ triggerAs: z = "div",
21
+ inline: S = !1,
22
+ placement: N = "top",
23
+ isShrinkable: T = !1,
24
+ maxWidth: v = "320px",
25
+ fill: w = !1,
26
+ shouldShow: d,
27
+ suppressed: o = !1,
28
+ describesTrigger: F = !0
28
29
  }) => {
29
- const N = L || h ? { ...L ? se : {}, ...h ? C : {} } : void 0, [t, g] = x(!1), [d, O] = x(!1), u = f(null), r = f(null), o = J(() => {
30
- u.current && (clearTimeout(u.current), u.current = null), r.current !== null && (cancelAnimationFrame(r.current), r.current = null);
31
- }, []), F = () => {
32
- O(!0), r.current !== null && cancelAnimationFrame(r.current), r.current = requestAnimationFrame(() => {
33
- r.current = null, g(!0);
30
+ const O = T || w ? { ...T ? ce : {}, ...w ? V : {} } : void 0, [t, f] = p(!1), [u, Y] = p(!1), m = h(null), i = h(null), r = ee(() => {
31
+ m.current && (clearTimeout(m.current), m.current = null), i.current !== null && (cancelAnimationFrame(i.current), i.current = null);
32
+ }, []), I = () => {
33
+ Y(!0), i.current !== null && cancelAnimationFrame(i.current), i.current = requestAnimationFrame(() => {
34
+ i.current = null, f(!0);
34
35
  });
35
- }, v = f(null), y = f(null);
36
- re(v, t);
37
- const I = Q(), s = n != null && n !== "" && n !== !1, Y = (e) => {
38
- e.stopPropagation(), !(!s || c && !c()) && (o(), u.current = setTimeout(() => {
39
- F();
40
- }, p * 1e3));
41
- }, U = (e) => {
42
- e.stopPropagation(), o(), g(!1);
43
- }, q = () => {
44
- !s || c && !c() || (o(), F());
36
+ }, y = h(null), b = h(null);
37
+ ae(y, t);
38
+ const A = te(), s = n != null && n !== "" && n !== !1, U = (e) => {
39
+ e.stopPropagation(), !(!s || o || d && !d()) && (r(), m.current = setTimeout(() => {
40
+ I();
41
+ }, g * 1e3));
42
+ }, q = (e) => {
43
+ e.stopPropagation(), r(), f(!1);
45
44
  }, G = () => {
46
- o(), g(!1);
47
- }, [, S] = x({});
48
- P(() => {
45
+ !s || o || d && !d() || (r(), I());
46
+ }, K = () => {
47
+ r(), f(!1);
48
+ }, [X, D] = p(o);
49
+ o !== X && (D(o), o && f(!1)), R(() => {
50
+ o && r();
51
+ }, [o, r]);
52
+ const [, B] = p({});
53
+ R(() => {
49
54
  if (!t)
50
55
  return () => {
51
- o();
56
+ r();
52
57
  };
53
58
  const e = () => {
54
- S({});
59
+ B({});
55
60
  };
56
61
  return window.addEventListener("scroll", e, !0), window.addEventListener("resize", e), () => {
57
- o(), window.removeEventListener("scroll", e, !0), window.removeEventListener("resize", e);
62
+ r(), window.removeEventListener("scroll", e, !0), window.removeEventListener("resize", e);
58
63
  };
59
- }, [t, o]), P(() => {
60
- t && S({});
64
+ }, [t, r]), R(() => {
65
+ t && B({});
61
66
  }, [t]);
62
- const K = () => {
63
- if (!y.current)
67
+ const J = () => {
68
+ if (!b.current)
64
69
  return { display: "none" };
65
- const e = y.current.getBoundingClientRect(), a = {
70
+ const e = b.current.getBoundingClientRect(), l = {
66
71
  position: "fixed",
67
72
  display: "flex",
68
73
  width: "max-content",
69
- maxWidth: typeof m == "number" ? `${m}px` : m,
74
+ maxWidth: typeof v == "number" ? `${v}px` : v,
70
75
  minWidth: "32px",
71
76
  minHeight: "32px",
72
77
  padding: "8px 12px",
@@ -84,90 +89,90 @@ const oe = new RegExp("(?<=[/\\\\.\\-_?&#=:@])"), ie = (n) => n.split(oe).map((i
84
89
  opacity: t ? 1 : 0,
85
90
  visibility: t ? "visible" : "hidden",
86
91
  transition: "opacity 150ms ease-in-out, transform 150ms ease-in-out, visibility 150ms ease-in-out"
87
- }, b = () => {
88
- var $;
89
- const w = e.left + e.width / 2, B = (($ = v.current) == null ? void 0 : $.getBoundingClientRect().width) ?? 0;
90
- if (B === 0)
91
- return w;
92
- const M = B / 2, W = V + M, _ = window.innerWidth - V - M;
93
- return W > _ ? w : Math.min(Math.max(w, W), _);
92
+ }, x = () => {
93
+ var C;
94
+ const E = e.left + e.width / 2, M = ((C = y.current) == null ? void 0 : C.getBoundingClientRect().width) ?? 0;
95
+ if (M === 0)
96
+ return E;
97
+ const _ = M / 2, $ = H + _, P = window.innerWidth - H - _;
98
+ return $ > P ? E : Math.min(Math.max(E, $), P);
94
99
  };
95
- switch (z) {
100
+ switch (N) {
96
101
  case "top":
97
102
  return {
98
- ...a,
103
+ ...l,
99
104
  top: e.top - 8,
100
- left: b(),
105
+ left: x(),
101
106
  transform: `translate(-50%, -100%) ${t ? "scale(1)" : "scale(0.95)"}`
102
107
  };
103
108
  case "bottom":
104
109
  return {
105
- ...a,
110
+ ...l,
106
111
  top: e.bottom + 8,
107
- left: b(),
112
+ left: x(),
108
113
  transform: `translateX(-50%) ${t ? "scale(1)" : "scale(0.95)"}`
109
114
  };
110
115
  case "left":
111
116
  return {
112
- ...a,
117
+ ...l,
113
118
  top: e.top + e.height / 2,
114
119
  left: e.left - 8,
115
120
  transform: `translate(-100%, -50%) ${t ? "scale(1)" : "scale(0.95)"}`
116
121
  };
117
122
  case "right":
118
123
  return {
119
- ...a,
124
+ ...l,
120
125
  top: e.top + e.height / 2,
121
126
  left: e.right + 8,
122
127
  transform: `translateY(-50%) ${t ? "scale(1)" : "scale(0.95)"}`
123
128
  };
124
129
  default:
125
130
  return {
126
- ...a,
131
+ ...l,
127
132
  top: e.top - 8,
128
- left: b(),
133
+ left: x(),
129
134
  transform: `translate(-50%, -100%) ${t ? "scale(1)" : "scale(0.95)"}`
130
135
  };
131
136
  }
132
- }, A = s && d && T ? I : void 0;
133
- Z(() => {
134
- s && d && te();
135
- }, [s, d]);
136
- const X = j || !E.isValidElement(i) ? /* @__PURE__ */ l("span", { "aria-describedby": A, style: h ? C : void 0, children: i }) : E.cloneElement(i, {
137
- "aria-describedby": [i.props["aria-describedby"], A].filter(Boolean).join(" ") || void 0
137
+ }, W = s && u && F ? A : void 0;
138
+ ne(() => {
139
+ s && u && oe();
140
+ }, [s, u]);
141
+ const Q = k || !L.isValidElement(a) ? /* @__PURE__ */ c("span", { "aria-describedby": W, style: w ? V : void 0, children: a }) : L.cloneElement(a, {
142
+ "aria-describedby": [a.props["aria-describedby"], W].filter(Boolean).join(" ") || void 0
138
143
  });
139
- return /* @__PURE__ */ H(D, { children: [
140
- /* @__PURE__ */ l(
141
- R ? "span" : k,
144
+ return /* @__PURE__ */ j(Z, { children: [
145
+ /* @__PURE__ */ c(
146
+ S ? "span" : z,
142
147
  {
143
- ref: y,
144
- className: `relative ${R ? "inline-flex max-w-full align-middle" : "flex"} items-center`,
145
- style: N,
146
- onMouseEnter: Y,
147
- onMouseLeave: U,
148
- onFocus: q,
149
- onBlur: G,
150
- children: X
148
+ ref: b,
149
+ className: `relative ${S ? "inline-flex max-w-full align-middle" : "flex"} items-center`,
150
+ style: O,
151
+ onMouseEnter: U,
152
+ onMouseLeave: q,
153
+ onFocus: G,
154
+ onBlur: K,
155
+ children: Q
151
156
  }
152
157
  ),
153
- s && d && ee(
154
- /* @__PURE__ */ l(
158
+ s && u && re(
159
+ /* @__PURE__ */ c(
155
160
  "div",
156
161
  {
157
- ref: v,
158
- id: I,
162
+ ref: y,
163
+ id: A,
159
164
  role: "tooltip",
160
- "aria-hidden": T ? void 0 : !0,
161
- ...ne("tooltip"),
162
- style: K(),
163
- children: /* @__PURE__ */ l(
165
+ "aria-hidden": F ? void 0 : !0,
166
+ ...ie("tooltip"),
167
+ style: J(),
168
+ children: /* @__PURE__ */ c(
164
169
  "span",
165
170
  {
166
171
  style: {
167
172
  minWidth: 0,
168
173
  overflowWrap: "anywhere"
169
174
  },
170
- children: typeof n == "string" ? ie(n) : n
175
+ children: typeof n == "string" ? le(n) : n
171
176
  }
172
177
  )
173
178
  }
@@ -177,6 +182,6 @@ const oe = new RegExp("(?<=[/\\\\.\\-_?&#=:@])"), ie = (n) => n.split(oe).map((i
177
182
  ] });
178
183
  };
179
184
  export {
180
- pe as default
185
+ ge as default
181
186
  };
182
187
  //# sourceMappingURL=Tooltip.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.js","sources":["../../src/components/Tooltip.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useId, useInsertionEffect, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ensureOverlayStyles, overlayIdentity } from './portalOverlay';\nimport { useTopLayer } from './topLayer';\n\n// Split after each delimiter so long values (URLs, dotted paths) wrap at \"/\" or \".\"\n// instead of mid-token. <wbr> is copy-safe (a zero-width space would corrupt a copied\n// URL); overflow-wrap still handles a single run too long to fit.\nconst WRAP_AFTER = /(?<=[/\\\\.\\-_?&#=:@])/;\nconst withBreakOpportunities = (value: string): React.ReactNode =>\n value.split(WRAP_AFTER).map((chunk, i) => (\n <React.Fragment key={i}>\n {chunk}\n <wbr />\n </React.Fragment>\n ));\n\ninterface TooltipProps {\n text: React.ReactNode | string;\n children: React.ReactNode;\n delay?: number;\n wrapChildren?: boolean;\n placement?: 'top' | 'bottom' | 'left' | 'right';\n isShrinkable?: boolean;\n fill?: boolean;\n /** Max width of tooltip. Default: 320px */\n maxWidth?: number | string;\n /** Called synchronously when the trigger is hovered/focused; return false to\n * suppress the tooltip for this interaction. Lets wrappers defer expensive\n * checks (e.g. truncation measurement) to interaction time instead of mount. */\n shouldShow?: () => boolean;\n triggerAs?: 'div' | 'span';\n inline?: boolean;\n /** Whether the tooltip acts as the trigger's accessible description. False where the\n * trigger already points at the same sentence on screen, so it is not announced twice. */\n describesTrigger?: boolean;\n}\n\nconst SHRINKABLE_STYLE: React.CSSProperties = {\n minWidth: 0,\n overflow: 'hidden',\n};\n\nconst FILL_STYLE: React.CSSProperties = {\n flex: 1,\n minWidth: 0,\n};\n\n/** Kept clear of the viewport edge so a clamped tooltip does not sit flush against it. */\nconst VIEWPORT_MARGIN = 8;\n\nconst Tooltip: React.FC<TooltipProps> = ({\n text,\n children,\n delay = 1,\n wrapChildren = false,\n triggerAs = 'div',\n inline = false,\n placement = 'top',\n isShrinkable = false,\n maxWidth = '320px',\n fill = false,\n shouldShow,\n describesTrigger = true,\n}) => {\n const triggerStyle =\n isShrinkable || fill\n ? { ...(isShrinkable ? SHRINKABLE_STYLE : {}), ...(fill ? FILL_STYLE : {}) }\n : undefined;\n\n const [isVisible, setIsVisible] = useState(false);\n // Portal mounts on first show, not on mount: an at-rest tooltip otherwise\n // costs a hidden document.body node plus a getBoundingClientRect per render —\n // multiplied by every row in a large table.\n const [hasShown, setHasShown] = useState(false);\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const showFrameRef = useRef<number | null>(null);\n\n const cancelPendingShow = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n if (showFrameRef.current !== null) {\n cancelAnimationFrame(showFrameRef.current);\n showFrameRef.current = null;\n }\n }, []);\n\n const scheduleVisible = () => {\n // Two steps so the portal mounts hidden first and the fade-in transition\n // still runs on the very first show. The frame is tracked so leave/blur/\n // unmount can cancel a show that is already past its delay.\n setHasShown(true);\n if (showFrameRef.current !== null) {\n cancelAnimationFrame(showFrameRef.current);\n }\n showFrameRef.current = requestAnimationFrame(() => {\n showFrameRef.current = null;\n setIsVisible(true);\n });\n };\n const tooltipRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n\n // Tied to visibility, not mount: the node is latched into the DOM after its first show, and\n // re-entering on each show keeps a tooltip above the panel it is annotating.\n useTopLayer(tooltipRef, isVisible);\n\n const tooltipId = useId();\n\n const hasText = text !== null && text !== undefined && text !== '' && text !== false;\n\n const handleMouseEnter = (e: React.MouseEvent) => {\n e.stopPropagation();\n\n if (!hasText || (shouldShow && !shouldShow())) {\n return;\n }\n\n cancelPendingShow();\n\n timeoutRef.current = setTimeout(() => {\n scheduleVisible();\n }, delay * 1000);\n };\n\n const handleMouseLeave = (e: React.MouseEvent) => {\n e.stopPropagation();\n\n cancelPendingShow();\n setIsVisible(false);\n };\n\n const handleFocus = () => {\n if (!hasText || (shouldShow && !shouldShow())) {\n return;\n }\n\n cancelPendingShow();\n scheduleVisible();\n };\n\n const handleBlur = () => {\n cancelPendingShow();\n setIsVisible(false);\n };\n\n const [, forceUpdate] = useState({});\n\n useEffect(() => {\n // Only a VISIBLE tooltip needs to track scroll/resize; keeping global\n // listeners per mounted instance made every scroll event fan out across\n // every tooltip on the page.\n if (!isVisible) {\n return () => {\n cancelPendingShow();\n };\n }\n const handleUpdate = () => {\n forceUpdate({});\n };\n\n window.addEventListener('scroll', handleUpdate, true);\n window.addEventListener('resize', handleUpdate);\n\n return () => {\n cancelPendingShow();\n window.removeEventListener('scroll', handleUpdate, true);\n window.removeEventListener('resize', handleUpdate);\n };\n }, [isVisible, cancelPendingShow]);\n\n // The first render that mounts the tooltip has no measured width yet, so the clamp below\n // cannot run on it. One extra pass once it is in the DOM gives the clamp its measurement\n // — before the opacity transition finishes, so nothing is seen sliding into place.\n useEffect(() => {\n if (isVisible) {\n forceUpdate({});\n }\n }, [isVisible]);\n\n const getTooltipStyles = (): React.CSSProperties => {\n if (!triggerRef.current) {\n return { display: 'none' };\n }\n\n const rect = triggerRef.current.getBoundingClientRect();\n\n const baseStyles: React.CSSProperties = {\n position: 'fixed',\n display: 'flex',\n width: 'max-content',\n maxWidth: typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth,\n minWidth: '32px',\n minHeight: '32px',\n padding: '8px 12px',\n alignItems: 'center',\n gap: '8px',\n borderRadius: '12px',\n backgroundColor: 'var(--malachite-tooltip-background, rgb(59, 59, 59))',\n color: 'var(--malachite-tooltip-foreground, rgb(255, 255, 255))',\n boxShadow: 'var(--malachite-tooltip-shadow, 0px 0px 10px 0px rgba(0, 0, 0, 0.20))',\n fontSize: '14px',\n lineHeight: '1.4',\n whiteSpace: 'normal',\n textAlign: 'left',\n pointerEvents: 'none',\n opacity: isVisible ? 1 : 0,\n visibility: isVisible ? 'visible' : 'hidden',\n transition:\n 'opacity 150ms ease-in-out, transform 150ms ease-in-out, visibility 150ms ease-in-out',\n };\n\n // A trigger near the viewport edge would otherwise centre a wide tooltip half off\n // screen, where the panel or the window crops it. Clamping the CENTRE keeps the\n // `translateX(-50%)` placement honest: the box stays put, it just stops short.\n const centeredLeft = (): number => {\n const desired = rect.left + rect.width / 2;\n const width = tooltipRef.current?.getBoundingClientRect().width ?? 0;\n\n if (width === 0) {\n return desired;\n }\n\n const half = width / 2;\n const min = VIEWPORT_MARGIN + half;\n const max = window.innerWidth - VIEWPORT_MARGIN - half;\n\n // A tooltip wider than the viewport has no in-bounds centre; leave it centred\n // rather than pinning it to a nonsensical one.\n return min > max ? desired : Math.min(Math.max(desired, min), max);\n };\n\n switch (placement) {\n case 'top':\n return {\n ...baseStyles,\n top: rect.top - 8,\n left: centeredLeft(),\n transform: `translate(-50%, -100%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n case 'bottom':\n return {\n ...baseStyles,\n top: rect.bottom + 8,\n left: centeredLeft(),\n transform: `translateX(-50%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n case 'left':\n return {\n ...baseStyles,\n top: rect.top + rect.height / 2,\n left: rect.left - 8,\n transform: `translate(-100%, -50%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n case 'right':\n return {\n ...baseStyles,\n top: rect.top + rect.height / 2,\n left: rect.right + 8,\n transform: `translateY(-50%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n default:\n return {\n ...baseStyles,\n top: rect.top - 8,\n left: centeredLeft(),\n transform: `translate(-50%, -100%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n }\n };\n\n // Only reference the tooltip id once the portal can exist — a dangling\n // aria-describedby (text set, never shown) confuses assistive tech.\n const describedBy = hasText && hasShown && describesTrigger ? tooltipId : undefined;\n useInsertionEffect(() => {\n if (hasText && hasShown) {\n ensureOverlayStyles();\n }\n }, [hasText, hasShown]);\n const renderedChildren =\n wrapChildren || !React.isValidElement(children) ? (\n <span aria-describedby={describedBy} style={fill ? FILL_STYLE : undefined}>\n {children}\n </span>\n ) : (\n React.cloneElement(children as React.ReactElement, {\n 'aria-describedby':\n [(children as React.ReactElement).props['aria-describedby'], describedBy]\n .filter(Boolean)\n .join(' ') || undefined,\n })\n );\n\n const Trigger = inline ? 'span' : triggerAs;\n\n // Create the tooltip content without its own shadow root\n return (\n <>\n <Trigger\n ref={triggerRef}\n className={`relative ${inline ? 'inline-flex max-w-full align-middle' : 'flex'} items-center`}\n style={triggerStyle}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onFocus={handleFocus}\n onBlur={handleBlur}\n >\n {renderedChildren}\n </Trigger>\n\n {hasText &&\n hasShown &&\n createPortal(\n <div\n ref={tooltipRef}\n id={tooltipId}\n role=\"tooltip\"\n // Nothing references it, and the sentence is already on screen and\n // described: left in the tree it is a second copy to read past.\n aria-hidden={describesTrigger ? undefined : true}\n {...overlayIdentity('tooltip')}\n style={getTooltipStyles()}\n >\n {/* min-w-0 + overflow-wrap let long values wrap within maxWidth. */}\n <span\n style={{\n minWidth: 0,\n overflowWrap: 'anywhere',\n }}\n >\n {typeof text === 'string' ? withBreakOpportunities(text) : text}\n </span>\n </div>,\n document.body,\n )}\n </>\n );\n};\n\nexport default Tooltip;\n"],"names":["WRAP_AFTER","withBreakOpportunities","value","chunk","i","jsxs","React","SHRINKABLE_STYLE","FILL_STYLE","VIEWPORT_MARGIN","Tooltip","text","children","delay","wrapChildren","triggerAs","inline","placement","isShrinkable","maxWidth","fill","shouldShow","describesTrigger","triggerStyle","isVisible","setIsVisible","useState","hasShown","setHasShown","timeoutRef","useRef","showFrameRef","cancelPendingShow","useCallback","scheduleVisible","tooltipRef","triggerRef","useTopLayer","tooltipId","useId","hasText","handleMouseEnter","handleMouseLeave","handleFocus","handleBlur","forceUpdate","useEffect","handleUpdate","getTooltipStyles","rect","baseStyles","centeredLeft","desired","width","_a","half","min","max","describedBy","useInsertionEffect","ensureOverlayStyles","renderedChildren","jsx","Fragment","createPortal","overlayIdentity"],"mappings":"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"}
1
+ {"version":3,"file":"Tooltip.js","sources":["../../src/components/Tooltip.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useId, useInsertionEffect, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport { ensureOverlayStyles, overlayIdentity } from './portalOverlay';\nimport { useTopLayer } from './topLayer';\n\n// Split after each delimiter so long values (URLs, dotted paths) wrap at \"/\" or \".\"\n// instead of mid-token. <wbr> is copy-safe (a zero-width space would corrupt a copied\n// URL); overflow-wrap still handles a single run too long to fit.\nconst WRAP_AFTER = /(?<=[/\\\\.\\-_?&#=:@])/;\nconst withBreakOpportunities = (value: string): React.ReactNode =>\n value.split(WRAP_AFTER).map((chunk, i) => (\n <React.Fragment key={i}>\n {chunk}\n <wbr />\n </React.Fragment>\n ));\n\ninterface TooltipProps {\n text: React.ReactNode | string;\n children: React.ReactNode;\n delay?: number;\n wrapChildren?: boolean;\n placement?: 'top' | 'bottom' | 'left' | 'right';\n isShrinkable?: boolean;\n fill?: boolean;\n /** Max width of tooltip. Default: 320px */\n maxWidth?: number | string;\n /** Called synchronously when the trigger is hovered/focused; return false to\n * suppress the tooltip for this interaction. Lets wrappers defer expensive\n * checks (e.g. truncation measurement) to interaction time instead of mount. */\n shouldShow?: () => boolean;\n suppressed?: boolean;\n triggerAs?: 'div' | 'span';\n inline?: boolean;\n /** Whether the tooltip acts as the trigger's accessible description. False where the\n * trigger already points at the same sentence on screen, so it is not announced twice. */\n describesTrigger?: boolean;\n}\n\nconst SHRINKABLE_STYLE: React.CSSProperties = {\n minWidth: 0,\n overflow: 'hidden',\n};\n\nconst FILL_STYLE: React.CSSProperties = {\n flex: 1,\n minWidth: 0,\n};\n\n/** Kept clear of the viewport edge so a clamped tooltip does not sit flush against it. */\nconst VIEWPORT_MARGIN = 8;\n\nconst Tooltip: React.FC<TooltipProps> = ({\n text,\n children,\n delay = 1,\n wrapChildren = false,\n triggerAs = 'div',\n inline = false,\n placement = 'top',\n isShrinkable = false,\n maxWidth = '320px',\n fill = false,\n shouldShow,\n suppressed = false,\n describesTrigger = true,\n}) => {\n const triggerStyle =\n isShrinkable || fill\n ? { ...(isShrinkable ? SHRINKABLE_STYLE : {}), ...(fill ? FILL_STYLE : {}) }\n : undefined;\n\n const [isVisible, setIsVisible] = useState(false);\n // Portal mounts on first show, not on mount: an at-rest tooltip otherwise\n // costs a hidden document.body node plus a getBoundingClientRect per render —\n // multiplied by every row in a large table.\n const [hasShown, setHasShown] = useState(false);\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const showFrameRef = useRef<number | null>(null);\n\n const cancelPendingShow = useCallback(() => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n if (showFrameRef.current !== null) {\n cancelAnimationFrame(showFrameRef.current);\n showFrameRef.current = null;\n }\n }, []);\n\n const scheduleVisible = () => {\n // Two steps so the portal mounts hidden first and the fade-in transition\n // still runs on the very first show. The frame is tracked so leave/blur/\n // unmount can cancel a show that is already past its delay.\n setHasShown(true);\n if (showFrameRef.current !== null) {\n cancelAnimationFrame(showFrameRef.current);\n }\n showFrameRef.current = requestAnimationFrame(() => {\n showFrameRef.current = null;\n setIsVisible(true);\n });\n };\n const tooltipRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n\n // Tied to visibility, not mount: the node is latched into the DOM after its first show, and\n // re-entering on each show keeps a tooltip above the panel it is annotating.\n useTopLayer(tooltipRef, isVisible);\n\n const tooltipId = useId();\n\n const hasText = text !== null && text !== undefined && text !== '' && text !== false;\n\n const handleMouseEnter = (e: React.MouseEvent) => {\n e.stopPropagation();\n\n if (!hasText || suppressed || (shouldShow && !shouldShow())) {\n return;\n }\n\n cancelPendingShow();\n\n timeoutRef.current = setTimeout(() => {\n scheduleVisible();\n }, delay * 1000);\n };\n\n const handleMouseLeave = (e: React.MouseEvent) => {\n e.stopPropagation();\n\n cancelPendingShow();\n setIsVisible(false);\n };\n\n const handleFocus = () => {\n if (!hasText || suppressed || (shouldShow && !shouldShow())) {\n return;\n }\n\n cancelPendingShow();\n scheduleVisible();\n };\n\n const handleBlur = () => {\n cancelPendingShow();\n setIsVisible(false);\n };\n\n const [wasSuppressed, setWasSuppressed] = useState(suppressed);\n if (suppressed !== wasSuppressed) {\n setWasSuppressed(suppressed);\n if (suppressed) {\n setIsVisible(false);\n }\n }\n\n useEffect(() => {\n if (suppressed) {\n cancelPendingShow();\n }\n }, [suppressed, cancelPendingShow]);\n\n const [, forceUpdate] = useState({});\n\n useEffect(() => {\n // Only a VISIBLE tooltip needs to track scroll/resize; keeping global\n // listeners per mounted instance made every scroll event fan out across\n // every tooltip on the page.\n if (!isVisible) {\n return () => {\n cancelPendingShow();\n };\n }\n const handleUpdate = () => {\n forceUpdate({});\n };\n\n window.addEventListener('scroll', handleUpdate, true);\n window.addEventListener('resize', handleUpdate);\n\n return () => {\n cancelPendingShow();\n window.removeEventListener('scroll', handleUpdate, true);\n window.removeEventListener('resize', handleUpdate);\n };\n }, [isVisible, cancelPendingShow]);\n\n // The first render that mounts the tooltip has no measured width yet, so the clamp below\n // cannot run on it. One extra pass once it is in the DOM gives the clamp its measurement\n // — before the opacity transition finishes, so nothing is seen sliding into place.\n useEffect(() => {\n if (isVisible) {\n forceUpdate({});\n }\n }, [isVisible]);\n\n const getTooltipStyles = (): React.CSSProperties => {\n if (!triggerRef.current) {\n return { display: 'none' };\n }\n\n const rect = triggerRef.current.getBoundingClientRect();\n\n const baseStyles: React.CSSProperties = {\n position: 'fixed',\n display: 'flex',\n width: 'max-content',\n maxWidth: typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth,\n minWidth: '32px',\n minHeight: '32px',\n padding: '8px 12px',\n alignItems: 'center',\n gap: '8px',\n borderRadius: '12px',\n backgroundColor: 'var(--malachite-tooltip-background, rgb(59, 59, 59))',\n color: 'var(--malachite-tooltip-foreground, rgb(255, 255, 255))',\n boxShadow: 'var(--malachite-tooltip-shadow, 0px 0px 10px 0px rgba(0, 0, 0, 0.20))',\n fontSize: '14px',\n lineHeight: '1.4',\n whiteSpace: 'normal',\n textAlign: 'left',\n pointerEvents: 'none',\n opacity: isVisible ? 1 : 0,\n visibility: isVisible ? 'visible' : 'hidden',\n transition:\n 'opacity 150ms ease-in-out, transform 150ms ease-in-out, visibility 150ms ease-in-out',\n };\n\n // A trigger near the viewport edge would otherwise centre a wide tooltip half off\n // screen, where the panel or the window crops it. Clamping the CENTRE keeps the\n // `translateX(-50%)` placement honest: the box stays put, it just stops short.\n const centeredLeft = (): number => {\n const desired = rect.left + rect.width / 2;\n const width = tooltipRef.current?.getBoundingClientRect().width ?? 0;\n\n if (width === 0) {\n return desired;\n }\n\n const half = width / 2;\n const min = VIEWPORT_MARGIN + half;\n const max = window.innerWidth - VIEWPORT_MARGIN - half;\n\n // A tooltip wider than the viewport has no in-bounds centre; leave it centred\n // rather than pinning it to a nonsensical one.\n return min > max ? desired : Math.min(Math.max(desired, min), max);\n };\n\n switch (placement) {\n case 'top':\n return {\n ...baseStyles,\n top: rect.top - 8,\n left: centeredLeft(),\n transform: `translate(-50%, -100%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n case 'bottom':\n return {\n ...baseStyles,\n top: rect.bottom + 8,\n left: centeredLeft(),\n transform: `translateX(-50%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n case 'left':\n return {\n ...baseStyles,\n top: rect.top + rect.height / 2,\n left: rect.left - 8,\n transform: `translate(-100%, -50%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n case 'right':\n return {\n ...baseStyles,\n top: rect.top + rect.height / 2,\n left: rect.right + 8,\n transform: `translateY(-50%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n default:\n return {\n ...baseStyles,\n top: rect.top - 8,\n left: centeredLeft(),\n transform: `translate(-50%, -100%) ${isVisible ? 'scale(1)' : 'scale(0.95)'}`,\n };\n }\n };\n\n // Only reference the tooltip id once the portal can exist — a dangling\n // aria-describedby (text set, never shown) confuses assistive tech.\n const describedBy = hasText && hasShown && describesTrigger ? tooltipId : undefined;\n useInsertionEffect(() => {\n if (hasText && hasShown) {\n ensureOverlayStyles();\n }\n }, [hasText, hasShown]);\n const renderedChildren =\n wrapChildren || !React.isValidElement(children) ? (\n <span aria-describedby={describedBy} style={fill ? FILL_STYLE : undefined}>\n {children}\n </span>\n ) : (\n React.cloneElement(children as React.ReactElement, {\n 'aria-describedby':\n [(children as React.ReactElement).props['aria-describedby'], describedBy]\n .filter(Boolean)\n .join(' ') || undefined,\n })\n );\n\n const Trigger = inline ? 'span' : triggerAs;\n\n // Create the tooltip content without its own shadow root\n return (\n <>\n <Trigger\n ref={triggerRef}\n className={`relative ${inline ? 'inline-flex max-w-full align-middle' : 'flex'} items-center`}\n style={triggerStyle}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onFocus={handleFocus}\n onBlur={handleBlur}\n >\n {renderedChildren}\n </Trigger>\n\n {hasText &&\n hasShown &&\n createPortal(\n <div\n ref={tooltipRef}\n id={tooltipId}\n role=\"tooltip\"\n // Nothing references it, and the sentence is already on screen and\n // described: left in the tree it is a second copy to read past.\n aria-hidden={describesTrigger ? undefined : true}\n {...overlayIdentity('tooltip')}\n style={getTooltipStyles()}\n >\n {/* min-w-0 + overflow-wrap let long values wrap within maxWidth. */}\n <span\n style={{\n minWidth: 0,\n overflowWrap: 'anywhere',\n }}\n >\n {typeof text === 'string' ? withBreakOpportunities(text) : text}\n </span>\n </div>,\n document.body,\n )}\n </>\n );\n};\n\nexport default Tooltip;\n"],"names":["WRAP_AFTER","withBreakOpportunities","value","chunk","i","jsxs","React","SHRINKABLE_STYLE","FILL_STYLE","VIEWPORT_MARGIN","Tooltip","text","children","delay","wrapChildren","triggerAs","inline","placement","isShrinkable","maxWidth","fill","shouldShow","suppressed","describesTrigger","triggerStyle","isVisible","setIsVisible","useState","hasShown","setHasShown","timeoutRef","useRef","showFrameRef","cancelPendingShow","useCallback","scheduleVisible","tooltipRef","triggerRef","useTopLayer","tooltipId","useId","hasText","handleMouseEnter","handleMouseLeave","handleFocus","handleBlur","wasSuppressed","setWasSuppressed","useEffect","forceUpdate","handleUpdate","getTooltipStyles","rect","baseStyles","centeredLeft","desired","width","_a","half","min","max","describedBy","useInsertionEffect","ensureOverlayStyles","renderedChildren","jsx","Fragment","createPortal","overlayIdentity"],"mappings":"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"}