@mieweb/ui 0.7.3-dev.20 → 0.7.3-dev.22

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 (56) hide show
  1. package/dist/brands/index.cjs +13 -13
  2. package/dist/brands/index.js +1 -1
  3. package/dist/chunk-5JZIDILK.cjs +164 -0
  4. package/dist/chunk-5JZIDILK.cjs.map +1 -0
  5. package/dist/chunk-7IKLGH3Z.cjs +92 -0
  6. package/dist/chunk-7IKLGH3Z.cjs.map +1 -0
  7. package/dist/chunk-7L7OPISJ.cjs +291 -0
  8. package/dist/chunk-7L7OPISJ.cjs.map +1 -0
  9. package/dist/{chunk-VNNFI5DQ.cjs → chunk-ABST3R3G.cjs} +60 -2
  10. package/dist/chunk-ABST3R3G.cjs.map +1 -0
  11. package/dist/{chunk-4PJ24GQ4.js → chunk-DX64KLSN.js} +2 -2
  12. package/dist/{chunk-4PJ24GQ4.js.map → chunk-DX64KLSN.js.map} +1 -1
  13. package/dist/chunk-JHZW3Y62.js +142 -0
  14. package/dist/chunk-JHZW3Y62.js.map +1 -0
  15. package/dist/{chunk-3Z7CLG4U.js → chunk-VCHTV65A.js} +60 -2
  16. package/dist/chunk-VCHTV65A.js.map +1 -0
  17. package/dist/chunk-WBGUYSWY.js +90 -0
  18. package/dist/chunk-WBGUYSWY.js.map +1 -0
  19. package/dist/{chunk-LGYGKLJL.cjs → chunk-WIYQI35R.cjs} +2 -2
  20. package/dist/{chunk-LGYGKLJL.cjs.map → chunk-WIYQI35R.cjs.map} +1 -1
  21. package/dist/{chunk-WG6MPHWK.cjs → chunk-XJTFZLWH.cjs} +2 -86
  22. package/dist/chunk-XJTFZLWH.cjs.map +1 -0
  23. package/dist/{chunk-KGS7BL5T.js → chunk-XUVEF2RQ.js} +4 -87
  24. package/dist/chunk-XUVEF2RQ.js.map +1 -0
  25. package/dist/chunk-XWYKLEKG.js +269 -0
  26. package/dist/chunk-XWYKLEKG.js.map +1 -0
  27. package/dist/components/GlossaryTooltip/index.cjs +15 -0
  28. package/dist/components/GlossaryTooltip/index.cjs.map +1 -0
  29. package/dist/components/GlossaryTooltip/index.d.cts +64 -0
  30. package/dist/components/GlossaryTooltip/index.d.ts +64 -0
  31. package/dist/components/GlossaryTooltip/index.js +6 -0
  32. package/dist/components/GlossaryTooltip/index.js.map +1 -0
  33. package/dist/components/Markdown/index.cjs +15 -15
  34. package/dist/components/Markdown/index.js +3 -3
  35. package/dist/components/SectionSpyNav/index.cjs +15 -0
  36. package/dist/components/SectionSpyNav/index.cjs.map +1 -0
  37. package/dist/components/SectionSpyNav/index.d.cts +63 -0
  38. package/dist/components/SectionSpyNav/index.d.ts +63 -0
  39. package/dist/components/SectionSpyNav/index.js +6 -0
  40. package/dist/components/SectionSpyNav/index.js.map +1 -0
  41. package/dist/hooks/index.cjs +18 -17
  42. package/dist/hooks/index.js +2 -1
  43. package/dist/index.cjs +161 -150
  44. package/dist/index.cjs.map +1 -1
  45. package/dist/index.d.cts +2 -0
  46. package/dist/index.d.ts +2 -0
  47. package/dist/index.js +25 -21
  48. package/dist/index.js.map +1 -1
  49. package/dist/styles.css +1 -1
  50. package/dist/tailwind-preset.cjs +4 -4
  51. package/dist/tailwind-preset.js +1 -1
  52. package/package.json +1 -1
  53. package/dist/chunk-3Z7CLG4U.js.map +0 -1
  54. package/dist/chunk-KGS7BL5T.js.map +0 -1
  55. package/dist/chunk-VNNFI5DQ.cjs.map +0 -1
  56. package/dist/chunk-WG6MPHWK.cjs.map +0 -1
@@ -6,10 +6,10 @@ var chunkP52GA3GJ_cjs = require('../chunk-P52GA3GJ.cjs');
6
6
  var chunkLCQGAOAZ_cjs = require('../chunk-LCQGAOAZ.cjs');
7
7
  var chunkZ5J4NTPL_cjs = require('../chunk-Z5J4NTPL.cjs');
8
8
  var chunkU7VQUOLS_cjs = require('../chunk-U7VQUOLS.cjs');
9
+ var chunkJ644FU54_cjs = require('../chunk-J644FU54.cjs');
9
10
  var chunkWNJRS7Y7_cjs = require('../chunk-WNJRS7Y7.cjs');
10
11
  var chunkUCGUA3QV_cjs = require('../chunk-UCGUA3QV.cjs');
11
12
  var chunkRR2MJBGV_cjs = require('../chunk-RR2MJBGV.cjs');
12
- var chunkJ644FU54_cjs = require('../chunk-J644FU54.cjs');
13
13
 
14
14
 
15
15
 
@@ -37,18 +37,6 @@ Object.defineProperty(exports, "webchartBrand", {
37
37
  enumerable: true,
38
38
  get: function () { return chunkU7VQUOLS_cjs.webchartBrand; }
39
39
  });
40
- Object.defineProperty(exports, "bluehiveBrand", {
41
- enumerable: true,
42
- get: function () { return chunkWNJRS7Y7_cjs.bluehiveBrand; }
43
- });
44
- Object.defineProperty(exports, "ccmeBrand", {
45
- enumerable: true,
46
- get: function () { return chunkUCGUA3QV_cjs.ccmeBrand; }
47
- });
48
- Object.defineProperty(exports, "ozwellBrand", {
49
- enumerable: true,
50
- get: function () { return chunkRR2MJBGV_cjs.ozwellBrand; }
51
- });
52
40
  Object.defineProperty(exports, "createBrandPreset", {
53
41
  enumerable: true,
54
42
  get: function () { return chunkJ644FU54_cjs.createBrandPreset; }
@@ -61,5 +49,17 @@ Object.defineProperty(exports, "generateTailwindTheme", {
61
49
  enumerable: true,
62
50
  get: function () { return chunkJ644FU54_cjs.generateTailwindTheme; }
63
51
  });
52
+ Object.defineProperty(exports, "bluehiveBrand", {
53
+ enumerable: true,
54
+ get: function () { return chunkWNJRS7Y7_cjs.bluehiveBrand; }
55
+ });
56
+ Object.defineProperty(exports, "ccmeBrand", {
57
+ enumerable: true,
58
+ get: function () { return chunkUCGUA3QV_cjs.ccmeBrand; }
59
+ });
60
+ Object.defineProperty(exports, "ozwellBrand", {
61
+ enumerable: true,
62
+ get: function () { return chunkRR2MJBGV_cjs.ozwellBrand; }
63
+ });
64
64
  //# sourceMappingURL=index.cjs.map
65
65
  //# sourceMappingURL=index.cjs.map
@@ -4,9 +4,9 @@ export { enterpriseHealthBrand } from '../chunk-MTZPVOP6.js';
4
4
  export { miewebBrand } from '../chunk-NERS5ZT6.js';
5
5
  export { wagglelineBrand } from '../chunk-2NTYAALC.js';
6
6
  export { webchartBrand } from '../chunk-CW66SO5O.js';
7
+ export { createBrandPreset, generateBrandCSS, generateTailwindTheme } from '../chunk-WOYUQ4AT.js';
7
8
  export { bluehiveBrand } from '../chunk-3T7QGLNB.js';
8
9
  export { ccmeBrand } from '../chunk-SCQRJPSV.js';
9
10
  export { ozwellBrand } from '../chunk-5YUBQIC7.js';
10
- export { createBrandPreset, generateBrandCSS, generateTailwindTheme } from '../chunk-WOYUQ4AT.js';
11
11
  //# sourceMappingURL=index.js.map
12
12
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,164 @@
1
+ 'use strict';
2
+
3
+ var chunkRDGRKYQ5_cjs = require('./chunk-RDGRKYQ5.cjs');
4
+ var chunk7IKLGH3Z_cjs = require('./chunk-7IKLGH3Z.cjs');
5
+ var chunkS5RVSXDV_cjs = require('./chunk-S5RVSXDV.cjs');
6
+ var React = require('react');
7
+ var lucideReact = require('lucide-react');
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+
10
+ function _interopNamespace(e) {
11
+ if (e && e.__esModule) return e;
12
+ var n = Object.create(null);
13
+ if (e) {
14
+ Object.keys(e).forEach(function (k) {
15
+ if (k !== 'default') {
16
+ var d = Object.getOwnPropertyDescriptor(e, k);
17
+ Object.defineProperty(n, k, d.get ? d : {
18
+ enumerable: true,
19
+ get: function () { return e[k]; }
20
+ });
21
+ }
22
+ });
23
+ }
24
+ n.default = e;
25
+ return Object.freeze(n);
26
+ }
27
+
28
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
29
+
30
+ function CtaArrow({ href }) {
31
+ const Icon = href.startsWith("#") ? lucideReact.ArrowDown : href.startsWith("/") ? lucideReact.ArrowRight : lucideReact.ArrowUpRight;
32
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon, { "aria-hidden": "true", className: "h-3.5 w-3.5" });
33
+ }
34
+ var CTA_TIER_VARIANT = {
35
+ explore: "ghost",
36
+ evaluate: "outline",
37
+ commit: "primary"
38
+ };
39
+ function SectionSpyNav({
40
+ items,
41
+ cta,
42
+ label = "On this page",
43
+ tone = "surface",
44
+ rootMargin = "-22% 0px -68% 0px",
45
+ onItemClick,
46
+ onCtaClick,
47
+ className
48
+ }) {
49
+ const ids = React__namespace.useMemo(() => items.map((it) => it.id), [items]);
50
+ const { activeId } = chunk7IKLGH3Z_cjs.useScrollSpy({ ids, rootMargin });
51
+ const active = activeId ?? items[0]?.id ?? "";
52
+ const railRef = React__namespace.useRef(null);
53
+ const markRef = React__namespace.useRef(null);
54
+ const findActiveLink = React__namespace.useCallback(() => {
55
+ const links = railRef.current?.querySelectorAll("a");
56
+ if (!links) return null;
57
+ for (const link of links) {
58
+ if (link.dataset.id === active) return link;
59
+ }
60
+ return null;
61
+ }, [active]);
62
+ const syncMarker = React__namespace.useCallback(() => {
63
+ const link = findActiveLink();
64
+ const mark = markRef.current;
65
+ if (!link || !mark) return;
66
+ mark.style.left = `${link.offsetLeft}px`;
67
+ mark.style.width = `${link.offsetWidth}px`;
68
+ }, [findActiveLink]);
69
+ React__namespace.useEffect(() => {
70
+ const link = findActiveLink();
71
+ link?.scrollIntoView?.({ inline: "center", block: "nearest" });
72
+ syncMarker();
73
+ }, [findActiveLink, syncMarker]);
74
+ React__namespace.useEffect(() => {
75
+ window.addEventListener("resize", syncMarker);
76
+ return () => window.removeEventListener("resize", syncMarker);
77
+ }, [syncMarker]);
78
+ const brand = tone === "brand";
79
+ return /* @__PURE__ */ jsxRuntime.jsx(
80
+ "nav",
81
+ {
82
+ className: chunkS5RVSXDV_cjs.cn(
83
+ "sticky top-0 z-30 w-full",
84
+ brand ? "bg-primary-900 text-white" : "border-border bg-card/95 border-b backdrop-blur",
85
+ className
86
+ ),
87
+ "aria-label": label,
88
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 px-4 py-0.5", children: [
89
+ /* @__PURE__ */ jsxRuntime.jsx(
90
+ "span",
91
+ {
92
+ className: chunkS5RVSXDV_cjs.cn(
93
+ "shrink-0 text-[11px] font-semibold tracking-wide uppercase max-md:hidden",
94
+ brand ? "text-white/85" : "text-muted-foreground"
95
+ ),
96
+ "aria-hidden": "true",
97
+ children: label
98
+ }
99
+ ),
100
+ /* @__PURE__ */ jsxRuntime.jsxs(
101
+ "div",
102
+ {
103
+ ref: railRef,
104
+ className: "relative flex min-w-0 flex-1 gap-1 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
105
+ children: [
106
+ items.map((it) => {
107
+ const isActive = active === it.id;
108
+ return /* @__PURE__ */ jsxRuntime.jsx(
109
+ "a",
110
+ {
111
+ href: `#${it.id}`,
112
+ "data-id": it.id,
113
+ onClick: () => onItemClick?.(it.id),
114
+ className: chunkS5RVSXDV_cjs.cn(
115
+ "shrink-0 rounded px-2.5 py-2 text-sm whitespace-nowrap transition-colors",
116
+ brand ? isActive ? "font-semibold text-white" : "text-white/85 hover:text-white" : isActive ? "text-foreground font-semibold" : "text-muted-foreground hover:text-foreground"
117
+ ),
118
+ "aria-current": isActive ? "location" : void 0,
119
+ children: it.label
120
+ },
121
+ it.id
122
+ );
123
+ }),
124
+ /* @__PURE__ */ jsxRuntime.jsx(
125
+ "span",
126
+ {
127
+ ref: markRef,
128
+ className: chunkS5RVSXDV_cjs.cn(
129
+ "absolute bottom-0 h-0.5 rounded-full transition-[left,width] duration-300",
130
+ brand ? "bg-primary-400" : "bg-primary-500"
131
+ ),
132
+ "aria-hidden": "true"
133
+ }
134
+ )
135
+ ]
136
+ }
137
+ ),
138
+ cta && /* @__PURE__ */ jsxRuntime.jsxs(
139
+ "a",
140
+ {
141
+ href: cta.href,
142
+ onClick: () => onCtaClick?.(cta),
143
+ className: chunkS5RVSXDV_cjs.cn(
144
+ chunkRDGRKYQ5_cjs.buttonVariants({
145
+ variant: CTA_TIER_VARIANT[cta.tier ?? "explore"],
146
+ size: "sm"
147
+ }),
148
+ "shrink-0",
149
+ brand && (cta.tier ?? "explore") !== "commit" && "text-white hover:bg-white/10 hover:text-white"
150
+ ),
151
+ children: [
152
+ cta.label,
153
+ /* @__PURE__ */ jsxRuntime.jsx(CtaArrow, { href: cta.href })
154
+ ]
155
+ }
156
+ )
157
+ ] })
158
+ }
159
+ );
160
+ }
161
+
162
+ exports.SectionSpyNav = SectionSpyNav;
163
+ //# sourceMappingURL=chunk-5JZIDILK.cjs.map
164
+ //# sourceMappingURL=chunk-5JZIDILK.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/SectionSpyNav/SectionSpyNav.tsx"],"names":["ArrowDown","ArrowRight","ArrowUpRight","jsx","React","useScrollSpy","cn","jsxs","buttonVariants"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DA,SAAS,QAAA,CAAS,EAAE,IAAA,EAAK,EAAqB;AAC5C,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,GAC5BA,wBACA,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,GACjBC,sBAAA,GACAC,wBAAA;AACN,EAAA,uBAAOC,cAAA,CAAC,IAAA,EAAA,EAAK,aAAA,EAAY,MAAA,EAAO,WAAU,aAAA,EAAc,CAAA;AAC1D;AAEA,IAAM,gBAAA,GAAmB;AAAA,EACvB,OAAA,EAAS,OAAA;AAAA,EACT,QAAA,EAAU,SAAA;AAAA,EACV,MAAA,EAAQ;AACV,CAAA;AA2BO,SAAS,aAAA,CAAc;AAAA,EAC5B,KAAA;AAAA,EACA,GAAA;AAAA,EACA,KAAA,GAAQ,cAAA;AAAA,EACR,IAAA,GAAO,SAAA;AAAA,EACP,UAAA,GAAa,mBAAA;AAAA,EACb,WAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA,EAAuB;AACrB,EAAA,MAAM,GAAA,GAAYC,gBAAA,CAAA,OAAA,CAAQ,MAAM,KAAA,CAAM,GAAA,CAAI,CAAC,EAAA,KAAO,EAAA,CAAG,EAAE,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AACjE,EAAA,MAAM,EAAE,QAAA,EAAS,GAAIC,+BAAa,EAAE,GAAA,EAAK,YAAY,CAAA;AACrD,EAAA,MAAM,MAAA,GAAS,QAAA,IAAY,KAAA,CAAM,CAAC,GAAG,EAAA,IAAM,EAAA;AAE3C,EAAA,MAAM,OAAA,GAAgBD,wBAAuB,IAAI,CAAA;AACjD,EAAA,MAAM,OAAA,GAAgBA,wBAAwB,IAAI,CAAA;AAIlD,EAAA,MAAM,cAAA,GAAuBA,6BAAY,MAAgC;AACvE,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,OAAA,EAAS,gBAAA,CAAoC,GAAG,CAAA;AACtE,IAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,EAAA,KAAO,MAAA,EAAQ,OAAO,IAAA;AAAA,IACzC;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAKX,EAAA,MAAM,UAAA,GAAmBA,6BAAY,MAAM;AACzC,IAAA,MAAM,OAAO,cAAA,EAAe;AAC5B,IAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,IAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,IAAA,EAAM;AACpB,IAAA,IAAA,CAAK,KAAA,CAAM,IAAA,GAAO,CAAA,EAAG,IAAA,CAAK,UAAU,CAAA,EAAA,CAAA;AACpC,IAAA,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,CAAA,EAAG,IAAA,CAAK,WAAW,CAAA,EAAA,CAAA;AAAA,EACxC,CAAA,EAAG,CAAC,cAAc,CAAC,CAAA;AAEnB,EAAMA,2BAAU,MAAM;AACpB,IAAA,MAAM,OAAO,cAAA,EAAe;AAC5B,IAAA,IAAA,EAAM,iBAAiB,EAAE,MAAA,EAAQ,QAAA,EAAU,KAAA,EAAO,WAAW,CAAA;AAC7D,IAAA,UAAA,EAAW;AAAA,EACb,CAAA,EAAG,CAAC,cAAA,EAAgB,UAAU,CAAC,CAAA;AAE/B,EAAMA,2BAAU,MAAM;AACpB,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,UAAU,CAAA;AAC5C,IAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,QAAA,EAAU,UAAU,CAAA;AAAA,EAC9D,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAA,MAAM,QAAQ,IAAA,KAAS,OAAA;AAEvB,EAAA,uBACED,cAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAWG,oBAAA;AAAA,QACT,0BAAA;AAAA,QACA,QACI,2BAAA,GACA,iDAAA;AAAA,QACJ;AAAA,OACF;AAAA,MACA,YAAA,EAAY,KAAA;AAAA,MAEZ,QAAA,kBAAAC,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qCAAA,EACb,QAAA,EAAA;AAAA,wBAAAJ,cAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAWG,oBAAA;AAAA,cACT,0EAAA;AAAA,cACA,QAAQ,eAAA,GAAkB;AAAA,aAC5B;AAAA,YACA,aAAA,EAAY,MAAA;AAAA,YAEX,QAAA,EAAA;AAAA;AAAA,SACH;AAAA,wBACAC,eAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,GAAA,EAAK,OAAA;AAAA,YACL,SAAA,EAAU,yGAAA;AAAA,YAET,QAAA,EAAA;AAAA,cAAA,KAAA,CAAM,GAAA,CAAI,CAAC,EAAA,KAAO;AACjB,gBAAA,MAAM,QAAA,GAAW,WAAW,EAAA,CAAG,EAAA;AAC/B,gBAAA,uBACEJ,cAAA;AAAA,kBAAC,GAAA;AAAA,kBAAA;AAAA,oBAEC,IAAA,EAAM,CAAA,CAAA,EAAI,EAAA,CAAG,EAAE,CAAA,CAAA;AAAA,oBACf,WAAS,EAAA,CAAG,EAAA;AAAA,oBACZ,OAAA,EAAS,MAAM,WAAA,GAAc,EAAA,CAAG,EAAE,CAAA;AAAA,oBAClC,SAAA,EAAWG,oBAAA;AAAA,sBACT,0EAAA;AAAA,sBACA,KAAA,GACI,QAAA,GACE,0BAAA,GACA,gCAAA,GACF,WACE,+BAAA,GACA;AAAA,qBACR;AAAA,oBACA,cAAA,EAAc,WAAW,UAAA,GAAa,MAAA;AAAA,oBAErC,QAAA,EAAA,EAAA,CAAG;AAAA,mBAAA;AAAA,kBAhBC,EAAA,CAAG;AAAA,iBAiBV;AAAA,cAEJ,CAAC,CAAA;AAAA,8BACDH,cAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,GAAA,EAAK,OAAA;AAAA,kBACL,SAAA,EAAWG,oBAAA;AAAA,oBACT,2EAAA;AAAA,oBACA,QAAQ,gBAAA,GAAmB;AAAA,mBAC7B;AAAA,kBACA,aAAA,EAAY;AAAA;AAAA;AACd;AAAA;AAAA,SACF;AAAA,QACC,GAAA,oBACCC,eAAA;AAAA,UAAC,GAAA;AAAA,UAAA;AAAA,YACC,MAAM,GAAA,CAAI,IAAA;AAAA,YACV,OAAA,EAAS,MAAM,UAAA,GAAa,GAAG,CAAA;AAAA,YAC/B,SAAA,EAAWD,oBAAA;AAAA,cACTE,gCAAA,CAAe;AAAA,gBACb,OAAA,EAAS,gBAAA,CAAiB,GAAA,CAAI,IAAA,IAAQ,SAAS,CAAA;AAAA,gBAC/C,IAAA,EAAM;AAAA,eACP,CAAA;AAAA,cACD,UAAA;AAAA,cACA,KAAA,IAAA,CACG,GAAA,CAAI,IAAA,IAAQ,SAAA,MAAe,QAAA,IAC5B;AAAA,aACJ;AAAA,YAEC,QAAA,EAAA;AAAA,cAAA,GAAA,CAAI,KAAA;AAAA,8BACLL,cAAA,CAAC,QAAA,EAAA,EAAS,IAAA,EAAM,GAAA,CAAI,IAAA,EAAM;AAAA;AAAA;AAAA;AAC5B,OAAA,EAEJ;AAAA;AAAA,GACF;AAEJ","file":"chunk-5JZIDILK.cjs","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { ArrowDown, ArrowRight, ArrowUpRight } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { useScrollSpy } from '../../hooks/useScrollSpy';\nimport { buttonVariants } from '../Button';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** One section the nav links to. The id must match a `section[id]` on the page. */\nexport interface SectionSpyItem {\n id: string;\n label: string;\n}\n\n/**\n * Funnel intent for the bar's single contextual CTA — drives its visual\n * weight so the in-page strip never out-shouts a page's primary CTA:\n * `explore` (quiet next step) → `evaluate` (sales-ready ask) → `commit`\n * (high-intent action).\n */\nexport type SectionSpyCtaTier = 'explore' | 'evaluate' | 'commit';\n\nexport interface SectionSpyCta {\n label: string;\n href: string;\n tier?: SectionSpyCtaTier;\n}\n\nexport interface SectionSpyNavProps {\n /** Sections to link to, in page order. */\n items: SectionSpyItem[];\n /** Optional single page-specific next-step CTA at the end of the bar. */\n cta?: SectionSpyCta;\n /** Eyebrow before the links (default \"On this page\"). */\n label?: string;\n /**\n * Visual tone: `surface` sits on the page background; `brand` renders the\n * inverted primary band.\n */\n tone?: 'surface' | 'brand';\n /** IntersectionObserver root margin tuning for the scroll spy. */\n rootMargin?: string;\n /** Called with the section id when a nav link is clicked. */\n onItemClick?: (id: string) => void;\n /** Called when the CTA is clicked (e.g. for analytics). */\n onCtaClick?: (cta: SectionSpyCta) => void;\n className?: string;\n}\n\n// =============================================================================\n// Internals\n// =============================================================================\n\n/** Directional glyph inferred from the destination. */\nfunction CtaArrow({ href }: { href: string }) {\n const Icon = href.startsWith('#')\n ? ArrowDown\n : href.startsWith('/')\n ? ArrowRight\n : ArrowUpRight;\n return <Icon aria-hidden=\"true\" className=\"h-3.5 w-3.5\" />;\n}\n\nconst CTA_TIER_VARIANT = {\n explore: 'ghost',\n evaluate: 'outline',\n commit: 'primary',\n} as const;\n\n// =============================================================================\n// SectionSpyNav\n// =============================================================================\n\n/**\n * Sticky horizontal in-page wayfinding: jumps between a page's major\n * sections, highlights the one in view with a sliding underline, and can\n * carry a single page-specific next-step CTA. Pure anchor links, so it\n * still works if the scroll spy never runs.\n *\n * The horizontal complement to `TableOfContents` — use that for a sidebar\n * outline, this for a band under the page header. Section elements need\n * matching `id`s.\n *\n * @example\n * ```tsx\n * <SectionSpyNav\n * items={[\n * { id: 'overview', label: 'Overview' },\n * { id: 'pricing', label: 'Pricing' },\n * ]}\n * cta={{ label: 'Book a demo', href: '/demo', tier: 'evaluate' }}\n * />\n * ```\n */\nexport function SectionSpyNav({\n items,\n cta,\n label = 'On this page',\n tone = 'surface',\n rootMargin = '-22% 0px -68% 0px',\n onItemClick,\n onCtaClick,\n className,\n}: SectionSpyNavProps) {\n const ids = React.useMemo(() => items.map((it) => it.id), [items]);\n const { activeId } = useScrollSpy({ ids, rootMargin });\n const active = activeId ?? items[0]?.id ?? '';\n\n const railRef = React.useRef<HTMLDivElement>(null);\n const markRef = React.useRef<HTMLSpanElement>(null);\n\n // Find the active link by dataset rather than a CSS selector, so ids\n // never need escaping and CSS.escape availability doesn't matter.\n const findActiveLink = React.useCallback((): HTMLAnchorElement | null => {\n const links = railRef.current?.querySelectorAll<HTMLAnchorElement>('a');\n if (!links) return null;\n for (const link of links) {\n if (link.dataset.id === active) return link;\n }\n return null;\n }, [active]);\n\n // Slide the underline beneath the active link. offsetLeft/offsetWidth are\n // physical and measured against the rail, so the marker tracks the link\n // in both directions and while the rail is scrolled horizontally.\n const syncMarker = React.useCallback(() => {\n const link = findActiveLink();\n const mark = markRef.current;\n if (!link || !mark) return;\n mark.style.left = `${link.offsetLeft}px`;\n mark.style.width = `${link.offsetWidth}px`;\n }, [findActiveLink]);\n\n React.useEffect(() => {\n const link = findActiveLink();\n link?.scrollIntoView?.({ inline: 'center', block: 'nearest' });\n syncMarker();\n }, [findActiveLink, syncMarker]);\n\n React.useEffect(() => {\n window.addEventListener('resize', syncMarker);\n return () => window.removeEventListener('resize', syncMarker);\n }, [syncMarker]);\n\n const brand = tone === 'brand';\n\n return (\n <nav\n className={cn(\n 'sticky top-0 z-30 w-full',\n brand\n ? 'bg-primary-900 text-white'\n : 'border-border bg-card/95 border-b backdrop-blur',\n className\n )}\n aria-label={label}\n >\n <div className=\"flex items-center gap-4 px-4 py-0.5\">\n <span\n className={cn(\n 'shrink-0 text-[11px] font-semibold tracking-wide uppercase max-md:hidden',\n brand ? 'text-white/85' : 'text-muted-foreground'\n )}\n aria-hidden=\"true\"\n >\n {label}\n </span>\n <div\n ref={railRef}\n className=\"relative flex min-w-0 flex-1 gap-1 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\"\n >\n {items.map((it) => {\n const isActive = active === it.id;\n return (\n <a\n key={it.id}\n href={`#${it.id}`}\n data-id={it.id}\n onClick={() => onItemClick?.(it.id)}\n className={cn(\n 'shrink-0 rounded px-2.5 py-2 text-sm whitespace-nowrap transition-colors',\n brand\n ? isActive\n ? 'font-semibold text-white'\n : 'text-white/85 hover:text-white'\n : isActive\n ? 'text-foreground font-semibold'\n : 'text-muted-foreground hover:text-foreground'\n )}\n aria-current={isActive ? 'location' : undefined}\n >\n {it.label}\n </a>\n );\n })}\n <span\n ref={markRef}\n className={cn(\n 'absolute bottom-0 h-0.5 rounded-full transition-[left,width] duration-300',\n brand ? 'bg-primary-400' : 'bg-primary-500'\n )}\n aria-hidden=\"true\"\n />\n </div>\n {cta && (\n <a\n href={cta.href}\n onClick={() => onCtaClick?.(cta)}\n className={cn(\n buttonVariants({\n variant: CTA_TIER_VARIANT[cta.tier ?? 'explore'],\n size: 'sm',\n }),\n 'shrink-0',\n brand &&\n (cta.tier ?? 'explore') !== 'commit' &&\n 'text-white hover:bg-white/10 hover:text-white'\n )}\n >\n {cta.label}\n <CtaArrow href={cta.href} />\n </a>\n )}\n </div>\n </nav>\n );\n}\n"]}
@@ -0,0 +1,92 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+
5
+ // src/hooks/useScrollSpy.ts
6
+ function useScrollSpy({
7
+ selectors,
8
+ ids,
9
+ rootMargin = "0px 0px -60% 0px",
10
+ threshold = 0,
11
+ root,
12
+ enabled = true
13
+ } = {}) {
14
+ const [activeId, setActiveId] = react.useState(null);
15
+ const visibleEntries = react.useRef(
16
+ /* @__PURE__ */ new Map()
17
+ );
18
+ const rootEl = root?.current ?? null;
19
+ react.useEffect(() => {
20
+ if (!enabled) return;
21
+ const container = rootEl ?? document;
22
+ function resolveElements() {
23
+ let els = [];
24
+ if (ids && ids.length > 0) {
25
+ els = ids.map((id) => document.getElementById(id)).filter((el) => el !== null);
26
+ } else if (selectors) {
27
+ els = Array.from(container.querySelectorAll(selectors));
28
+ }
29
+ return els.filter((el) => el.id);
30
+ }
31
+ let intersectionObserver = null;
32
+ let mutationObserver = null;
33
+ function startObserving() {
34
+ const elements = resolveElements();
35
+ if (elements.length === 0) return false;
36
+ intersectionObserver = new IntersectionObserver(
37
+ (entries2) => {
38
+ for (const entry of entries2) {
39
+ if (entry.isIntersecting) {
40
+ visibleEntries.current.set(entry.target.id, entry);
41
+ } else {
42
+ visibleEntries.current.delete(entry.target.id);
43
+ }
44
+ }
45
+ if (visibleEntries.current.size > 0) {
46
+ let topmost = null;
47
+ let topmostTop = Infinity;
48
+ for (const [id, entry] of visibleEntries.current) {
49
+ const top = entry.boundingClientRect.top;
50
+ if (top < topmostTop) {
51
+ topmostTop = top;
52
+ topmost = id;
53
+ }
54
+ }
55
+ if (topmost) {
56
+ setActiveId(topmost);
57
+ }
58
+ }
59
+ },
60
+ {
61
+ root: rootEl,
62
+ rootMargin,
63
+ threshold
64
+ }
65
+ );
66
+ for (const el of elements) {
67
+ intersectionObserver.observe(el);
68
+ }
69
+ mutationObserver?.disconnect();
70
+ mutationObserver = null;
71
+ return true;
72
+ }
73
+ if (!startObserving()) {
74
+ const watchRoot = rootEl ?? document.body;
75
+ mutationObserver = new MutationObserver(() => {
76
+ startObserving();
77
+ });
78
+ mutationObserver.observe(watchRoot, { childList: true, subtree: true });
79
+ }
80
+ const entries = visibleEntries.current;
81
+ return () => {
82
+ mutationObserver?.disconnect();
83
+ intersectionObserver?.disconnect();
84
+ entries.clear();
85
+ };
86
+ }, [selectors, ids, rootMargin, threshold, rootEl, enabled]);
87
+ return { activeId };
88
+ }
89
+
90
+ exports.useScrollSpy = useScrollSpy;
91
+ //# sourceMappingURL=chunk-7IKLGH3Z.cjs.map
92
+ //# sourceMappingURL=chunk-7IKLGH3Z.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/useScrollSpy.ts"],"names":["useState","useRef","useEffect","entries"],"mappings":"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","file":"chunk-7IKLGH3Z.cjs","sourcesContent":["import { useEffect, useState, useRef, type RefObject } from 'react';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface UseScrollSpyOptions {\n /** CSS selector for the elements to observe (e.g. 'h2, h3, h4') */\n selectors?: string;\n /** Explicit list of element IDs to observe (alternative to selectors) */\n ids?: string[];\n /** IntersectionObserver root margin (default: '0px 0px -60% 0px') */\n rootMargin?: string;\n /** IntersectionObserver threshold (default: 0) */\n threshold?: number | number[];\n /** Scroll container element ref. Defaults to document viewport. */\n root?: RefObject<HTMLElement | null>;\n /** Whether the hook is active (default: true) */\n enabled?: boolean;\n}\n\nexport interface UseScrollSpyReturn {\n /** The ID of the currently active (in-view) element */\n activeId: string | null;\n}\n\n// =============================================================================\n// Hook\n// =============================================================================\n\n/**\n * Tracks which section is currently in the viewport using IntersectionObserver.\n * Pairs naturally with `TableOfContents` to highlight the active heading.\n *\n * @example\n * ```tsx\n * function DocsPage() {\n * const { activeId } = useScrollSpy({ selectors: 'h2, h3' });\n * return (\n * <aside>\n * <TableOfContents activeId={activeId} />\n * </aside>\n * );\n * }\n * ```\n */\nexport function useScrollSpy({\n selectors,\n ids,\n rootMargin = '0px 0px -60% 0px',\n threshold = 0,\n root,\n enabled = true,\n}: UseScrollSpyOptions = {}): UseScrollSpyReturn {\n const [activeId, setActiveId] = useState<string | null>(null);\n const visibleEntries = useRef<Map<string, IntersectionObserverEntry>>(\n new Map()\n );\n\n // Track root.current so the effect re-runs when the ref attaches\n const rootEl = root?.current ?? null;\n\n useEffect(() => {\n if (!enabled) return;\n\n const container = rootEl ?? document;\n\n // Resolve target elements from the DOM\n function resolveElements(): Element[] {\n let els: Element[] = [];\n if (ids && ids.length > 0) {\n els = ids\n .map((id) => document.getElementById(id))\n .filter((el): el is HTMLElement => el !== null);\n } else if (selectors) {\n els = Array.from(container.querySelectorAll(selectors));\n }\n return els.filter((el) => el.id);\n }\n\n let intersectionObserver: IntersectionObserver | null = null;\n let mutationObserver: MutationObserver | null = null;\n\n function startObserving(): boolean {\n const elements = resolveElements();\n if (elements.length === 0) return false;\n\n intersectionObserver = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting) {\n visibleEntries.current.set(entry.target.id, entry);\n } else {\n visibleEntries.current.delete(entry.target.id);\n }\n }\n\n // Pick the topmost visible heading (by DOM order)\n if (visibleEntries.current.size > 0) {\n let topmost: string | null = null;\n let topmostTop = Infinity;\n\n for (const [id, entry] of visibleEntries.current) {\n const top = entry.boundingClientRect.top;\n if (top < topmostTop) {\n topmostTop = top;\n topmost = id;\n }\n }\n\n if (topmost) {\n setActiveId(topmost);\n }\n }\n },\n {\n root: rootEl,\n rootMargin,\n threshold,\n }\n );\n\n for (const el of elements) {\n intersectionObserver.observe(el);\n }\n\n // Elements found — stop watching for new DOM nodes\n mutationObserver?.disconnect();\n mutationObserver = null;\n return true;\n }\n\n // If target elements don't exist yet (e.g. headings mount after ToC),\n // watch for DOM changes and retry until they appear.\n if (!startObserving()) {\n const watchRoot = rootEl ?? document.body;\n mutationObserver = new MutationObserver(() => {\n startObserving();\n });\n mutationObserver.observe(watchRoot, { childList: true, subtree: true });\n }\n\n const entries = visibleEntries.current;\n return () => {\n mutationObserver?.disconnect();\n intersectionObserver?.disconnect();\n entries.clear();\n };\n }, [selectors, ids, rootMargin, threshold, rootEl, enabled]);\n\n return { activeId };\n}\n"]}
@@ -0,0 +1,291 @@
1
+ 'use strict';
2
+
3
+ var chunkFHY3K6PL_cjs = require('./chunk-FHY3K6PL.cjs');
4
+ var chunkMYFZYUPR_cjs = require('./chunk-MYFZYUPR.cjs');
5
+ var chunkS5RVSXDV_cjs = require('./chunk-S5RVSXDV.cjs');
6
+ var React = require('react');
7
+ var reactDom = require('react-dom');
8
+ var lucideReact = require('lucide-react');
9
+ var jsxRuntime = require('react/jsx-runtime');
10
+
11
+ function _interopNamespace(e) {
12
+ if (e && e.__esModule) return e;
13
+ var n = Object.create(null);
14
+ if (e) {
15
+ Object.keys(e).forEach(function (k) {
16
+ if (k !== 'default') {
17
+ var d = Object.getOwnPropertyDescriptor(e, k);
18
+ Object.defineProperty(n, k, d.get ? d : {
19
+ enumerable: true,
20
+ get: function () { return e[k]; }
21
+ });
22
+ }
23
+ });
24
+ }
25
+ n.default = e;
26
+ return Object.freeze(n);
27
+ }
28
+
29
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
30
+
31
+ var HIDE_GRACE_MS = 180;
32
+ function GlossaryTooltip({
33
+ children,
34
+ term,
35
+ definition,
36
+ category,
37
+ keyFact,
38
+ source,
39
+ related,
40
+ href,
41
+ maxDefinitionLength = 190,
42
+ underline = true,
43
+ className
44
+ }) {
45
+ const [open, setOpen] = React__namespace.useState(false);
46
+ const [pinned, setPinned] = React__namespace.useState(false);
47
+ const timer = React__namespace.useRef(null);
48
+ const suppressFocusShow = React__namespace.useRef(false);
49
+ const { anchorRef, floatingRef, style } = chunkMYFZYUPR_cjs.useAnchoredPosition({
50
+ open,
51
+ placement: "top",
52
+ offset: 10,
53
+ viewportPadding: 8,
54
+ allowFlip: true
55
+ });
56
+ const clearHideTimer = () => {
57
+ if (timer.current) {
58
+ clearTimeout(timer.current);
59
+ timer.current = null;
60
+ }
61
+ };
62
+ const show = React__namespace.useCallback(() => {
63
+ clearHideTimer();
64
+ setOpen(true);
65
+ }, []);
66
+ const scheduleHide = React__namespace.useCallback(() => {
67
+ if (pinned) return;
68
+ clearHideTimer();
69
+ timer.current = setTimeout(() => setOpen(false), HIDE_GRACE_MS);
70
+ }, [pinned]);
71
+ const close = React__namespace.useCallback(() => {
72
+ clearHideTimer();
73
+ setPinned(false);
74
+ setOpen(false);
75
+ if (floatingRef.current?.contains(document.activeElement)) {
76
+ suppressFocusShow.current = true;
77
+ anchorRef.current?.querySelector("a,button")?.focus();
78
+ }
79
+ }, [anchorRef, floatingRef]);
80
+ React__namespace.useEffect(() => () => clearHideTimer(), []);
81
+ React__namespace.useEffect(() => {
82
+ if (pinned) floatingRef.current?.focus();
83
+ }, [pinned, floatingRef]);
84
+ chunkFHY3K6PL_cjs.useEscapeKey(close, open);
85
+ React__namespace.useEffect(() => {
86
+ if (!open || !pinned) return;
87
+ const onPointer = (e) => {
88
+ const t = e.target;
89
+ if (anchorRef.current?.contains(t) || floatingRef.current?.contains(t))
90
+ return;
91
+ close();
92
+ };
93
+ document.addEventListener("mousedown", onPointer);
94
+ document.addEventListener("touchstart", onPointer);
95
+ return () => {
96
+ document.removeEventListener("mousedown", onPointer);
97
+ document.removeEventListener("touchstart", onPointer);
98
+ };
99
+ }, [open, pinned, close, anchorRef, floatingRef]);
100
+ const togglePin = React__namespace.useCallback(() => {
101
+ if (pinned) close();
102
+ else {
103
+ setPinned(true);
104
+ show();
105
+ }
106
+ }, [pinned, close, show]);
107
+ const onTriggerClick = (e) => {
108
+ const coarse = typeof window !== "undefined" && window.matchMedia("(hover: none)").matches;
109
+ if (href) {
110
+ if (!coarse) return;
111
+ e.preventDefault();
112
+ }
113
+ togglePin();
114
+ };
115
+ const onTriggerKeyDown = (e) => {
116
+ if (href) return;
117
+ if (e.key === "Enter" || e.key === " ") {
118
+ e.preventDefault();
119
+ togglePin();
120
+ }
121
+ };
122
+ const onDialogKeyDown = (e) => {
123
+ if (e.target !== e.currentTarget) return;
124
+ if (e.key === "Enter" || e.key === " ") {
125
+ e.preventDefault();
126
+ close();
127
+ }
128
+ };
129
+ const onTriggerFocus = () => {
130
+ if (suppressFocusShow.current) {
131
+ suppressFocusShow.current = false;
132
+ return;
133
+ }
134
+ show();
135
+ };
136
+ const onBlurCapture = (e) => {
137
+ const next = e.relatedTarget;
138
+ if (next && (anchorRef.current?.contains(next) || floatingRef.current?.contains(next)))
139
+ return;
140
+ scheduleHide();
141
+ };
142
+ const limit = Math.max(1, maxDefinitionLength);
143
+ const short = definition.length > limit ? `${definition.slice(0, limit - 1).trimEnd()}\u2026` : definition;
144
+ const triggerClasses = chunkS5RVSXDV_cjs.cn(
145
+ "cursor-help",
146
+ underline && "decoration-primary-400/70 underline decoration-dashed underline-offset-4",
147
+ className
148
+ );
149
+ const triggerProps = {
150
+ onClick: onTriggerClick,
151
+ className: chunkS5RVSXDV_cjs.cn(
152
+ triggerClasses,
153
+ href && "text-primary-800 dark:text-primary-400 font-medium"
154
+ )
155
+ };
156
+ return /* @__PURE__ */ jsxRuntime.jsxs(
157
+ "span",
158
+ {
159
+ ref: anchorRef,
160
+ className: "relative inline",
161
+ onMouseEnter: show,
162
+ onMouseLeave: scheduleHide,
163
+ onFocus: onTriggerFocus,
164
+ onBlur: onBlurCapture,
165
+ children: [
166
+ href ? /* @__PURE__ */ jsxRuntime.jsx(
167
+ "a",
168
+ {
169
+ href,
170
+ "aria-expanded": open,
171
+ "aria-haspopup": "dialog",
172
+ ...triggerProps,
173
+ children
174
+ }
175
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
176
+ "button",
177
+ {
178
+ type: "button",
179
+ "aria-expanded": open,
180
+ "aria-haspopup": "dialog",
181
+ "aria-label": `${term} \u2014 show definition`,
182
+ onKeyDown: onTriggerKeyDown,
183
+ ...triggerProps,
184
+ className: chunkS5RVSXDV_cjs.cn(
185
+ "inline appearance-none border-0 bg-transparent p-0 text-inherit [font:inherit]",
186
+ triggerProps.className
187
+ ),
188
+ children
189
+ }
190
+ ),
191
+ open && reactDom.createPortal(
192
+ /* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions -- keyboard dismissal on a focused non-modal dialog container is the WAI-ARIA pattern; links inside keep their own semantics */
193
+ /* @__PURE__ */ jsxRuntime.jsx(
194
+ "span",
195
+ {
196
+ ref: floatingRef,
197
+ role: "dialog",
198
+ "aria-label": term,
199
+ tabIndex: -1,
200
+ onMouseEnter: show,
201
+ onMouseLeave: scheduleHide,
202
+ onBlurCapture,
203
+ onKeyDown: onDialogKeyDown,
204
+ className: "focus-visible:ring-ring z-50 block w-80 rounded-lg outline-none focus-visible:ring-2",
205
+ style,
206
+ children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "border-border bg-card block overflow-hidden rounded-lg border text-start font-normal tracking-normal normal-case shadow-xl ring-1 ring-black/5 dark:ring-white/10", children: [
207
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "from-primary-700 to-primary-600 block bg-gradient-to-br px-3.5 py-2.5", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-start justify-between gap-2", children: [
208
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "block min-w-0", children: [
209
+ category && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1 inline-flex rounded-full bg-white/15 px-2 py-0.5 text-[10px] font-bold tracking-wide text-white uppercase", children: category }),
210
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-sm leading-snug font-semibold text-white", children: term })
211
+ ] }),
212
+ pinned && /* @__PURE__ */ jsxRuntime.jsx(
213
+ "button",
214
+ {
215
+ type: "button",
216
+ onClick: close,
217
+ "aria-label": "Close definition",
218
+ className: "shrink-0 rounded p-0.5 text-white/70 hover:bg-white/10 hover:text-white",
219
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { "aria-hidden": "true", className: "h-3.5 w-3.5" })
220
+ }
221
+ )
222
+ ] }) }),
223
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "block px-3.5 py-2.5", children: [
224
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground block text-[13px] leading-relaxed", children: short }),
225
+ keyFact && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "mt-2 flex items-start gap-1.5", children: [
226
+ /* @__PURE__ */ jsxRuntime.jsx(
227
+ lucideReact.Diamond,
228
+ {
229
+ "aria-hidden": "true",
230
+ className: "text-primary-500 mt-0.5 h-3 w-3 shrink-0"
231
+ }
232
+ ),
233
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground min-w-0 text-xs leading-relaxed font-medium", children: keyFact })
234
+ ] })
235
+ ] }),
236
+ (source || related && related.length > 0 || href) && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "border-border bg-muted/50 block border-t px-3.5 py-2", children: [
237
+ related && related.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mb-1.5 flex flex-wrap gap-1", children: related.map(
238
+ (r) => r.href ? /* @__PURE__ */ jsxRuntime.jsx(
239
+ "a",
240
+ {
241
+ href: r.href,
242
+ className: "border-border bg-card text-foreground hover:border-primary-400 hover:text-primary-800 dark:hover:text-primary-400 rounded-full border px-2 py-0.5 text-[11px] font-medium",
243
+ children: r.term
244
+ },
245
+ r.term
246
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
247
+ "span",
248
+ {
249
+ className: "border-border bg-card text-muted-foreground rounded-full border px-2 py-0.5 text-[11px] font-medium",
250
+ children: r.term
251
+ },
252
+ r.term
253
+ )
254
+ ) }),
255
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center justify-between gap-2", children: [
256
+ source ? /* @__PURE__ */ jsxRuntime.jsx(
257
+ "a",
258
+ {
259
+ href: source.url,
260
+ target: "_blank",
261
+ rel: "noopener noreferrer",
262
+ className: "text-primary-800 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300 min-w-0 truncate text-[11px] font-semibold",
263
+ children: source.label
264
+ }
265
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
266
+ href && /* @__PURE__ */ jsxRuntime.jsxs(
267
+ "a",
268
+ {
269
+ href,
270
+ className: "text-muted-foreground hover:text-foreground inline-flex shrink-0 items-center gap-0.5 text-[11px] font-medium",
271
+ children: [
272
+ "Full definition",
273
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { "aria-hidden": "true", className: "h-3 w-3" })
274
+ ]
275
+ }
276
+ )
277
+ ] })
278
+ ] })
279
+ ] })
280
+ }
281
+ ),
282
+ document.body
283
+ )
284
+ ]
285
+ }
286
+ );
287
+ }
288
+
289
+ exports.GlossaryTooltip = GlossaryTooltip;
290
+ //# sourceMappingURL=chunk-7L7OPISJ.cjs.map
291
+ //# sourceMappingURL=chunk-7L7OPISJ.cjs.map