@mieweb/ui 0.11.0-dev.44 → 0.11.0-dev.46
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.
- package/dist/{EncounterMdyEditor-L7RBLE7B.js → EncounterMdyEditor-ATNWXQ72.js} +3 -3
- package/dist/{EncounterMdyEditor-L7RBLE7B.js.map → EncounterMdyEditor-ATNWXQ72.js.map} +1 -1
- package/dist/{EncounterMdyEditor-46WMYRFI.cjs → EncounterMdyEditor-XA7HLLVD.cjs} +6 -6
- package/dist/{EncounterMdyEditor-46WMYRFI.cjs.map → EncounterMdyEditor-XA7HLLVD.cjs.map} +1 -1
- package/dist/ag-grid.cjs +2 -2
- package/dist/ag-grid.js +1 -1
- package/dist/{chunk-L3CAWGBU.js → chunk-2D6TFO2Y.js} +3 -3
- package/dist/{chunk-L3CAWGBU.js.map → chunk-2D6TFO2Y.js.map} +1 -1
- package/dist/{chunk-AHYDJN4H.cjs → chunk-2XHPPOXY.cjs} +32 -32
- package/dist/{chunk-AHYDJN4H.cjs.map → chunk-2XHPPOXY.cjs.map} +1 -1
- package/dist/{chunk-3IKIRGHI.cjs → chunk-3H6BQV2D.cjs} +6 -6
- package/dist/{chunk-3IKIRGHI.cjs.map → chunk-3H6BQV2D.cjs.map} +1 -1
- package/dist/{chunk-IIV5GNSK.cjs → chunk-3PT4B4JT.cjs} +4 -4
- package/dist/{chunk-IIV5GNSK.cjs.map → chunk-3PT4B4JT.cjs.map} +1 -1
- package/dist/{chunk-GLG6UE2H.cjs → chunk-3SEQVGLH.cjs} +4 -4
- package/dist/{chunk-GLG6UE2H.cjs.map → chunk-3SEQVGLH.cjs.map} +1 -1
- package/dist/{chunk-JUY2JLFL.js → chunk-3XDU7XIC.js} +3 -3
- package/dist/{chunk-JUY2JLFL.js.map → chunk-3XDU7XIC.js.map} +1 -1
- package/dist/{chunk-LQ22CY7X.js → chunk-46ZUORUE.js} +5 -5
- package/dist/{chunk-LQ22CY7X.js.map → chunk-46ZUORUE.js.map} +1 -1
- package/dist/{chunk-CKECOCYJ.js → chunk-4IOIDS2Z.js} +3 -3
- package/dist/{chunk-CKECOCYJ.js.map → chunk-4IOIDS2Z.js.map} +1 -1
- package/dist/{chunk-NCG7NJAW.cjs → chunk-5O54NWAL.cjs} +83 -9
- package/dist/chunk-5O54NWAL.cjs.map +1 -0
- package/dist/{chunk-XX6PNPF2.cjs → chunk-5UKGOBCZ.cjs} +16 -2
- package/dist/chunk-5UKGOBCZ.cjs.map +1 -0
- package/dist/{chunk-HH7PWD5I.cjs → chunk-6I2G26AX.cjs} +27 -23
- package/dist/chunk-6I2G26AX.cjs.map +1 -0
- package/dist/{chunk-F7SZSOB3.js → chunk-6PCA5H47.js} +3 -3
- package/dist/{chunk-F7SZSOB3.js.map → chunk-6PCA5H47.js.map} +1 -1
- package/dist/{chunk-ULEX7OOJ.js → chunk-6Y6W5DUY.js} +4 -4
- package/dist/{chunk-ULEX7OOJ.js.map → chunk-6Y6W5DUY.js.map} +1 -1
- package/dist/{chunk-S7AMZ4RD.cjs → chunk-7K6SW4VB.cjs} +4 -4
- package/dist/{chunk-S7AMZ4RD.cjs.map → chunk-7K6SW4VB.cjs.map} +1 -1
- package/dist/{chunk-KY67AMQ5.cjs → chunk-7MF3O3BU.cjs} +4 -4
- package/dist/{chunk-KY67AMQ5.cjs.map → chunk-7MF3O3BU.cjs.map} +1 -1
- package/dist/{chunk-Z3WMDVMR.cjs → chunk-7QNBPB7F.cjs} +9 -5
- package/dist/chunk-7QNBPB7F.cjs.map +1 -0
- package/dist/{chunk-YFWDS6MX.js → chunk-AB24H2RM.js} +3 -3
- package/dist/{chunk-YFWDS6MX.js.map → chunk-AB24H2RM.js.map} +1 -1
- package/dist/{chunk-2W73UQ3T.js → chunk-BPYI7BDC.js} +3 -3
- package/dist/{chunk-2W73UQ3T.js.map → chunk-BPYI7BDC.js.map} +1 -1
- package/dist/{chunk-EAAVFTKI.cjs → chunk-BUM72SAI.cjs} +35 -17
- package/dist/chunk-BUM72SAI.cjs.map +1 -0
- package/dist/{chunk-AHT2HRHC.cjs → chunk-CFT3P5KP.cjs} +16 -16
- package/dist/{chunk-AHT2HRHC.cjs.map → chunk-CFT3P5KP.cjs.map} +1 -1
- package/dist/{chunk-7U7SONM5.js → chunk-CVCUQ2MZ.js} +3 -3
- package/dist/{chunk-7U7SONM5.js.map → chunk-CVCUQ2MZ.js.map} +1 -1
- package/dist/{chunk-PWXDRFJL.cjs → chunk-DHEOWRIE.cjs} +6 -6
- package/dist/{chunk-PWXDRFJL.cjs.map → chunk-DHEOWRIE.cjs.map} +1 -1
- package/dist/{chunk-2KK4WZ7Y.cjs → chunk-F6ZTKNAL.cjs} +4 -4
- package/dist/{chunk-2KK4WZ7Y.cjs.map → chunk-F6ZTKNAL.cjs.map} +1 -1
- package/dist/{chunk-OYUIEJPN.js → chunk-GTRYDFMT.js} +38 -10
- package/dist/chunk-GTRYDFMT.js.map +1 -0
- package/dist/{chunk-2FZYZ4HT.cjs → chunk-HDSYYQYM.cjs} +4 -4
- package/dist/{chunk-2FZYZ4HT.cjs.map → chunk-HDSYYQYM.cjs.map} +1 -1
- package/dist/{chunk-JCIQIR5V.js → chunk-IGUDEWIW.js} +4 -4
- package/dist/{chunk-JCIQIR5V.js.map → chunk-IGUDEWIW.js.map} +1 -1
- package/dist/{chunk-DIIXY6EB.js → chunk-IYXZ25E6.js} +27 -9
- package/dist/chunk-IYXZ25E6.js.map +1 -0
- package/dist/{chunk-YVKBXNPK.js → chunk-JBNQ2L3K.js} +10 -6
- package/dist/chunk-JBNQ2L3K.js.map +1 -0
- package/dist/{chunk-GU6TPVXF.cjs → chunk-JK2IWOI7.cjs} +6 -6
- package/dist/{chunk-GU6TPVXF.cjs.map → chunk-JK2IWOI7.cjs.map} +1 -1
- package/dist/{chunk-TZKBW4GA.cjs → chunk-K76UNS22.cjs} +6 -6
- package/dist/{chunk-TZKBW4GA.cjs.map → chunk-K76UNS22.cjs.map} +1 -1
- package/dist/{chunk-DAAJ3B2T.js → chunk-KP72MDFB.js} +4 -4
- package/dist/{chunk-DAAJ3B2T.js.map → chunk-KP72MDFB.js.map} +1 -1
- package/dist/{chunk-MLCIINXT.js → chunk-LBUXS6FJ.js} +4 -4
- package/dist/{chunk-MLCIINXT.js.map → chunk-LBUXS6FJ.js.map} +1 -1
- package/dist/{chunk-MD55WRGN.cjs → chunk-LE3HZ7MM.cjs} +37 -37
- package/dist/{chunk-MD55WRGN.cjs.map → chunk-LE3HZ7MM.cjs.map} +1 -1
- package/dist/{chunk-GG3IK5TL.cjs → chunk-MQK2D6I6.cjs} +9 -9
- package/dist/{chunk-GG3IK5TL.cjs.map → chunk-MQK2D6I6.cjs.map} +1 -1
- package/dist/{chunk-3A4N5E6P.js → chunk-N6STVVB6.js} +3 -3
- package/dist/{chunk-3A4N5E6P.js.map → chunk-N6STVVB6.js.map} +1 -1
- package/dist/{chunk-5WA6IYZD.js → chunk-NB2C6FSI.js} +16 -2
- package/dist/chunk-NB2C6FSI.js.map +1 -0
- package/dist/{chunk-2GBVJHWN.cjs → chunk-NH5JOZLG.cjs} +13 -13
- package/dist/{chunk-2GBVJHWN.cjs.map → chunk-NH5JOZLG.cjs.map} +1 -1
- package/dist/{chunk-NWU634SO.cjs → chunk-O2EAHOXM.cjs} +4 -4
- package/dist/{chunk-NWU634SO.cjs.map → chunk-O2EAHOXM.cjs.map} +1 -1
- package/dist/{chunk-JUYBJLPI.cjs → chunk-O7Y56J4R.cjs} +4 -4
- package/dist/{chunk-JUYBJLPI.cjs.map → chunk-O7Y56J4R.cjs.map} +1 -1
- package/dist/{chunk-GLRKXJCR.js → chunk-OX32ITWC.js} +3 -3
- package/dist/{chunk-GLRKXJCR.js.map → chunk-OX32ITWC.js.map} +1 -1
- package/dist/{chunk-L4APW65W.cjs → chunk-PJ4XEBMU.cjs} +4 -4
- package/dist/{chunk-L4APW65W.cjs.map → chunk-PJ4XEBMU.cjs.map} +1 -1
- package/dist/{chunk-OZKJYLN6.js → chunk-PSCSU63K.js} +3 -3
- package/dist/{chunk-OZKJYLN6.js.map → chunk-PSCSU63K.js.map} +1 -1
- package/dist/{chunk-ZULFKL3C.js → chunk-QJ75ZMCG.js} +7 -7
- package/dist/{chunk-ZULFKL3C.js.map → chunk-QJ75ZMCG.js.map} +1 -1
- package/dist/{chunk-EI4JU5JF.js → chunk-RKM4VGAN.js} +3 -3
- package/dist/{chunk-EI4JU5JF.js.map → chunk-RKM4VGAN.js.map} +1 -1
- package/dist/{chunk-ME7EVT6F.js → chunk-RYGVILUR.js} +3 -3
- package/dist/{chunk-ME7EVT6F.js.map → chunk-RYGVILUR.js.map} +1 -1
- package/dist/{chunk-EGPDT7SM.js → chunk-S7NJV335.js} +3 -3
- package/dist/{chunk-EGPDT7SM.js.map → chunk-S7NJV335.js.map} +1 -1
- package/dist/{chunk-TERHGQ73.cjs → chunk-U7XWWU5H.cjs} +5 -5
- package/dist/{chunk-TERHGQ73.cjs.map → chunk-U7XWWU5H.cjs.map} +1 -1
- package/dist/{chunk-G35LXI2A.js → chunk-UIFN2LYT.js} +3 -3
- package/dist/{chunk-G35LXI2A.js.map → chunk-UIFN2LYT.js.map} +1 -1
- package/dist/{chunk-NIE3WBJH.js → chunk-ULKDK6W6.js} +83 -9
- package/dist/chunk-ULKDK6W6.js.map +1 -0
- package/dist/{chunk-KB2PLV5Q.js → chunk-VQGRMCVT.js} +4 -4
- package/dist/{chunk-KB2PLV5Q.js.map → chunk-VQGRMCVT.js.map} +1 -1
- package/dist/{chunk-IPHJQ6CF.js → chunk-WI35L5TR.js} +10 -6
- package/dist/chunk-WI35L5TR.js.map +1 -0
- package/dist/{chunk-Q6QLGCL7.cjs → chunk-XCCH5KHW.cjs} +9 -9
- package/dist/{chunk-Q6QLGCL7.cjs.map → chunk-XCCH5KHW.cjs.map} +1 -1
- package/dist/{chunk-KQXD6BFO.cjs → chunk-XM3D4KAF.cjs} +9 -9
- package/dist/{chunk-KQXD6BFO.cjs.map → chunk-XM3D4KAF.cjs.map} +1 -1
- package/dist/{chunk-PINIBEIU.cjs → chunk-XRXOGMMG.cjs} +39 -11
- package/dist/chunk-XRXOGMMG.cjs.map +1 -0
- package/dist/{chunk-XPWFIDZM.cjs → chunk-XU3X2AUL.cjs} +4 -4
- package/dist/{chunk-XPWFIDZM.cjs.map → chunk-XU3X2AUL.cjs.map} +1 -1
- package/dist/{chunk-CRR7AE5D.js → chunk-Z6I4XFPC.js} +3 -3
- package/dist/{chunk-CRR7AE5D.js.map → chunk-Z6I4XFPC.js.map} +1 -1
- package/dist/{chunk-LTCHD3K5.cjs → chunk-Z7ZOSENN.cjs} +5 -5
- package/dist/{chunk-LTCHD3K5.cjs.map → chunk-Z7ZOSENN.cjs.map} +1 -1
- package/dist/{chunk-NZUQL42A.cjs → chunk-ZDA6FEKA.cjs} +5 -5
- package/dist/{chunk-NZUQL42A.cjs.map → chunk-ZDA6FEKA.cjs.map} +1 -1
- package/dist/{chunk-UY2EZYIC.js → chunk-ZSBG6C3P.js} +3 -3
- package/dist/{chunk-UY2EZYIC.js.map → chunk-ZSBG6C3P.js.map} +1 -1
- package/dist/{chunk-KAQNYX7B.js → chunk-ZVRJVUFX.js} +3 -3
- package/dist/{chunk-KAQNYX7B.js.map → chunk-ZVRJVUFX.js.map} +1 -1
- package/dist/components/AudioPlayer/index.cjs +7 -7
- package/dist/components/AudioPlayer/index.js +2 -2
- package/dist/components/BoardView/index.cjs +5 -5
- package/dist/components/BoardView/index.js +2 -2
- package/dist/components/CollabStatus/index.cjs +5 -5
- package/dist/components/CollabStatus/index.js +2 -2
- package/dist/components/Dropdown/index.cjs +9 -9
- package/dist/components/Dropdown/index.d.cts +6 -1
- package/dist/components/Dropdown/index.d.ts +6 -1
- package/dist/components/Dropdown/index.js +2 -2
- package/dist/components/EmailEditor/index.cjs +17 -17
- package/dist/components/EmailEditor/index.js +8 -8
- package/dist/components/MediaEditor/index.cjs +10 -10
- package/dist/components/MediaEditor/index.js +5 -5
- package/dist/components/MediaFeed/index.cjs +6 -6
- package/dist/components/MediaFeed/index.js +5 -5
- package/dist/components/MediaPlayer/index.cjs +8 -8
- package/dist/components/MediaPlayer/index.js +4 -4
- package/dist/components/MegaMenu/index.cjs +5 -5
- package/dist/components/MegaMenu/index.js +2 -2
- package/dist/components/RecordHeader/index.cjs +5 -5
- package/dist/components/RecordHeader/index.js +3 -3
- package/dist/components/RecordLayout/index.cjs +5 -5
- package/dist/components/RecordLayout/index.js +3 -3
- package/dist/components/RichTextEditor/index.cjs +6 -6
- package/dist/components/RichTextEditor/index.js +3 -3
- package/dist/components/Slider/index.cjs +6 -6
- package/dist/components/Slider/index.js +2 -2
- package/dist/components/SliderCalculator/index.cjs +5 -5
- package/dist/components/SliderCalculator/index.js +3 -3
- package/dist/components/SuperChat/index.cjs +23 -23
- package/dist/components/SuperChat/index.js +8 -8
- package/dist/components/SuperChat/plugins/index.cjs +5 -5
- package/dist/components/SuperChat/plugins/index.js +4 -4
- package/dist/components/Tabs/index.cjs +8 -8
- package/dist/components/Tabs/index.js +2 -2
- package/dist/components/Textarea/index.cjs +9 -9
- package/dist/components/Textarea/index.js +6 -6
- package/dist/components/ThemeProvider/index.cjs +9 -9
- package/dist/components/ThemeProvider/index.js +3 -3
- package/dist/components/Tooltip/index.cjs +3 -3
- package/dist/components/Tooltip/index.js +2 -2
- package/dist/components/ViewSet/index.cjs +5 -5
- package/dist/components/ViewSet/index.js +4 -4
- package/dist/components/ViewSwitcher/index.cjs +4 -4
- package/dist/components/ViewSwitcher/index.js +2 -2
- package/dist/deck.cjs +3 -3
- package/dist/deck.js +1 -1
- package/dist/esheet.cjs +109 -109
- package/dist/esheet.js +12 -12
- package/dist/hooks/index.cjs +5 -5
- package/dist/hooks/index.js +1 -1
- package/dist/index.cjs +288 -288
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +42 -42
- package/dist/kerebron.cjs +8 -8
- package/dist/kerebron.d.cts +27 -2
- package/dist/kerebron.d.ts +27 -2
- package/dist/kerebron.js +5 -5
- package/dist/{model-5PB6KNYH.cjs → model-2TISYEYF.cjs} +20 -20
- package/dist/{model-5PB6KNYH.cjs.map → model-2TISYEYF.cjs.map} +1 -1
- package/dist/{model-OGWTZEXR.js → model-BCS5BUK3.js} +6 -6
- package/dist/{model-OGWTZEXR.js.map → model-BCS5BUK3.js.map} +1 -1
- package/dist/org-chart.cjs +2 -2
- package/dist/org-chart.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/tailwind-preset.cjs +4 -4
- package/dist/tailwind-preset.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-5WA6IYZD.js.map +0 -1
- package/dist/chunk-DIIXY6EB.js.map +0 -1
- package/dist/chunk-EAAVFTKI.cjs.map +0 -1
- package/dist/chunk-HH7PWD5I.cjs.map +0 -1
- package/dist/chunk-IPHJQ6CF.js.map +0 -1
- package/dist/chunk-NCG7NJAW.cjs.map +0 -1
- package/dist/chunk-NIE3WBJH.js.map +0 -1
- package/dist/chunk-OYUIEJPN.js.map +0 -1
- package/dist/chunk-PINIBEIU.cjs.map +0 -1
- package/dist/chunk-XX6PNPF2.cjs.map +0 -1
- package/dist/chunk-YVKBXNPK.js.map +0 -1
- package/dist/chunk-Z3WMDVMR.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/SliderCalculator/SliderCalculator.tsx"],"names":["usePrefersReducedMotion","React","jsx","cn","jsxs","Slider","ChevronUp","ChevronDown"],"mappings":"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","file":"chunk-JUYBJLPI.cjs","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { ChevronDown, ChevronUp } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { Slider } from '../Slider';\nimport { usePrefersReducedMotion } from '../../hooks/usePrefersReducedMotion';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type CalculatorFormat =\n | 'number'\n | 'currency'\n | 'compactCurrency'\n | 'percent'\n | 'hours'\n | ((value: number) => string);\n\nexport interface CalculatorInput {\n /** Key in the values object passed to `compute`. */\n id: string;\n label: string;\n min: number;\n max: number;\n step?: number;\n /** Starting value. */\n defaultValue: number;\n /** How the current value renders next to the label. Default `number`. */\n format?: CalculatorFormat;\n description?: string;\n}\n\nexport interface CalculatorBreakdown {\n label: string;\n value: number;\n}\n\nexport interface CalculatorMathRow {\n label: string;\n value: string;\n}\n\nexport interface CalculatorResult {\n /** The headline number. */\n total: number;\n /** One-line context under the headline, e.g. \"42% of today's spend · 1,200 hours returned\". */\n summary?: string;\n /** Horizontal bars showing what makes up `total`. */\n breakdown?: CalculatorBreakdown[];\n /** Rows revealed by \"Show the math\". */\n math?: CalculatorMathRow[];\n /** Free-text assumptions listed under the math. */\n assumptions?: string[];\n}\n\nexport interface SliderCalculatorProps {\n inputs: CalculatorInput[];\n /** Pure function from current values to a result. Runs on every change. */\n compute: (values: Record<string, number>) => CalculatorResult;\n /** Copy for the controls column. */\n eyebrow?: string;\n heading?: string;\n description?: string;\n headingLevel?: 'h2' | 'h3';\n /** Label above the headline number. Default \"Estimated annual value\". */\n resultLabel?: string;\n /** Format for the headline. Default `compactCurrency`. */\n resultFormat?: CalculatorFormat;\n /** Format for breakdown values. Default `currency`. */\n breakdownFormat?: CalculatorFormat;\n /** Actions under the result (Buttons, links). */\n actions?: React.ReactNode;\n /** Small print under the actions. */\n footnote?: string;\n /** Labels for the math toggle. */\n mathLabels?: { show?: string; hide?: string };\n /** Currency for the built-in formatters. Default `USD`. */\n currency?: string;\n locale?: string;\n /** Fires with the latest values and result on every change. */\n onChange?: (values: Record<string, number>, result: CalculatorResult) => void;\n className?: string;\n}\n\n// =============================================================================\n// Formatting\n// =============================================================================\n\nfunction makeFormatter(\n format: CalculatorFormat | undefined,\n locale: string,\n currency: string\n): (v: number) => string {\n if (typeof format === 'function') return format;\n switch (format) {\n case 'currency':\n return (v) =>\n v.toLocaleString(locale, {\n style: 'currency',\n currency,\n maximumFractionDigits: 0,\n });\n case 'compactCurrency':\n return (v) =>\n v.toLocaleString(locale, {\n style: 'currency',\n currency,\n notation: 'compact',\n maximumFractionDigits: v >= 1_000_000 ? 2 : 0,\n });\n case 'percent':\n return (v) => `${v.toLocaleString(locale)}%`;\n case 'hours':\n return (v) => `${v.toLocaleString(locale)} hr`;\n default:\n return (v) => v.toLocaleString(locale);\n }\n}\n\n// =============================================================================\n// AnimatedNumber\n// =============================================================================\n\nexport interface AnimatedNumberProps {\n value: number;\n format?: (v: number) => string;\n /** Tween length in ms. Default 480. */\n duration?: number;\n className?: string;\n}\n\n/** Tweens between numeric values with an ease-out; snaps under reduced motion. */\nexport function AnimatedNumber({\n value,\n format = (v) => v.toLocaleString(),\n duration = 480,\n className,\n}: AnimatedNumberProps) {\n const reduced = usePrefersReducedMotion();\n const [shown, setShown] = React.useState(value);\n const shownRef = React.useRef(value);\n\n React.useEffect(() => {\n if (reduced || typeof window === 'undefined') {\n shownRef.current = value;\n setShown(value);\n return;\n }\n const from = shownRef.current;\n const start = performance.now();\n let raf = 0;\n const tick = (t: number) => {\n const p = Math.min(1, (t - start) / duration);\n const eased = 1 - Math.pow(1 - p, 3);\n const v = from + (value - from) * eased;\n shownRef.current = v;\n setShown(v);\n if (p < 1) raf = requestAnimationFrame(tick);\n };\n raf = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(raf);\n }, [value, duration, reduced]);\n\n return (\n <span className={cn('tabular-nums', className)} data-slot=\"animated-number\">\n {format(shown)}\n </span>\n );\n}\n\n// =============================================================================\n// SliderCalculator\n// =============================================================================\n\n/**\n * A two-column interactive calculator: labelled sliders on the left, a live\n * result panel on the right with an animated headline number, a one-line\n * summary, proportional breakdown bars, a \"Show the math\" disclosure and an\n * actions slot. Bring your own `compute` — the component owns only the\n * interaction. Ported from the Enterprise Health ROI calculator.\n *\n * @example\n * ```tsx\n * <SliderCalculator\n * heading=\"What is consolidation worth?\"\n * inputs={[\n * { id: 'people', label: 'People covered', min: 500, max: 60000, step: 500, defaultValue: 8000 },\n * { id: 'cost', label: 'Cost per exam', min: 20, max: 400, step: 5, defaultValue: 120, format: 'currency' },\n * ]}\n * compute={({ people, cost }) => ({ total: people * cost * 0.18 })}\n * actions={<Button effect=\"sheen\">Request a demo</Button>}\n * />\n * ```\n */\nexport function SliderCalculator({\n inputs,\n compute,\n eyebrow,\n heading,\n description,\n headingLevel: Heading = 'h2',\n resultLabel = 'Estimated annual value',\n resultFormat = 'compactCurrency',\n breakdownFormat = 'currency',\n actions,\n footnote,\n mathLabels,\n currency = 'USD',\n locale = 'en-US',\n onChange,\n className,\n}: SliderCalculatorProps) {\n const [values, setValues] = React.useState<Record<string, number>>(() =>\n Object.fromEntries(inputs.map((i) => [i.id, i.defaultValue]))\n );\n const [showMath, setShowMath] = React.useState(false);\n const id = React.useId();\n\n const result = React.useMemo(() => compute(values), [compute, values]);\n\n // Notify from an effect keyed on `values` only. `result` and `onChange` are\n // read through a ref: an inline `compute` or `onChange` prop gets a new\n // identity on every parent render, and depending on either would re-fire the\n // notification (and potentially loop) without any actual slider change.\n const skipInitialNotify = React.useRef(true);\n const notifyRef = React.useRef({ onChange, result });\n notifyRef.current = { onChange, result };\n React.useEffect(() => {\n if (skipInitialNotify.current) {\n skipInitialNotify.current = false;\n return;\n }\n notifyRef.current.onChange?.(values, notifyRef.current.result);\n }, [values]);\n\n const fmtResult = React.useMemo(\n () => makeFormatter(resultFormat, locale, currency),\n [resultFormat, locale, currency]\n );\n const fmtBreakdown = makeFormatter(breakdownFormat, locale, currency);\n\n // Announce only the settled total. The result container previously carried\n // aria-live while `AnimatedNumber` updated every animation frame, so screen\n // readers could queue or repeat intermediate values during a drag.\n const [announced, setAnnounced] = React.useState('');\n const skipInitialAnnounce = React.useRef(true);\n React.useEffect(() => {\n if (skipInitialAnnounce.current) {\n skipInitialAnnounce.current = false;\n return;\n }\n const t = window.setTimeout(\n () => setAnnounced(fmtResult(result.total)),\n 600\n );\n return () => window.clearTimeout(t);\n }, [result.total, fmtResult]);\n\n const labels = {\n show: 'Show the math',\n hide: 'Hide the math',\n ...mathLabels,\n };\n\n const set = (key: string, v: number) => {\n setValues((prev) => ({ ...prev, [key]: v }));\n };\n\n return (\n <div\n data-slot=\"slider-calculator\"\n className={cn(\n 'border-border bg-card text-card-foreground grid overflow-hidden rounded-2xl border shadow-md',\n 'lg:grid-cols-[1.1fr_1fr]',\n className\n )}\n >\n {/* Controls */}\n <div className=\"p-6 sm:p-8\">\n {eyebrow && (\n <p className=\"text-primary-800 dark:text-primary-300 mb-2 text-[11px] font-bold tracking-[0.14em] uppercase\">\n {eyebrow}\n </p>\n )}\n {heading && (\n <Heading className=\"text-foreground text-2xl leading-tight font-semibold sm:text-3xl\">\n {heading}\n </Heading>\n )}\n {description && (\n <p className=\"text-muted-foreground mt-3 text-sm\">{description}</p>\n )}\n\n <div className={cn('space-y-5', (heading || description) && 'mt-7')}>\n {inputs.map((input) => (\n <Slider\n key={input.id}\n id={`${id}-${input.id}`}\n label={input.label}\n description={input.description}\n min={input.min}\n max={input.max}\n step={input.step}\n value={values[input.id]}\n onValueChange={(v) => set(input.id, v)}\n showValue\n formatValue={makeFormatter(input.format, locale, currency)}\n />\n ))}\n </div>\n </div>\n\n {/* Result */}\n <div\n data-slot=\"slider-calculator-result\"\n className=\"bg-primary-950 flex flex-col gap-6 p-6 text-white [background:radial-gradient(120%_120%_at_100%_0%,var(--mieweb-primary-800),var(--mieweb-primary-950)_70%)] sm:p-8\"\n >\n <span aria-live=\"polite\" className=\"sr-only\">\n {announced ? `${resultLabel}: ${announced}` : ''}\n </span>\n <div>\n <p className=\"text-[11px] font-bold tracking-[0.14em] text-white/70 uppercase\">\n {resultLabel}\n </p>\n <p className=\"mt-2 text-5xl leading-none font-semibold tracking-tight sm:text-6xl\">\n <AnimatedNumber value={result.total} format={fmtResult} />\n </p>\n {result.summary && (\n <p className=\"mt-3 text-sm text-white/80\">{result.summary}</p>\n )}\n </div>\n\n {result.breakdown && result.breakdown.length > 0 && (\n <div className=\"space-y-3\">\n {result.breakdown.map((b) => {\n const pct =\n result.total > 0\n ? Math.max(2, Math.min(100, (b.value / result.total) * 100))\n : 0;\n return (\n <div key={b.label}>\n <div className=\"mb-1 flex items-baseline justify-between gap-3 text-sm\">\n <span className=\"text-white/80\">{b.label}</span>\n <b className=\"tabular-nums\">\n <AnimatedNumber\n value={Math.max(b.value, 0)}\n format={fmtBreakdown}\n />\n </b>\n </div>\n <div className=\"h-1.5 overflow-hidden rounded-full bg-white/15\">\n <span\n className=\"block h-full rounded-full transition-[width] duration-500 ease-out [background:linear-gradient(90deg,var(--mieweb-accent,var(--mieweb-primary-300)),var(--mieweb-primary-300))]\"\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n })}\n </div>\n )}\n\n {(result.math?.length || result.assumptions?.length) && (\n <div>\n <button\n type=\"button\"\n onClick={() => setShowMath((v) => !v)}\n aria-expanded={showMath}\n aria-controls={`${id}-math`}\n className=\"inline-flex items-center gap-1 text-sm font-semibold text-white/80 underline-offset-4 hover:text-white hover:underline\"\n >\n {showMath ? labels.hide : labels.show}\n {showMath ? (\n <ChevronUp size={14} aria-hidden />\n ) : (\n <ChevronDown size={14} aria-hidden />\n )}\n </button>\n {showMath && (\n <div\n id={`${id}-math`}\n className=\"mt-3 rounded-xl border border-white/15 bg-white/5 p-4 text-sm\"\n >\n {result.math?.map((row) => (\n <div\n key={row.label}\n className=\"flex justify-between gap-4 border-b border-white/10 py-1.5 last:border-0\"\n >\n <span className=\"text-white/75\">{row.label}</span>\n <b className=\"tabular-nums\">{row.value}</b>\n </div>\n ))}\n {result.assumptions && result.assumptions.length > 0 && (\n <ul className=\"mt-3 list-disc space-y-1 ps-5 text-xs text-white/70\">\n {result.assumptions.map((a) => (\n <li key={a}>{a}</li>\n ))}\n </ul>\n )}\n </div>\n )}\n </div>\n )}\n\n {actions && (\n <div className=\"mt-auto flex flex-wrap gap-3\">{actions}</div>\n )}\n {footnote && <p className=\"text-xs text-white/60\">{footnote}</p>}\n </div>\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/SliderCalculator/SliderCalculator.tsx"],"names":["usePrefersReducedMotion","React","jsx","cn","jsxs","Slider","ChevronUp","ChevronDown"],"mappings":"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","file":"chunk-O7Y56J4R.cjs","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { ChevronDown, ChevronUp } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { Slider } from '../Slider';\nimport { usePrefersReducedMotion } from '../../hooks/usePrefersReducedMotion';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type CalculatorFormat =\n | 'number'\n | 'currency'\n | 'compactCurrency'\n | 'percent'\n | 'hours'\n | ((value: number) => string);\n\nexport interface CalculatorInput {\n /** Key in the values object passed to `compute`. */\n id: string;\n label: string;\n min: number;\n max: number;\n step?: number;\n /** Starting value. */\n defaultValue: number;\n /** How the current value renders next to the label. Default `number`. */\n format?: CalculatorFormat;\n description?: string;\n}\n\nexport interface CalculatorBreakdown {\n label: string;\n value: number;\n}\n\nexport interface CalculatorMathRow {\n label: string;\n value: string;\n}\n\nexport interface CalculatorResult {\n /** The headline number. */\n total: number;\n /** One-line context under the headline, e.g. \"42% of today's spend · 1,200 hours returned\". */\n summary?: string;\n /** Horizontal bars showing what makes up `total`. */\n breakdown?: CalculatorBreakdown[];\n /** Rows revealed by \"Show the math\". */\n math?: CalculatorMathRow[];\n /** Free-text assumptions listed under the math. */\n assumptions?: string[];\n}\n\nexport interface SliderCalculatorProps {\n inputs: CalculatorInput[];\n /** Pure function from current values to a result. Runs on every change. */\n compute: (values: Record<string, number>) => CalculatorResult;\n /** Copy for the controls column. */\n eyebrow?: string;\n heading?: string;\n description?: string;\n headingLevel?: 'h2' | 'h3';\n /** Label above the headline number. Default \"Estimated annual value\". */\n resultLabel?: string;\n /** Format for the headline. Default `compactCurrency`. */\n resultFormat?: CalculatorFormat;\n /** Format for breakdown values. Default `currency`. */\n breakdownFormat?: CalculatorFormat;\n /** Actions under the result (Buttons, links). */\n actions?: React.ReactNode;\n /** Small print under the actions. */\n footnote?: string;\n /** Labels for the math toggle. */\n mathLabels?: { show?: string; hide?: string };\n /** Currency for the built-in formatters. Default `USD`. */\n currency?: string;\n locale?: string;\n /** Fires with the latest values and result on every change. */\n onChange?: (values: Record<string, number>, result: CalculatorResult) => void;\n className?: string;\n}\n\n// =============================================================================\n// Formatting\n// =============================================================================\n\nfunction makeFormatter(\n format: CalculatorFormat | undefined,\n locale: string,\n currency: string\n): (v: number) => string {\n if (typeof format === 'function') return format;\n switch (format) {\n case 'currency':\n return (v) =>\n v.toLocaleString(locale, {\n style: 'currency',\n currency,\n maximumFractionDigits: 0,\n });\n case 'compactCurrency':\n return (v) =>\n v.toLocaleString(locale, {\n style: 'currency',\n currency,\n notation: 'compact',\n maximumFractionDigits: v >= 1_000_000 ? 2 : 0,\n });\n case 'percent':\n return (v) => `${v.toLocaleString(locale)}%`;\n case 'hours':\n return (v) => `${v.toLocaleString(locale)} hr`;\n default:\n return (v) => v.toLocaleString(locale);\n }\n}\n\n// =============================================================================\n// AnimatedNumber\n// =============================================================================\n\nexport interface AnimatedNumberProps {\n value: number;\n format?: (v: number) => string;\n /** Tween length in ms. Default 480. */\n duration?: number;\n className?: string;\n}\n\n/** Tweens between numeric values with an ease-out; snaps under reduced motion. */\nexport function AnimatedNumber({\n value,\n format = (v) => v.toLocaleString(),\n duration = 480,\n className,\n}: AnimatedNumberProps) {\n const reduced = usePrefersReducedMotion();\n const [shown, setShown] = React.useState(value);\n const shownRef = React.useRef(value);\n\n React.useEffect(() => {\n if (reduced || typeof window === 'undefined') {\n shownRef.current = value;\n setShown(value);\n return;\n }\n const from = shownRef.current;\n const start = performance.now();\n let raf = 0;\n const tick = (t: number) => {\n const p = Math.min(1, (t - start) / duration);\n const eased = 1 - Math.pow(1 - p, 3);\n const v = from + (value - from) * eased;\n shownRef.current = v;\n setShown(v);\n if (p < 1) raf = requestAnimationFrame(tick);\n };\n raf = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(raf);\n }, [value, duration, reduced]);\n\n return (\n <span className={cn('tabular-nums', className)} data-slot=\"animated-number\">\n {format(shown)}\n </span>\n );\n}\n\n// =============================================================================\n// SliderCalculator\n// =============================================================================\n\n/**\n * A two-column interactive calculator: labelled sliders on the left, a live\n * result panel on the right with an animated headline number, a one-line\n * summary, proportional breakdown bars, a \"Show the math\" disclosure and an\n * actions slot. Bring your own `compute` — the component owns only the\n * interaction. Ported from the Enterprise Health ROI calculator.\n *\n * @example\n * ```tsx\n * <SliderCalculator\n * heading=\"What is consolidation worth?\"\n * inputs={[\n * { id: 'people', label: 'People covered', min: 500, max: 60000, step: 500, defaultValue: 8000 },\n * { id: 'cost', label: 'Cost per exam', min: 20, max: 400, step: 5, defaultValue: 120, format: 'currency' },\n * ]}\n * compute={({ people, cost }) => ({ total: people * cost * 0.18 })}\n * actions={<Button effect=\"sheen\">Request a demo</Button>}\n * />\n * ```\n */\nexport function SliderCalculator({\n inputs,\n compute,\n eyebrow,\n heading,\n description,\n headingLevel: Heading = 'h2',\n resultLabel = 'Estimated annual value',\n resultFormat = 'compactCurrency',\n breakdownFormat = 'currency',\n actions,\n footnote,\n mathLabels,\n currency = 'USD',\n locale = 'en-US',\n onChange,\n className,\n}: SliderCalculatorProps) {\n const [values, setValues] = React.useState<Record<string, number>>(() =>\n Object.fromEntries(inputs.map((i) => [i.id, i.defaultValue]))\n );\n const [showMath, setShowMath] = React.useState(false);\n const id = React.useId();\n\n const result = React.useMemo(() => compute(values), [compute, values]);\n\n // Notify from an effect keyed on `values` only. `result` and `onChange` are\n // read through a ref: an inline `compute` or `onChange` prop gets a new\n // identity on every parent render, and depending on either would re-fire the\n // notification (and potentially loop) without any actual slider change.\n const skipInitialNotify = React.useRef(true);\n const notifyRef = React.useRef({ onChange, result });\n notifyRef.current = { onChange, result };\n React.useEffect(() => {\n if (skipInitialNotify.current) {\n skipInitialNotify.current = false;\n return;\n }\n notifyRef.current.onChange?.(values, notifyRef.current.result);\n }, [values]);\n\n const fmtResult = React.useMemo(\n () => makeFormatter(resultFormat, locale, currency),\n [resultFormat, locale, currency]\n );\n const fmtBreakdown = makeFormatter(breakdownFormat, locale, currency);\n\n // Announce only the settled total. The result container previously carried\n // aria-live while `AnimatedNumber` updated every animation frame, so screen\n // readers could queue or repeat intermediate values during a drag.\n const [announced, setAnnounced] = React.useState('');\n const skipInitialAnnounce = React.useRef(true);\n React.useEffect(() => {\n if (skipInitialAnnounce.current) {\n skipInitialAnnounce.current = false;\n return;\n }\n const t = window.setTimeout(\n () => setAnnounced(fmtResult(result.total)),\n 600\n );\n return () => window.clearTimeout(t);\n }, [result.total, fmtResult]);\n\n const labels = {\n show: 'Show the math',\n hide: 'Hide the math',\n ...mathLabels,\n };\n\n const set = (key: string, v: number) => {\n setValues((prev) => ({ ...prev, [key]: v }));\n };\n\n return (\n <div\n data-slot=\"slider-calculator\"\n className={cn(\n 'border-border bg-card text-card-foreground grid overflow-hidden rounded-2xl border shadow-md',\n 'lg:grid-cols-[1.1fr_1fr]',\n className\n )}\n >\n {/* Controls */}\n <div className=\"p-6 sm:p-8\">\n {eyebrow && (\n <p className=\"text-primary-800 dark:text-primary-300 mb-2 text-[11px] font-bold tracking-[0.14em] uppercase\">\n {eyebrow}\n </p>\n )}\n {heading && (\n <Heading className=\"text-foreground text-2xl leading-tight font-semibold sm:text-3xl\">\n {heading}\n </Heading>\n )}\n {description && (\n <p className=\"text-muted-foreground mt-3 text-sm\">{description}</p>\n )}\n\n <div className={cn('space-y-5', (heading || description) && 'mt-7')}>\n {inputs.map((input) => (\n <Slider\n key={input.id}\n id={`${id}-${input.id}`}\n label={input.label}\n description={input.description}\n min={input.min}\n max={input.max}\n step={input.step}\n value={values[input.id]}\n onValueChange={(v) => set(input.id, v)}\n showValue\n formatValue={makeFormatter(input.format, locale, currency)}\n />\n ))}\n </div>\n </div>\n\n {/* Result */}\n <div\n data-slot=\"slider-calculator-result\"\n className=\"bg-primary-950 flex flex-col gap-6 p-6 text-white [background:radial-gradient(120%_120%_at_100%_0%,var(--mieweb-primary-800),var(--mieweb-primary-950)_70%)] sm:p-8\"\n >\n <span aria-live=\"polite\" className=\"sr-only\">\n {announced ? `${resultLabel}: ${announced}` : ''}\n </span>\n <div>\n <p className=\"text-[11px] font-bold tracking-[0.14em] text-white/70 uppercase\">\n {resultLabel}\n </p>\n <p className=\"mt-2 text-5xl leading-none font-semibold tracking-tight sm:text-6xl\">\n <AnimatedNumber value={result.total} format={fmtResult} />\n </p>\n {result.summary && (\n <p className=\"mt-3 text-sm text-white/80\">{result.summary}</p>\n )}\n </div>\n\n {result.breakdown && result.breakdown.length > 0 && (\n <div className=\"space-y-3\">\n {result.breakdown.map((b) => {\n const pct =\n result.total > 0\n ? Math.max(2, Math.min(100, (b.value / result.total) * 100))\n : 0;\n return (\n <div key={b.label}>\n <div className=\"mb-1 flex items-baseline justify-between gap-3 text-sm\">\n <span className=\"text-white/80\">{b.label}</span>\n <b className=\"tabular-nums\">\n <AnimatedNumber\n value={Math.max(b.value, 0)}\n format={fmtBreakdown}\n />\n </b>\n </div>\n <div className=\"h-1.5 overflow-hidden rounded-full bg-white/15\">\n <span\n className=\"block h-full rounded-full transition-[width] duration-500 ease-out [background:linear-gradient(90deg,var(--mieweb-accent,var(--mieweb-primary-300)),var(--mieweb-primary-300))]\"\n style={{ width: `${pct}%` }}\n />\n </div>\n </div>\n );\n })}\n </div>\n )}\n\n {(result.math?.length || result.assumptions?.length) && (\n <div>\n <button\n type=\"button\"\n onClick={() => setShowMath((v) => !v)}\n aria-expanded={showMath}\n aria-controls={`${id}-math`}\n className=\"inline-flex items-center gap-1 text-sm font-semibold text-white/80 underline-offset-4 hover:text-white hover:underline\"\n >\n {showMath ? labels.hide : labels.show}\n {showMath ? (\n <ChevronUp size={14} aria-hidden />\n ) : (\n <ChevronDown size={14} aria-hidden />\n )}\n </button>\n {showMath && (\n <div\n id={`${id}-math`}\n className=\"mt-3 rounded-xl border border-white/15 bg-white/5 p-4 text-sm\"\n >\n {result.math?.map((row) => (\n <div\n key={row.label}\n className=\"flex justify-between gap-4 border-b border-white/10 py-1.5 last:border-0\"\n >\n <span className=\"text-white/75\">{row.label}</span>\n <b className=\"tabular-nums\">{row.value}</b>\n </div>\n ))}\n {result.assumptions && result.assumptions.length > 0 && (\n <ul className=\"mt-3 list-disc space-y-1 ps-5 text-xs text-white/70\">\n {result.assumptions.map((a) => (\n <li key={a}>{a}</li>\n ))}\n </ul>\n )}\n </div>\n )}\n </div>\n )}\n\n {actions && (\n <div className=\"mt-auto flex flex-wrap gap-3\">{actions}</div>\n )}\n {footnote && <p className=\"text-xs text-white/60\">{footnote}</p>}\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useDirection } from './chunk-
|
|
1
|
+
import { useDirection } from './chunk-JBNQ2L3K.js';
|
|
2
2
|
import { buttonVariants } from './chunk-VP3XNLUL.js';
|
|
3
3
|
import { cn } from './chunk-TQONQSJO.js';
|
|
4
4
|
import * as React from 'react';
|
|
@@ -432,5 +432,5 @@ function MegaMenuBar({
|
|
|
432
432
|
}
|
|
433
433
|
|
|
434
434
|
export { MegaMenu, MegaMenuBar, normalizePath };
|
|
435
|
-
//# sourceMappingURL=chunk-
|
|
436
|
-
//# sourceMappingURL=chunk-
|
|
435
|
+
//# sourceMappingURL=chunk-OX32ITWC.js.map
|
|
436
|
+
//# sourceMappingURL=chunk-OX32ITWC.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/MegaMenu/MegaMenu.tsx"],"names":[],"mappings":"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","file":"chunk-GLRKXJCR.js","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { ArrowRight, ChevronDown, ChevronRight } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { useDirection } from '../../hooks/useDirection';\nimport { buttonVariants } from '../Button';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type MegaMenuTone = 'primary' | 'accent' | 'neutral';\n\n/** The right-column feature panel. */\nexport interface MegaMenuFeatured {\n /** Small caps label, e.g. \"Whitepaper\". */\n eyebrow: string;\n title: string;\n description?: string;\n ctaLabel: string;\n ctaHref: string;\n /** Icon tile above the title. Ignored when `media` is given. */\n icon?: React.ReactNode;\n /** Rich media in place of the icon tile — a `VideoCard variant=\"plate\"`, an image. */\n media?: React.ReactNode;\n /** Panel colour. Default `primary`. */\n tone?: MegaMenuTone;\n}\n\nexport interface MegaMenuItem {\n label: string;\n href: string;\n description?: string;\n icon?: React.ReactNode;\n /**\n * Feature panel to show while this item is hovered/focused. Falls back to\n * the menu-level `featured` when unset — this is what makes the right\n * column contextual instead of static.\n */\n featured?: MegaMenuFeatured;\n external?: boolean;\n}\n\nexport interface MegaMenuGroup {\n label: string;\n /** Makes the group heading a link. */\n href?: string;\n items: MegaMenuItem[];\n}\n\nexport interface MegaMenuConfig {\n /** Stable id — used by `MegaMenuBar` to track the open menu. */\n key: string;\n /** Trigger label. */\n label: string;\n /** Trigger destination. Omit for a pure toggle. */\n href?: string;\n /** Heading inside the panel, e.g. \"Resources & insight\". */\n heading?: string;\n /** Flat 2-column grid of items (icon + label + description). */\n items?: MegaMenuItem[];\n /** Grouped columns of compact items. Takes precedence over `items`. */\n groups?: MegaMenuGroup[];\n /** \"Browse all …\" footer link. */\n allLabel?: string;\n allHref?: string;\n /** Footer CTA button. */\n ctaLabel?: string;\n ctaHref?: string;\n /** Default right-column feature panel. */\n featured?: MegaMenuFeatured;\n}\n\nexport interface MegaMenuProps {\n menu: MegaMenuConfig;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** Current pathname — marks the matching item/group with `aria-current`. */\n currentPath?: string;\n /** Trigger colours for light (on dark header) or dark (on light header) chrome. */\n variant?: 'light' | 'dark';\n /**\n * Override how the feature panel is chosen. Receives the hovered item (or\n * `null` when none) and the menu; return `undefined` to hide the column.\n * Default: `item?.featured ?? menu.featured`.\n */\n resolveFeatured?: (\n item: MegaMenuItem | null,\n menu: MegaMenuConfig\n ) => MegaMenuFeatured | undefined;\n /** Called after any in-panel navigation (close mobile drawers, etc.). */\n onNavigate?: () => void;\n /** Viewport width below which hover-open is disabled (touch/mobile). Default 900. */\n hoverMinWidth?: number;\n className?: string;\n}\n\nconst OPEN_DELAY_MS = 70;\nconst CLOSE_DELAY_MS = 150;\n\n/**\n * Normalize an href for `currentPath` comparison (strips hash, query and\n * trailing slashes). Shared with `SiteHeader`'s mobile drawer so desktop and\n * mobile menu links agree on `aria-current`.\n */\nexport function normalizePath(href: string): string {\n const path = href.split('#')[0].split('?')[0];\n // Trim trailing slashes with a scan: an anchored `\\/+$` is CodeQL's canonical\n // polynomial-backtracking pattern on caller-supplied hrefs full of slashes.\n let end = path.length;\n while (end > 0 && path[end - 1] === '/') end--;\n return path.slice(0, end) || '/';\n}\n\n// =============================================================================\n// MegaMenu\n// =============================================================================\n\n/**\n * A hover/click mega-menu: trigger link + chevron toggle, a panel with a\n * heading, a 2-column item grid (or grouped columns), a footer with\n * \"Browse all\" + CTA, and a right-column feature panel that **follows the\n * hovered item** (`item.featured`) before falling back to the menu default.\n * Marks the current route with `aria-current`. Ported from the Enterprise\n * Health frontdoor nav.\n *\n * Controlled — pair with `MegaMenuBar` to keep one menu open at a time.\n */\nexport function MegaMenu({\n menu,\n open,\n onOpenChange,\n currentPath,\n variant = 'dark',\n resolveFeatured = (item, m) => item?.featured ?? m.featured,\n onNavigate,\n hoverMinWidth = 900,\n className,\n}: MegaMenuProps) {\n const rootRef = React.useRef<HTMLDivElement>(null);\n const panelRef = React.useRef<HTMLDivElement>(null);\n const triggerRef = React.useRef<HTMLElement>(null);\n const openTimer = React.useRef<number | null>(null);\n const closeTimer = React.useRef<number | null>(null);\n const [left, setLeft] = React.useState<number | undefined>();\n const [hovered, setHovered] = React.useState<MegaMenuItem | null>(null);\n const panelId = React.useId();\n\n const isHoverViewport = () =>\n typeof window !== 'undefined' && window.innerWidth >= hoverMinWidth;\n\n const clearTimers = React.useCallback(() => {\n if (openTimer.current !== null) window.clearTimeout(openTimer.current);\n if (closeTimer.current !== null) window.clearTimeout(closeTimer.current);\n openTimer.current = closeTimer.current = null;\n }, []);\n\n const requestOpen = React.useCallback(() => {\n clearTimers();\n openTimer.current = window.setTimeout(\n () => onOpenChange(true),\n OPEN_DELAY_MS\n );\n }, [clearTimers, onOpenChange]);\n\n const requestClose = React.useCallback(() => {\n clearTimers();\n closeTimer.current = window.setTimeout(\n () => onOpenChange(false),\n CLOSE_DELAY_MS\n );\n }, [clearTimers, onOpenChange]);\n\n // Clamp the panel inside the viewport (it's absolutely positioned under the\n // trigger). Anchoring is logical: the panel's inline-start edge aligns with\n // the trigger's — left edge in LTR, right edge in RTL — before clamping.\n // `useDirection` is reactive, so an open panel re-clamps when `dir` changes.\n const direction = useDirection(rootRef);\n const position = React.useCallback(() => {\n const root = rootRef.current;\n const panel = panelRef.current;\n if (!root || !panel || !isHoverViewport()) {\n setLeft(undefined);\n return;\n }\n const rect = root.getBoundingClientRect();\n const pad = 16;\n const vw = document.documentElement.clientWidth;\n const desired =\n direction === 'rtl' ? rect.right - panel.offsetWidth : rect.left;\n const clamped = Math.min(\n Math.max(desired, pad),\n Math.max(pad, vw - pad - panel.offsetWidth)\n );\n setLeft(clamped - rect.left);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [hoverMinWidth, direction]);\n\n const curPath = currentPath ? normalizePath(currentPath) : null;\n const isCurrent = (href: string) =>\n curPath !== null && normalizePath(href) === curPath;\n const featured = resolveFeatured(hovered, menu);\n\n React.useEffect(() => {\n if (open) position();\n else setHovered(null);\n // `featured` is a dep because the feature column swaps the 600px layout\n // for the 880px one after open — the wider panel must be re-clamped or a\n // menu opened near the viewport edge overflows it.\n }, [open, position, featured]);\n\n React.useEffect(() => {\n window.addEventListener('resize', position);\n return () => window.removeEventListener('resize', position);\n }, [position]);\n\n React.useEffect(() => clearTimers, [clearTimers]);\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'Escape' && open) {\n e.stopPropagation();\n clearTimers();\n onOpenChange(false);\n triggerRef.current?.focus();\n }\n };\n\n const triggerClass = cn(\n 'inline-flex items-center rounded-lg px-3 py-2 text-sm font-medium transition-colors',\n variant === 'light'\n ? 'text-white/90 hover:bg-white/10 hover:text-white'\n : 'text-foreground/80 hover:bg-muted hover:text-foreground',\n open &&\n (variant === 'light'\n ? 'bg-white/10 text-white'\n : 'bg-muted text-foreground')\n );\n\n const navigate = () => {\n onOpenChange(false);\n onNavigate?.();\n };\n\n return (\n // Hover/focus delegation region only — the trigger, toggle and links inside are the interactive elements.\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <div\n ref={rootRef}\n data-slot=\"mega-menu\"\n data-state={open ? 'open' : 'closed'}\n className={cn('relative', className)}\n onMouseEnter={() => isHoverViewport() && requestOpen()}\n onMouseLeave={() => isHoverViewport() && requestClose()}\n onFocusCapture={() => {\n if (!isHoverViewport()) return;\n clearTimers();\n onOpenChange(true);\n }}\n onBlurCapture={(e) => {\n if (!isHoverViewport()) return;\n if (!rootRef.current?.contains(e.relatedTarget as Node | null))\n requestClose();\n }}\n onKeyDown={onKeyDown}\n >\n <div className=\"flex items-center\">\n {menu.href ? (\n <a\n ref={triggerRef as React.RefObject<HTMLAnchorElement>}\n href={menu.href}\n className={triggerClass}\n aria-haspopup=\"true\"\n aria-expanded={open}\n aria-controls={panelId}\n aria-current={isCurrent(menu.href) ? 'page' : undefined}\n onClick={navigate}\n >\n {menu.label}\n </a>\n ) : (\n <button\n ref={triggerRef as React.RefObject<HTMLButtonElement>}\n type=\"button\"\n className={triggerClass}\n aria-haspopup=\"true\"\n aria-expanded={open}\n aria-controls={panelId}\n onClick={() => {\n clearTimers();\n onOpenChange(!open);\n }}\n >\n {menu.label}\n </button>\n )}\n <button\n type=\"button\"\n aria-label={`Toggle ${menu.label} menu`}\n aria-expanded={open}\n aria-controls={panelId}\n onClick={() => {\n clearTimers();\n onOpenChange(!open);\n }}\n className={cn(\n '-ms-1 rounded-md p-1 transition-transform',\n variant === 'light'\n ? 'text-white/70 hover:text-white'\n : 'text-muted-foreground hover:text-foreground',\n open && 'rotate-180'\n )}\n >\n <ChevronDown size={16} aria-hidden=\"true\" />\n </button>\n </div>\n\n <div\n id={panelId}\n ref={panelRef}\n role=\"region\"\n aria-label={menu.label}\n data-slot=\"mega-menu-panel\"\n // rtl-ignore -- viewport-clamp coordinate; math above is direction-aware\n style={{ left }}\n className={cn(\n 'border-border bg-card text-card-foreground absolute top-full z-50 mt-3 origin-top-left rounded-2xl border shadow-xl rtl:origin-top-right',\n 'transition-[opacity,transform] duration-200',\n open\n ? 'visible translate-y-0 opacity-100'\n : 'pointer-events-none invisible -translate-y-1 opacity-0',\n featured\n ? 'grid w-[min(880px,calc(100vw-2rem))] grid-cols-[1fr_280px]'\n : 'w-[min(600px,calc(100vw-2rem))]'\n )}\n >\n <div className=\"p-6\">\n {menu.heading && (\n <p className=\"text-muted-foreground mb-4 text-[11px] font-bold tracking-[0.14em] uppercase\">\n {menu.heading}\n </p>\n )}\n\n {menu.groups ? (\n <div className=\"grid gap-6 sm:grid-cols-2 lg:grid-cols-3\">\n {menu.groups.map((g) => (\n <div key={g.label}>\n {g.href ? (\n <a\n href={g.href}\n aria-current={isCurrent(g.href) ? 'page' : undefined}\n onClick={navigate}\n className=\"text-foreground hover:text-primary-700 dark:hover:text-primary-300 mb-2 inline-flex items-center gap-1 text-sm font-semibold\"\n >\n {g.label}\n <ChevronRight\n size={14}\n aria-hidden=\"true\"\n className=\"rtl:-scale-x-100\"\n />\n </a>\n ) : (\n <p className=\"text-foreground mb-2 text-sm font-semibold\">\n {g.label}\n </p>\n )}\n <ul className=\"space-y-0.5\">\n {g.items.map((it) => (\n <li key={it.href}>\n <ItemLink\n item={it}\n compact\n current={isCurrent(it.href)}\n onHover={setHovered}\n onNavigate={navigate}\n />\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n ) : (\n <div className=\"grid gap-1 sm:grid-cols-2\">\n {menu.items?.map((it) => (\n <ItemLink\n key={it.href}\n item={it}\n current={isCurrent(it.href)}\n onHover={setHovered}\n onNavigate={navigate}\n />\n ))}\n </div>\n )}\n\n {(menu.allHref || menu.ctaHref) && (\n <div className=\"border-border mt-5 flex items-center justify-between gap-4 border-t pt-4\">\n {menu.allHref ? (\n <a\n href={menu.allHref}\n onClick={navigate}\n className=\"text-foreground hover:text-primary-700 dark:hover:text-primary-300 inline-flex items-center gap-1.5 text-sm font-semibold\"\n >\n {menu.allLabel ?? 'Browse all'}\n <ArrowRight\n size={16}\n aria-hidden=\"true\"\n className=\"rtl:-scale-x-100\"\n />\n </a>\n ) : (\n <span />\n )}\n {menu.ctaHref && (\n <a\n href={menu.ctaHref}\n onClick={navigate}\n className={buttonVariants({ size: 'sm', effect: 'sheen' })}\n >\n {menu.ctaLabel ?? 'Get started'}\n </a>\n )}\n </div>\n )}\n </div>\n\n {featured && (\n <FeaturedPanel featured={featured} onNavigate={navigate} />\n )}\n </div>\n </div>\n );\n}\n\n// =============================================================================\n// Pieces\n// =============================================================================\n\nfunction ItemLink({\n item,\n compact,\n current,\n onHover,\n onNavigate,\n}: {\n item: MegaMenuItem;\n compact?: boolean;\n current: boolean;\n onHover: (item: MegaMenuItem | null) => void;\n onNavigate: () => void;\n}) {\n return (\n <a\n href={item.href}\n target={item.external ? '_blank' : undefined}\n rel={item.external ? 'noopener noreferrer' : undefined}\n aria-current={current ? 'page' : undefined}\n data-slot=\"mega-menu-item\"\n onClick={onNavigate}\n onMouseEnter={() => onHover(item)}\n onFocus={() => onHover(item)}\n className={cn(\n 'group flex items-start gap-3 rounded-xl text-start transition-colors',\n compact ? 'px-2 py-1.5' : 'p-3',\n 'hover:bg-primary-500/10 focus-visible:bg-primary-500/10 focus-visible:outline-none',\n current && 'bg-primary-500/10'\n )}\n >\n {item.icon && (\n <span\n className={cn(\n 'inline-flex shrink-0 items-center justify-center rounded-lg transition-colors',\n compact\n ? 'h-7 w-7 [&_svg]:h-4 [&_svg]:w-4'\n : 'h-10 w-10 [&_svg]:h-5 [&_svg]:w-5',\n 'bg-muted text-foreground/70 group-hover:bg-primary-800 group-hover:text-white',\n current && 'bg-primary-800 text-white'\n )}\n >\n {item.icon}\n </span>\n )}\n <span className=\"min-w-0\">\n <span\n className={cn(\n 'text-foreground group-hover:text-primary-800 dark:group-hover:text-primary-200 block font-semibold',\n compact ? 'text-sm' : 'text-base'\n )}\n >\n {item.label}\n </span>\n {!compact && item.description && (\n <span className=\"text-muted-foreground mt-0.5 block text-sm leading-snug\">\n {item.description}\n </span>\n )}\n </span>\n </a>\n );\n}\n\nconst TONE: Record<MegaMenuTone, string> = {\n primary: 'bg-gradient-to-br from-primary-800 to-primary-950 text-white',\n accent:\n 'text-white [background:linear-gradient(160deg,color-mix(in_srgb,var(--mieweb-accent,var(--mieweb-primary-700))_70%,#000)_0%,var(--mieweb-primary-950)_100%)]',\n neutral: 'bg-muted text-foreground',\n};\n\nfunction FeaturedPanel({\n featured,\n onNavigate,\n}: {\n featured: MegaMenuFeatured;\n onNavigate: () => void;\n}) {\n const tone = featured.tone ?? 'primary';\n const onDark = tone !== 'neutral';\n // `key` re-mounts the panel so swapping between items replays the fade-in.\n // A `div`, not `aside`: a complementary landmark nested inside the menu\n // region violates axe landmark-complementary-is-top-level.\n return (\n <div\n data-slot=\"mega-menu-featured\"\n key={featured.title}\n className={cn(\n 'flex flex-col rounded-e-2xl p-6 motion-safe:animate-[mie-fade-in_0.2s_ease-out]',\n TONE[tone]\n )}\n >\n <p\n className={cn(\n 'text-[11px] font-bold tracking-[0.14em] uppercase',\n onDark ? 'text-white/70' : 'text-muted-foreground'\n )}\n >\n {featured.eyebrow}\n </p>\n <div className=\"mt-4\">\n {featured.media ??\n (featured.icon && (\n <span\n className={cn(\n 'inline-flex h-14 w-14 items-center justify-center rounded-xl [&_svg]:h-7 [&_svg]:w-7',\n onDark ? 'bg-white/15 text-white' : 'bg-card text-foreground'\n )}\n >\n {featured.icon}\n </span>\n ))}\n </div>\n <p className=\"mt-4 text-xl leading-tight font-semibold\">\n {featured.title}\n </p>\n {featured.description && (\n <p\n className={cn(\n 'mt-2 text-sm leading-snug',\n onDark ? 'text-white/80' : 'text-muted-foreground'\n )}\n >\n {featured.description}\n </p>\n )}\n <div className=\"mt-auto pt-5\">\n <a\n href={featured.ctaHref}\n onClick={onNavigate}\n className={cn(\n buttonVariants({ variant: 'outline', effect: 'sheen' }),\n onDark &&\n 'border-white/40 text-white hover:border-white hover:bg-white/10 hover:text-white dark:border-white/40 dark:text-white dark:hover:border-white dark:hover:bg-white/10'\n )}\n >\n {featured.ctaLabel}\n <ArrowRight\n size={16}\n aria-hidden=\"true\"\n className=\"rtl:-scale-x-100\"\n />\n </a>\n </div>\n </div>\n );\n}\n\n// =============================================================================\n// MegaMenuBar — keeps one menu open at a time\n// =============================================================================\n\nexport interface MegaMenuBarProps extends Pick<\n MegaMenuProps,\n 'currentPath' | 'variant' | 'resolveFeatured' | 'onNavigate' | 'hoverMinWidth'\n> {\n menus: MegaMenuConfig[];\n className?: string;\n 'aria-label'?: string;\n}\n\n/** A row of `MegaMenu` triggers sharing one open-state so only one panel shows. */\nexport function MegaMenuBar({\n menus,\n className,\n 'aria-label': ariaLabel = 'Main navigation',\n ...rest\n}: MegaMenuBarProps) {\n const [openKey, setOpenKey] = React.useState<string | null>(null);\n return (\n <nav\n data-slot=\"mega-menu-bar\"\n aria-label={ariaLabel}\n className={cn('flex items-center gap-1', className)}\n >\n {menus.map((m) => (\n <MegaMenu\n key={m.key}\n menu={m}\n open={openKey === m.key}\n onOpenChange={(o) =>\n setOpenKey(o ? m.key : openKey === m.key ? null : openKey)\n }\n {...rest}\n />\n ))}\n </nav>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/MegaMenu/MegaMenu.tsx"],"names":[],"mappings":"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","file":"chunk-OX32ITWC.js","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { ArrowRight, ChevronDown, ChevronRight } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { useDirection } from '../../hooks/useDirection';\nimport { buttonVariants } from '../Button';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type MegaMenuTone = 'primary' | 'accent' | 'neutral';\n\n/** The right-column feature panel. */\nexport interface MegaMenuFeatured {\n /** Small caps label, e.g. \"Whitepaper\". */\n eyebrow: string;\n title: string;\n description?: string;\n ctaLabel: string;\n ctaHref: string;\n /** Icon tile above the title. Ignored when `media` is given. */\n icon?: React.ReactNode;\n /** Rich media in place of the icon tile — a `VideoCard variant=\"plate\"`, an image. */\n media?: React.ReactNode;\n /** Panel colour. Default `primary`. */\n tone?: MegaMenuTone;\n}\n\nexport interface MegaMenuItem {\n label: string;\n href: string;\n description?: string;\n icon?: React.ReactNode;\n /**\n * Feature panel to show while this item is hovered/focused. Falls back to\n * the menu-level `featured` when unset — this is what makes the right\n * column contextual instead of static.\n */\n featured?: MegaMenuFeatured;\n external?: boolean;\n}\n\nexport interface MegaMenuGroup {\n label: string;\n /** Makes the group heading a link. */\n href?: string;\n items: MegaMenuItem[];\n}\n\nexport interface MegaMenuConfig {\n /** Stable id — used by `MegaMenuBar` to track the open menu. */\n key: string;\n /** Trigger label. */\n label: string;\n /** Trigger destination. Omit for a pure toggle. */\n href?: string;\n /** Heading inside the panel, e.g. \"Resources & insight\". */\n heading?: string;\n /** Flat 2-column grid of items (icon + label + description). */\n items?: MegaMenuItem[];\n /** Grouped columns of compact items. Takes precedence over `items`. */\n groups?: MegaMenuGroup[];\n /** \"Browse all …\" footer link. */\n allLabel?: string;\n allHref?: string;\n /** Footer CTA button. */\n ctaLabel?: string;\n ctaHref?: string;\n /** Default right-column feature panel. */\n featured?: MegaMenuFeatured;\n}\n\nexport interface MegaMenuProps {\n menu: MegaMenuConfig;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** Current pathname — marks the matching item/group with `aria-current`. */\n currentPath?: string;\n /** Trigger colours for light (on dark header) or dark (on light header) chrome. */\n variant?: 'light' | 'dark';\n /**\n * Override how the feature panel is chosen. Receives the hovered item (or\n * `null` when none) and the menu; return `undefined` to hide the column.\n * Default: `item?.featured ?? menu.featured`.\n */\n resolveFeatured?: (\n item: MegaMenuItem | null,\n menu: MegaMenuConfig\n ) => MegaMenuFeatured | undefined;\n /** Called after any in-panel navigation (close mobile drawers, etc.). */\n onNavigate?: () => void;\n /** Viewport width below which hover-open is disabled (touch/mobile). Default 900. */\n hoverMinWidth?: number;\n className?: string;\n}\n\nconst OPEN_DELAY_MS = 70;\nconst CLOSE_DELAY_MS = 150;\n\n/**\n * Normalize an href for `currentPath` comparison (strips hash, query and\n * trailing slashes). Shared with `SiteHeader`'s mobile drawer so desktop and\n * mobile menu links agree on `aria-current`.\n */\nexport function normalizePath(href: string): string {\n const path = href.split('#')[0].split('?')[0];\n // Trim trailing slashes with a scan: an anchored `\\/+$` is CodeQL's canonical\n // polynomial-backtracking pattern on caller-supplied hrefs full of slashes.\n let end = path.length;\n while (end > 0 && path[end - 1] === '/') end--;\n return path.slice(0, end) || '/';\n}\n\n// =============================================================================\n// MegaMenu\n// =============================================================================\n\n/**\n * A hover/click mega-menu: trigger link + chevron toggle, a panel with a\n * heading, a 2-column item grid (or grouped columns), a footer with\n * \"Browse all\" + CTA, and a right-column feature panel that **follows the\n * hovered item** (`item.featured`) before falling back to the menu default.\n * Marks the current route with `aria-current`. Ported from the Enterprise\n * Health frontdoor nav.\n *\n * Controlled — pair with `MegaMenuBar` to keep one menu open at a time.\n */\nexport function MegaMenu({\n menu,\n open,\n onOpenChange,\n currentPath,\n variant = 'dark',\n resolveFeatured = (item, m) => item?.featured ?? m.featured,\n onNavigate,\n hoverMinWidth = 900,\n className,\n}: MegaMenuProps) {\n const rootRef = React.useRef<HTMLDivElement>(null);\n const panelRef = React.useRef<HTMLDivElement>(null);\n const triggerRef = React.useRef<HTMLElement>(null);\n const openTimer = React.useRef<number | null>(null);\n const closeTimer = React.useRef<number | null>(null);\n const [left, setLeft] = React.useState<number | undefined>();\n const [hovered, setHovered] = React.useState<MegaMenuItem | null>(null);\n const panelId = React.useId();\n\n const isHoverViewport = () =>\n typeof window !== 'undefined' && window.innerWidth >= hoverMinWidth;\n\n const clearTimers = React.useCallback(() => {\n if (openTimer.current !== null) window.clearTimeout(openTimer.current);\n if (closeTimer.current !== null) window.clearTimeout(closeTimer.current);\n openTimer.current = closeTimer.current = null;\n }, []);\n\n const requestOpen = React.useCallback(() => {\n clearTimers();\n openTimer.current = window.setTimeout(\n () => onOpenChange(true),\n OPEN_DELAY_MS\n );\n }, [clearTimers, onOpenChange]);\n\n const requestClose = React.useCallback(() => {\n clearTimers();\n closeTimer.current = window.setTimeout(\n () => onOpenChange(false),\n CLOSE_DELAY_MS\n );\n }, [clearTimers, onOpenChange]);\n\n // Clamp the panel inside the viewport (it's absolutely positioned under the\n // trigger). Anchoring is logical: the panel's inline-start edge aligns with\n // the trigger's — left edge in LTR, right edge in RTL — before clamping.\n // `useDirection` is reactive, so an open panel re-clamps when `dir` changes.\n const direction = useDirection(rootRef);\n const position = React.useCallback(() => {\n const root = rootRef.current;\n const panel = panelRef.current;\n if (!root || !panel || !isHoverViewport()) {\n setLeft(undefined);\n return;\n }\n const rect = root.getBoundingClientRect();\n const pad = 16;\n const vw = document.documentElement.clientWidth;\n const desired =\n direction === 'rtl' ? rect.right - panel.offsetWidth : rect.left;\n const clamped = Math.min(\n Math.max(desired, pad),\n Math.max(pad, vw - pad - panel.offsetWidth)\n );\n setLeft(clamped - rect.left);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [hoverMinWidth, direction]);\n\n const curPath = currentPath ? normalizePath(currentPath) : null;\n const isCurrent = (href: string) =>\n curPath !== null && normalizePath(href) === curPath;\n const featured = resolveFeatured(hovered, menu);\n\n React.useEffect(() => {\n if (open) position();\n else setHovered(null);\n // `featured` is a dep because the feature column swaps the 600px layout\n // for the 880px one after open — the wider panel must be re-clamped or a\n // menu opened near the viewport edge overflows it.\n }, [open, position, featured]);\n\n React.useEffect(() => {\n window.addEventListener('resize', position);\n return () => window.removeEventListener('resize', position);\n }, [position]);\n\n React.useEffect(() => clearTimers, [clearTimers]);\n\n const onKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'Escape' && open) {\n e.stopPropagation();\n clearTimers();\n onOpenChange(false);\n triggerRef.current?.focus();\n }\n };\n\n const triggerClass = cn(\n 'inline-flex items-center rounded-lg px-3 py-2 text-sm font-medium transition-colors',\n variant === 'light'\n ? 'text-white/90 hover:bg-white/10 hover:text-white'\n : 'text-foreground/80 hover:bg-muted hover:text-foreground',\n open &&\n (variant === 'light'\n ? 'bg-white/10 text-white'\n : 'bg-muted text-foreground')\n );\n\n const navigate = () => {\n onOpenChange(false);\n onNavigate?.();\n };\n\n return (\n // Hover/focus delegation region only — the trigger, toggle and links inside are the interactive elements.\n // eslint-disable-next-line jsx-a11y/no-static-element-interactions\n <div\n ref={rootRef}\n data-slot=\"mega-menu\"\n data-state={open ? 'open' : 'closed'}\n className={cn('relative', className)}\n onMouseEnter={() => isHoverViewport() && requestOpen()}\n onMouseLeave={() => isHoverViewport() && requestClose()}\n onFocusCapture={() => {\n if (!isHoverViewport()) return;\n clearTimers();\n onOpenChange(true);\n }}\n onBlurCapture={(e) => {\n if (!isHoverViewport()) return;\n if (!rootRef.current?.contains(e.relatedTarget as Node | null))\n requestClose();\n }}\n onKeyDown={onKeyDown}\n >\n <div className=\"flex items-center\">\n {menu.href ? (\n <a\n ref={triggerRef as React.RefObject<HTMLAnchorElement>}\n href={menu.href}\n className={triggerClass}\n aria-haspopup=\"true\"\n aria-expanded={open}\n aria-controls={panelId}\n aria-current={isCurrent(menu.href) ? 'page' : undefined}\n onClick={navigate}\n >\n {menu.label}\n </a>\n ) : (\n <button\n ref={triggerRef as React.RefObject<HTMLButtonElement>}\n type=\"button\"\n className={triggerClass}\n aria-haspopup=\"true\"\n aria-expanded={open}\n aria-controls={panelId}\n onClick={() => {\n clearTimers();\n onOpenChange(!open);\n }}\n >\n {menu.label}\n </button>\n )}\n <button\n type=\"button\"\n aria-label={`Toggle ${menu.label} menu`}\n aria-expanded={open}\n aria-controls={panelId}\n onClick={() => {\n clearTimers();\n onOpenChange(!open);\n }}\n className={cn(\n '-ms-1 rounded-md p-1 transition-transform',\n variant === 'light'\n ? 'text-white/70 hover:text-white'\n : 'text-muted-foreground hover:text-foreground',\n open && 'rotate-180'\n )}\n >\n <ChevronDown size={16} aria-hidden=\"true\" />\n </button>\n </div>\n\n <div\n id={panelId}\n ref={panelRef}\n role=\"region\"\n aria-label={menu.label}\n data-slot=\"mega-menu-panel\"\n // rtl-ignore -- viewport-clamp coordinate; math above is direction-aware\n style={{ left }}\n className={cn(\n 'border-border bg-card text-card-foreground absolute top-full z-50 mt-3 origin-top-left rounded-2xl border shadow-xl rtl:origin-top-right',\n 'transition-[opacity,transform] duration-200',\n open\n ? 'visible translate-y-0 opacity-100'\n : 'pointer-events-none invisible -translate-y-1 opacity-0',\n featured\n ? 'grid w-[min(880px,calc(100vw-2rem))] grid-cols-[1fr_280px]'\n : 'w-[min(600px,calc(100vw-2rem))]'\n )}\n >\n <div className=\"p-6\">\n {menu.heading && (\n <p className=\"text-muted-foreground mb-4 text-[11px] font-bold tracking-[0.14em] uppercase\">\n {menu.heading}\n </p>\n )}\n\n {menu.groups ? (\n <div className=\"grid gap-6 sm:grid-cols-2 lg:grid-cols-3\">\n {menu.groups.map((g) => (\n <div key={g.label}>\n {g.href ? (\n <a\n href={g.href}\n aria-current={isCurrent(g.href) ? 'page' : undefined}\n onClick={navigate}\n className=\"text-foreground hover:text-primary-700 dark:hover:text-primary-300 mb-2 inline-flex items-center gap-1 text-sm font-semibold\"\n >\n {g.label}\n <ChevronRight\n size={14}\n aria-hidden=\"true\"\n className=\"rtl:-scale-x-100\"\n />\n </a>\n ) : (\n <p className=\"text-foreground mb-2 text-sm font-semibold\">\n {g.label}\n </p>\n )}\n <ul className=\"space-y-0.5\">\n {g.items.map((it) => (\n <li key={it.href}>\n <ItemLink\n item={it}\n compact\n current={isCurrent(it.href)}\n onHover={setHovered}\n onNavigate={navigate}\n />\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n ) : (\n <div className=\"grid gap-1 sm:grid-cols-2\">\n {menu.items?.map((it) => (\n <ItemLink\n key={it.href}\n item={it}\n current={isCurrent(it.href)}\n onHover={setHovered}\n onNavigate={navigate}\n />\n ))}\n </div>\n )}\n\n {(menu.allHref || menu.ctaHref) && (\n <div className=\"border-border mt-5 flex items-center justify-between gap-4 border-t pt-4\">\n {menu.allHref ? (\n <a\n href={menu.allHref}\n onClick={navigate}\n className=\"text-foreground hover:text-primary-700 dark:hover:text-primary-300 inline-flex items-center gap-1.5 text-sm font-semibold\"\n >\n {menu.allLabel ?? 'Browse all'}\n <ArrowRight\n size={16}\n aria-hidden=\"true\"\n className=\"rtl:-scale-x-100\"\n />\n </a>\n ) : (\n <span />\n )}\n {menu.ctaHref && (\n <a\n href={menu.ctaHref}\n onClick={navigate}\n className={buttonVariants({ size: 'sm', effect: 'sheen' })}\n >\n {menu.ctaLabel ?? 'Get started'}\n </a>\n )}\n </div>\n )}\n </div>\n\n {featured && (\n <FeaturedPanel featured={featured} onNavigate={navigate} />\n )}\n </div>\n </div>\n );\n}\n\n// =============================================================================\n// Pieces\n// =============================================================================\n\nfunction ItemLink({\n item,\n compact,\n current,\n onHover,\n onNavigate,\n}: {\n item: MegaMenuItem;\n compact?: boolean;\n current: boolean;\n onHover: (item: MegaMenuItem | null) => void;\n onNavigate: () => void;\n}) {\n return (\n <a\n href={item.href}\n target={item.external ? '_blank' : undefined}\n rel={item.external ? 'noopener noreferrer' : undefined}\n aria-current={current ? 'page' : undefined}\n data-slot=\"mega-menu-item\"\n onClick={onNavigate}\n onMouseEnter={() => onHover(item)}\n onFocus={() => onHover(item)}\n className={cn(\n 'group flex items-start gap-3 rounded-xl text-start transition-colors',\n compact ? 'px-2 py-1.5' : 'p-3',\n 'hover:bg-primary-500/10 focus-visible:bg-primary-500/10 focus-visible:outline-none',\n current && 'bg-primary-500/10'\n )}\n >\n {item.icon && (\n <span\n className={cn(\n 'inline-flex shrink-0 items-center justify-center rounded-lg transition-colors',\n compact\n ? 'h-7 w-7 [&_svg]:h-4 [&_svg]:w-4'\n : 'h-10 w-10 [&_svg]:h-5 [&_svg]:w-5',\n 'bg-muted text-foreground/70 group-hover:bg-primary-800 group-hover:text-white',\n current && 'bg-primary-800 text-white'\n )}\n >\n {item.icon}\n </span>\n )}\n <span className=\"min-w-0\">\n <span\n className={cn(\n 'text-foreground group-hover:text-primary-800 dark:group-hover:text-primary-200 block font-semibold',\n compact ? 'text-sm' : 'text-base'\n )}\n >\n {item.label}\n </span>\n {!compact && item.description && (\n <span className=\"text-muted-foreground mt-0.5 block text-sm leading-snug\">\n {item.description}\n </span>\n )}\n </span>\n </a>\n );\n}\n\nconst TONE: Record<MegaMenuTone, string> = {\n primary: 'bg-gradient-to-br from-primary-800 to-primary-950 text-white',\n accent:\n 'text-white [background:linear-gradient(160deg,color-mix(in_srgb,var(--mieweb-accent,var(--mieweb-primary-700))_70%,#000)_0%,var(--mieweb-primary-950)_100%)]',\n neutral: 'bg-muted text-foreground',\n};\n\nfunction FeaturedPanel({\n featured,\n onNavigate,\n}: {\n featured: MegaMenuFeatured;\n onNavigate: () => void;\n}) {\n const tone = featured.tone ?? 'primary';\n const onDark = tone !== 'neutral';\n // `key` re-mounts the panel so swapping between items replays the fade-in.\n // A `div`, not `aside`: a complementary landmark nested inside the menu\n // region violates axe landmark-complementary-is-top-level.\n return (\n <div\n data-slot=\"mega-menu-featured\"\n key={featured.title}\n className={cn(\n 'flex flex-col rounded-e-2xl p-6 motion-safe:animate-[mie-fade-in_0.2s_ease-out]',\n TONE[tone]\n )}\n >\n <p\n className={cn(\n 'text-[11px] font-bold tracking-[0.14em] uppercase',\n onDark ? 'text-white/70' : 'text-muted-foreground'\n )}\n >\n {featured.eyebrow}\n </p>\n <div className=\"mt-4\">\n {featured.media ??\n (featured.icon && (\n <span\n className={cn(\n 'inline-flex h-14 w-14 items-center justify-center rounded-xl [&_svg]:h-7 [&_svg]:w-7',\n onDark ? 'bg-white/15 text-white' : 'bg-card text-foreground'\n )}\n >\n {featured.icon}\n </span>\n ))}\n </div>\n <p className=\"mt-4 text-xl leading-tight font-semibold\">\n {featured.title}\n </p>\n {featured.description && (\n <p\n className={cn(\n 'mt-2 text-sm leading-snug',\n onDark ? 'text-white/80' : 'text-muted-foreground'\n )}\n >\n {featured.description}\n </p>\n )}\n <div className=\"mt-auto pt-5\">\n <a\n href={featured.ctaHref}\n onClick={onNavigate}\n className={cn(\n buttonVariants({ variant: 'outline', effect: 'sheen' }),\n onDark &&\n 'border-white/40 text-white hover:border-white hover:bg-white/10 hover:text-white dark:border-white/40 dark:text-white dark:hover:border-white dark:hover:bg-white/10'\n )}\n >\n {featured.ctaLabel}\n <ArrowRight\n size={16}\n aria-hidden=\"true\"\n className=\"rtl:-scale-x-100\"\n />\n </a>\n </div>\n </div>\n );\n}\n\n// =============================================================================\n// MegaMenuBar — keeps one menu open at a time\n// =============================================================================\n\nexport interface MegaMenuBarProps extends Pick<\n MegaMenuProps,\n 'currentPath' | 'variant' | 'resolveFeatured' | 'onNavigate' | 'hoverMinWidth'\n> {\n menus: MegaMenuConfig[];\n className?: string;\n 'aria-label'?: string;\n}\n\n/** A row of `MegaMenu` triggers sharing one open-state so only one panel shows. */\nexport function MegaMenuBar({\n menus,\n className,\n 'aria-label': ariaLabel = 'Main navigation',\n ...rest\n}: MegaMenuBarProps) {\n const [openKey, setOpenKey] = React.useState<string | null>(null);\n return (\n <nav\n data-slot=\"mega-menu-bar\"\n aria-label={ariaLabel}\n className={cn('flex items-center gap-1', className)}\n >\n {menus.map((m) => (\n <MegaMenu\n key={m.key}\n menu={m}\n open={openKey === m.key}\n onOpenChange={(o) =>\n setOpenKey(o ? m.key : openKey === m.key ? null : openKey)\n }\n {...rest}\n />\n ))}\n </nav>\n );\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunkQ3YVLO52_cjs = require('./chunk-Q3YVLO52.cjs');
|
|
4
|
-
var
|
|
4
|
+
var chunk7QNBPB7F_cjs = require('./chunk-7QNBPB7F.cjs');
|
|
5
5
|
var chunkS5RVSXDV_cjs = require('./chunk-S5RVSXDV.cjs');
|
|
6
6
|
var React2 = require('react');
|
|
7
7
|
var reactDom = require('react-dom');
|
|
@@ -65,7 +65,7 @@ function peerLabels(peers) {
|
|
|
65
65
|
var PANEL_OFFSET = 6;
|
|
66
66
|
var VIEWPORT_PADDING = 8;
|
|
67
67
|
function useAnchoredPanel(open, anchorRef, panelRef) {
|
|
68
|
-
const direction =
|
|
68
|
+
const direction = chunk7QNBPB7F_cjs.useDirection(anchorRef);
|
|
69
69
|
const [pos, setPos] = React2__namespace.useState(
|
|
70
70
|
null
|
|
71
71
|
);
|
|
@@ -514,5 +514,5 @@ function useYjsCollabStatus({
|
|
|
514
514
|
exports.CollabStatus = CollabStatus;
|
|
515
515
|
exports.defaultCollabStatusLabels = defaultCollabStatusLabels;
|
|
516
516
|
exports.useYjsCollabStatus = useYjsCollabStatus;
|
|
517
|
-
//# sourceMappingURL=chunk-
|
|
518
|
-
//# sourceMappingURL=chunk-
|
|
517
|
+
//# sourceMappingURL=chunk-PJ4XEBMU.cjs.map
|
|
518
|
+
//# sourceMappingURL=chunk-PJ4XEBMU.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/CollabStatus/CollabStatus.tsx","../src/components/CollabStatus/useYjsCollabStatus.ts"],"names":["useDirection","React","jsxs","cn","jsx","createPortal","WrapText","X","Fragment","AvatarGroup","React2"],"mappings":"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","file":"chunk-L4APW65W.cjs","sourcesContent":["import * as React from 'react';\nimport { createPortal } from 'react-dom';\nimport { WrapText, X } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { useDirection } from '../../hooks/useDirection';\nimport { AvatarGroup, type AvatarPresence } from '../AvatarGroup/AvatarGroup';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Another participant currently present in the room. */\nexport interface CollabPeer {\n /** Display name published through presence. */\n name: string;\n /** Optional presence color (cursor/avatar tint). */\n color?: string;\n /**\n * What the peer is doing. Peers without a mode count as editing; `viewing`\n * peers are left out of the \"… are editing\" summary.\n */\n mode?: AvatarPresence;\n /** Avatar image URL. */\n avatarUrl?: string;\n}\n\n/** Static identity of the open collaboration room, shown in the debug panel. */\nexport interface CollabRoomInfo {\n /** Room name on the sync server (e.g. `case/4`). */\n name: string;\n /** Transport URL the client connected to. */\n url?: string;\n /** This window's client id (stable per document), or null before connect. */\n clientId?: number | null;\n /** The acting application user id passed to the sync server. */\n userId?: string;\n}\n\n/** Category of a collaboration event in the debug log. */\nexport type CollabLogKind = 'doc' | 'awareness' | 'sync' | 'patch';\n\n/** A single entry in the collaboration debug log. */\nexport interface CollabLogEntry {\n /** Stable key for rendering. */\n id: number | string;\n /** Wall-clock time of the event (epoch ms). */\n at: number;\n /** Event category. */\n kind: CollabLogKind;\n /** Whether this window or a peer originated it. */\n origin?: 'local' | 'remote';\n /** Human-readable detail line. */\n detail: string;\n}\n\n/** Every user-facing string, so apps can translate the widget. */\nexport interface CollabStatusLabels {\n /** Trigger text once the initial sync completed. */\n live: string;\n /** Trigger text before the initial sync completes. */\n connecting: string;\n /** Summary of who else is editing, e.g. `Ann, Bo are editing`. */\n editing: (names: string[]) => string;\n /** Accessible name / tooltip of the trigger button. */\n triggerLabel: string;\n /** Heading of the room-occupants section. */\n peersTitle: (count: number) => string;\n /** Shown in the occupants section when nobody else is in the room. */\n alone: React.ReactNode;\n /** Accessible name of an occupant with a `mode`, e.g. `Ann is viewing`. */\n presence?: (name: string, mode: AvatarPresence) => string;\n /** Heading of the debug panel. */\n logTitle: (count: number) => string;\n /** Accessible name of the panel close button. */\n close: string;\n /** Accessible name of the toggle that unclips long values. */\n wrap: string;\n /** Shown when the log is empty. */\n empty: React.ReactNode;\n roomTerm: string;\n urlTerm: string;\n clientTerm: string;\n userTerm: string;\n /** Suffix appended to the client id once synced / while connecting. */\n clientSynced: string;\n clientConnecting: string;\n}\n\nexport const defaultCollabStatusLabels: CollabStatusLabels = {\n live: 'Live',\n connecting: 'Connecting…',\n editing: (names) =>\n `${names.join(', ')} ${names.length === 1 ? 'is' : 'are'} editing`,\n triggerLabel: 'Live-sync status — open the update log',\n peersTitle: (count) => `In the room (${count})`,\n alone: 'You are the only one here.',\n logTitle: (count) => `Update log (${count})`,\n close: 'Close update log',\n wrap: 'Wrap long values',\n empty: 'No updates yet.',\n roomTerm: 'Room',\n urlTerm: 'Socket',\n clientTerm: 'Client',\n userTerm: 'User',\n clientSynced: 'synced',\n clientConnecting: 'connecting',\n};\n\nexport interface CollabStatusProps {\n /** True once the room has completed its initial sync with the server. */\n connected: boolean;\n /** Other people in the room right now. */\n peers?: CollabPeer[];\n /** Recent collaboration events, newest first. */\n log?: CollabLogEntry[];\n /** Identity of the open room, shown at the top of the panel. */\n room?: CollabRoomInfo | null;\n /** Set false to render a status-only chip with no debug panel. */\n showLog?: boolean;\n /**\n * Render the trigger as the bare connection dot, moving the status text into\n * its accessible name. For headers with no room for a full chip.\n */\n compact?: boolean;\n /**\n * An app-level condition worth the same glance as the connection state, e.g.\n * `\"Unsaved changes\"`. While set, the dot turns amber and the text joins the\n * trigger's accessible name and heads the panel.\n */\n attention?: React.ReactNode;\n /** Overrides for any user-facing string. */\n labels?: Partial<CollabStatusLabels>;\n /** Additional className for the trigger wrapper. */\n className?: string;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/** One occupant: a person, however many windows they have open. */\ninterface Occupant extends CollabPeer {\n label: string;\n}\n\n/**\n * Collapse multiple windows of the same person into `Name (N)`; they count as\n * viewing only if every window is explicitly viewing.\n */\nfunction peerLabels(peers: CollabPeer[]): Occupant[] {\n const seen = new Map<string, CollabPeer & { count: number }>();\n for (const p of peers) {\n const entry = seen.get(p.name);\n if (!entry) seen.set(p.name, { ...p, count: 1 });\n else {\n entry.count += 1;\n if (entry.mode === 'viewing' && p.mode !== 'viewing') entry.mode = p.mode;\n entry.avatarUrl ??= p.avatarUrl;\n }\n }\n return [...seen.values()].map(({ count, ...p }) => ({\n ...p,\n label: count > 1 ? `${p.name} (${count})` : p.name,\n }));\n}\n\nconst PANEL_OFFSET = 6;\nconst VIEWPORT_PADDING = 8;\n\n/**\n * Position the panel under the trigger, inline-end-aligned to it (right edge\n * in LTR, left edge in RTL) but clamped to the viewport on both axes (it flips\n * above the trigger when it would overflow the bottom). Direction is reactive\n * (`useDirection`), so an open panel re-anchors when the nearest `dir`\n * changes; the returned `direction` must be restated on the portal root,\n * which cannot inherit a local `dir` from the trigger subtree. Position is\n * null until the panel has been measured.\n */\nfunction useAnchoredPanel(\n open: boolean,\n anchorRef: React.RefObject<HTMLElement | null>,\n panelRef: React.RefObject<HTMLElement | null>\n) {\n const direction = useDirection(anchorRef);\n const [pos, setPos] = React.useState<{ top: number; left: number } | null>(\n null\n );\n\n React.useLayoutEffect(() => {\n if (!open) {\n setPos(null);\n return;\n }\n const update = () => {\n const anchor = anchorRef.current;\n const panel = panelRef.current;\n if (!anchor || !panel) return;\n const a = anchor.getBoundingClientRect();\n const { offsetWidth: width, offsetHeight: height } = panel;\n\n // Hug the trigger's inline-end edge; clamp result to the viewport.\n const anchoredLeft = direction === 'rtl' ? a.left : a.right - width;\n const maxLeft = window.innerWidth - width - VIEWPORT_PADDING;\n const left = Math.max(\n VIEWPORT_PADDING,\n Math.min(anchoredLeft, Math.max(VIEWPORT_PADDING, maxLeft))\n );\n\n let top = a.bottom + PANEL_OFFSET;\n if (top + height > window.innerHeight - VIEWPORT_PADDING) {\n top = Math.max(VIEWPORT_PADDING, a.top - height - PANEL_OFFSET);\n }\n\n setPos({ top, left });\n };\n\n // Measured after the (hidden) panel has been laid out.\n const raf = window.requestAnimationFrame(update);\n window.addEventListener('scroll', update, true);\n window.addEventListener('resize', update);\n return () => {\n window.cancelAnimationFrame(raf);\n window.removeEventListener('scroll', update, true);\n window.removeEventListener('resize', update);\n };\n }, [open, anchorRef, panelRef, direction]);\n\n return { pos, direction };\n}\n\nconst KIND_TONE: Record<CollabLogKind, string> = {\n doc: 'text-muted-foreground',\n awareness: 'text-primary-600 dark:text-primary-400',\n sync: 'text-success-700 dark:text-success-400',\n patch: 'text-muted-foreground',\n};\n\n// =============================================================================\n// Component\n// =============================================================================\n\n/**\n * Live-collaboration status chip: a connection dot, a `Live` / `Connecting…`\n * label, a summary of who else is editing, and a click-to-open panel with the\n * room identity, who is in the room, and a rolling log of collaboration\n * events. Pass `compact` to shrink the trigger down to the dot alone, and\n * `attention` to let an app condition (\"Unsaved changes\") share that dot.\n *\n * Transport-agnostic — it renders whatever presence state you hand it. For a\n * Yjs (`y-websocket`) room, {@link useYjsCollabStatus} produces these props\n * directly:\n *\n * @example\n * ```tsx\n * const doc = React.useMemo(() => new Y.Doc(), []);\n * const provider = React.useMemo(\n * () => new WebsocketProvider('ws://localhost:1234', 'case/4', doc),\n * [doc]\n * );\n * const status = useYjsCollabStatus({ doc, provider, user: { name: 'Ann' } });\n *\n * return <CollabStatus {...status} />;\n * ```\n */\nexport function CollabStatus({\n connected,\n peers = [],\n log = [],\n room = null,\n showLog = true,\n compact = false,\n attention = null,\n labels: labelOverrides,\n className,\n}: CollabStatusProps) {\n const labels = { ...defaultCollabStatusLabels, ...labelOverrides };\n const [open, setOpen] = React.useState(false);\n const [wrapped, setWrapped] = React.useState(false);\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const panelRef = React.useRef<HTMLDivElement>(null);\n const { pos, direction } = useAnchoredPanel(\n open && showLog,\n triggerRef,\n panelRef\n );\n const titleId = React.useId();\n\n // Escape closes and returns focus; a pointer outside dismisses.\n React.useEffect(() => {\n if (!open) return;\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n setOpen(false);\n triggerRef.current?.focus();\n };\n const onPointerDown = (e: Event) => {\n const target = e.target as Node;\n if (panelRef.current?.contains(target)) return;\n if (triggerRef.current?.contains(target)) return;\n setOpen(false);\n };\n document.addEventListener('keydown', onKeyDown);\n document.addEventListener('pointerdown', onPointerDown);\n return () => {\n document.removeEventListener('keydown', onKeyDown);\n document.removeEventListener('pointerdown', onPointerDown);\n };\n }, [open]);\n\n const occupants = peerLabels(peers);\n const names = occupants\n .filter((p) => p.mode !== 'viewing')\n .map((p) => p.label);\n // Long values are clipped to one line; the panel's wrap toggle unclips them.\n const clip = wrapped ? 'break-all whitespace-pre-wrap' : 'truncate';\n const statusText = connected ? labels.live : labels.connecting;\n const clientLine = `${room?.clientId ?? '—'} · ${\n connected ? labels.clientSynced : labels.clientConnecting\n }`;\n // Compact triggers have no visible text, so the status and who is editing\n // have to reach assistive tech (and the tooltip) through the label.\n const triggerLabel = compact\n ? [\n labels.triggerLabel,\n statusText,\n attention,\n names.length > 0 && labels.editing(names),\n ]\n .filter(Boolean)\n .join(' — ')\n : labels.triggerLabel;\n\n const trigger = (\n <button\n type=\"button\"\n ref={triggerRef}\n className={cn(\n 'text-muted-foreground inline-flex items-center gap-1.5 rounded-md px-1.5 py-0.5 text-xs',\n 'focus-visible:ring-ring focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-none',\n showLog && 'hover:bg-muted cursor-pointer',\n className\n )}\n onClick={showLog ? () => setOpen((v) => !v) : undefined}\n disabled={!showLog}\n title={showLog ? triggerLabel : undefined}\n aria-expanded={showLog ? open : undefined}\n aria-label={showLog ? triggerLabel : undefined}\n data-slot=\"collab-status-trigger\"\n >\n <span\n aria-hidden=\"true\"\n data-slot=\"collab-status-dot\"\n className={cn(\n 'h-2 w-2 shrink-0 rounded-full',\n !connected && 'bg-warning-500 animate-pulse',\n connected && attention && 'bg-warning-500',\n connected && !attention && 'bg-success-500'\n )}\n />\n {!compact && <span>{statusText}</span>}\n {!compact && attention && (\n <span className=\"text-warning-700 dark:text-warning-400 truncate\">\n · {attention}\n </span>\n )}\n {!compact && names.length > 0 && (\n <span className=\"truncate\">{`· ${labels.editing(names)}`}</span>\n )}\n </button>\n );\n\n if (!showLog) return trigger;\n\n return (\n <span\n className=\"relative inline-flex items-center\"\n data-slot=\"collab-status\"\n >\n {trigger}\n {open &&\n typeof document !== 'undefined' &&\n createPortal(\n <div\n ref={panelRef}\n role=\"dialog\"\n aria-labelledby={titleId}\n data-slot=\"collab-status-panel\"\n // Portals under <body> don't inherit a local `dir` from the\n // trigger subtree; restate the resolved direction.\n dir={direction}\n className={cn(\n 'bg-card text-card-foreground border-border fixed z-50 w-[26rem] max-w-[calc(100vw-1rem)]',\n 'rounded-lg border p-3 text-xs shadow-xl'\n )}\n style={{\n top: pos?.top ?? 0,\n // rtl-ignore -- fixed viewport coords; direction resolved reactively in useAnchoredPanel\n left: pos?.left ?? 0,\n visibility: pos ? undefined : 'hidden',\n }}\n >\n <div className=\"mb-2 flex items-center justify-between gap-2\">\n <strong id={titleId} className=\"text-foreground text-sm\">\n {labels.logTitle(log.length)}\n </strong>\n <span className=\"flex items-center gap-0.5\">\n <button\n type=\"button\"\n className={cn(\n 'hover:text-foreground focus-visible:ring-ring rounded p-0.5 focus-visible:ring-2 focus-visible:outline-none',\n wrapped\n ? 'text-foreground bg-muted'\n : 'text-muted-foreground'\n )}\n onClick={() => setWrapped((v) => !v)}\n aria-pressed={wrapped}\n aria-label={labels.wrap}\n title={labels.wrap}\n data-slot=\"collab-status-wrap\"\n >\n <WrapText className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground focus-visible:ring-ring rounded p-0.5 focus-visible:ring-2 focus-visible:outline-none\"\n onClick={() => {\n setOpen(false);\n triggerRef.current?.focus();\n }}\n aria-label={labels.close}\n >\n <X className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n </span>\n </div>\n\n {attention && (\n <p\n data-slot=\"collab-status-attention\"\n className=\"text-warning-700 dark:text-warning-400 mb-2\"\n >\n {attention}\n </p>\n )}\n\n {room && (\n <dl className=\"border-border text-muted-foreground mb-2 grid grid-cols-[auto_1fr] gap-x-3 gap-y-0.5 border-b pb-2\">\n <dt className=\"opacity-70\">{labels.roomTerm}</dt>\n {/* The values are clipped, so hovering must reveal the rest. */}\n <dd className={clip} title={room.name}>\n {room.name}\n </dd>\n {room.url && (\n <>\n <dt className=\"opacity-70\">{labels.urlTerm}</dt>\n <dd className={clip} title={room.url}>\n {room.url}\n </dd>\n </>\n )}\n <dt className=\"opacity-70\">{labels.clientTerm}</dt>\n <dd className={clip} title={clientLine}>\n {clientLine}\n </dd>\n {room.userId && (\n <>\n <dt className=\"opacity-70\">{labels.userTerm}</dt>\n <dd className={clip} title={room.userId}>\n {room.userId}\n </dd>\n </>\n )}\n </dl>\n )}\n\n <section className=\"border-border mb-2 border-b pb-2\">\n <strong className=\"text-foreground mb-1 block\">\n {labels.peersTitle(peers.length)}\n </strong>\n {peers.length === 0 ? (\n <p className=\"text-muted-foreground\">{labels.alone}</p>\n ) : (\n <div data-slot=\"collab-status-peers\">\n <AvatarGroup\n size=\"sm\"\n max={8}\n className=\"flex-wrap ps-0.5\"\n labels={{\n list: labels.peersTitle(peers.length),\n ...(labels.presence && { presence: labels.presence }),\n }}\n items={occupants.map((peer) => ({\n id: peer.name,\n name: peer.name,\n label: peer.label,\n src: peer.avatarUrl,\n presence: peer.mode,\n color: peer.color,\n }))}\n />\n </div>\n )}\n </section>\n\n {log.length === 0 ? (\n <p className=\"text-muted-foreground\">{labels.empty}</p>\n ) : (\n <ul className=\"max-h-72 space-y-0.5 overflow-y-auto font-mono\">\n {log.map((e) => (\n <li\n key={e.id}\n className=\"grid grid-cols-[auto_auto_1fr] gap-2\"\n >\n <span className=\"text-muted-foreground opacity-70\">\n {new Date(e.at).toLocaleTimeString()}\n </span>\n <span\n className={cn(\n 'whitespace-nowrap',\n e.origin === 'remote'\n ? 'text-primary-600 dark:text-primary-400'\n : KIND_TONE[e.kind]\n )}\n >\n {e.kind}\n {e.origin ? `/${e.origin}` : ''}\n </span>\n <span\n className={cn('text-foreground', clip)}\n title={e.detail}\n >\n {e.detail}\n </span>\n </li>\n ))}\n </ul>\n )}\n </div>,\n document.body\n )}\n </span>\n );\n}\n","import * as React from 'react';\nimport type {\n CollabLogEntry,\n CollabPeer,\n CollabRoomInfo,\n} from './CollabStatus';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n// =============================================================================\n// Structural Yjs types\n// =============================================================================\n//\n// Declared structurally (as methods, so parameter bivariance applies) rather\n// than imported from `yjs` / `y-protocols`, so `@mieweb/ui` needs no Yjs\n// dependency at all. A real `Y.Doc`, `Awareness` and `WebsocketProvider`\n// satisfy these as-is.\n\n/** The subset of `Y.Doc` this hook observes. */\nexport interface YjsDocLike {\n clientID: number;\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler: (...args: any[]) => void): void;\n}\n\n/** The subset of `y-protocols/awareness`.`Awareness` this hook uses. */\nexport interface YjsAwarenessLike {\n clientID: number;\n getStates(): Map<number, Record<string, any>>;\n setLocalStateField(field: string, value: unknown): void;\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler: (...args: any[]) => void): void;\n}\n\n/** The subset of `y-websocket`.`WebsocketProvider` this hook uses. */\nexport interface YjsProviderLike {\n awareness: YjsAwarenessLike;\n /** True once the initial sync completed (y-websocket exposes this). */\n synced?: boolean;\n /** Room name, used as the default label in the debug panel. */\n roomname?: string;\n /** Server URL, used as the default label in the debug panel. */\n url?: string;\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler: (...args: any[]) => void): void;\n}\n\n/** Awareness payload published whenever this window makes a local edit. */\ninterface EditActivity {\n at: number;\n fields: string[];\n}\n\n/** A remote collaborator's edit that just changed the open document. */\nexport interface CollabRemoteEdit {\n /** Human-readable labels of the fields that changed. */\n fields: string[];\n /** Who made the change, when attributable from presence. */\n by?: string;\n /** Timestamp; a new value signals a fresh growl/toast. */\n at: number;\n}\n\nexport interface UseYjsCollabStatusOptions {\n /** The shared document. Pass null to keep the hook inert. */\n doc: YjsDocLike | null | undefined;\n /** The sync provider (e.g. `y-websocket`). Pass null to keep it inert. */\n provider: YjsProviderLike | null | undefined;\n /**\n * Presence identity published for this window. Defaults to\n * `User <clientID>` so windows are distinguishable without a login.\n */\n user?: { name?: string; color?: string };\n /** Room label for the debug panel. Defaults to `provider.roomname`. */\n roomName?: string;\n /** URL label for the debug panel. Defaults to `provider.url`. */\n url?: string;\n /** Application user id shown in the debug panel. */\n userId?: string;\n /** Maximum log entries kept in memory. Default 100. */\n logCap?: number;\n}\n\nexport interface YjsCollabStatus {\n /** True once the initial server sync completed. */\n connected: boolean;\n /** Other windows currently present in the room. */\n peers: CollabPeer[];\n /** Recent collaboration events, newest first. */\n log: CollabLogEntry[];\n /** Room identity for the debug panel. */\n room: CollabRoomInfo | null;\n /** The most recent remote edit, or null. */\n lastRemoteEdit: CollabRemoteEdit | null;\n /**\n * Announce a local edit and the fields it touched, so other windows can\n * attribute it. Also records a `patch` log entry.\n */\n publishActivity: (fields: string[]) => void;\n}\n\n// =============================================================================\n// Hook\n// =============================================================================\n\n/**\n * Bind {@link CollabStatus} to a Yjs room: tracks initial-sync state, publishes\n * this window's presence, tracks peers joining/leaving, attributes remote edits,\n * and keeps a capped log of document/awareness/sync events.\n *\n * The return value is spreadable straight into the component.\n *\n * @example\n * ```tsx\n * import * as Y from 'yjs';\n * import { WebsocketProvider } from 'y-websocket';\n * import { CollabStatus, useYjsCollabStatus } from '@mieweb/ui';\n *\n * function Header({ caseId }: { caseId: string }) {\n * const doc = React.useMemo(() => new Y.Doc(), []);\n * const provider = React.useMemo(\n * () => new WebsocketProvider('ws://localhost:1234', `case/${caseId}`, doc),\n * [doc, caseId]\n * );\n * React.useEffect(() => () => provider.destroy(), [provider]);\n *\n * const status = useYjsCollabStatus({ doc, provider, user: { name: 'Ann' } });\n * return <CollabStatus {...status} />;\n * }\n * ```\n */\nexport function useYjsCollabStatus({\n doc,\n provider,\n user,\n roomName,\n url,\n userId,\n logCap = 100,\n}: UseYjsCollabStatusOptions): YjsCollabStatus {\n const [connected, setConnected] = React.useState(false);\n const [peers, setPeers] = React.useState<CollabPeer[]>([]);\n const [lastRemoteEdit, setLastRemoteEdit] =\n React.useState<CollabRemoteEdit | null>(null);\n const [log, setLog] = React.useState<CollabLogEntry[]>([]);\n\n const logIdRef = React.useRef(0);\n const awarenessRef = React.useRef<YjsAwarenessLike | null>(null);\n /** Effective display name published to presence. */\n const selfNameRef = React.useRef('');\n /** Last activity timestamp seen per remote client, to detect new edits. */\n const activitySeen = React.useRef(new Map<number, number>());\n /** Names present, keyed by clientID, to detect join/leave. */\n const peerNames = React.useRef(new Map<number, string>());\n\n const pushLog = React.useCallback(\n (entry: Omit<CollabLogEntry, 'id' | 'at'>) => {\n const full: CollabLogEntry = {\n id: ++logIdRef.current,\n at: Date.now(),\n ...entry,\n };\n setLog((prev) => [full, ...prev].slice(0, logCap));\n },\n [logCap]\n );\n\n const selfName = user?.name?.trim();\n const selfColor = user?.color;\n\n React.useEffect(() => {\n if (!doc || !provider) {\n setConnected(false);\n setPeers([]);\n setLastRemoteEdit(null);\n return;\n }\n\n const awareness = provider.awareness;\n awarenessRef.current = awareness;\n activitySeen.current = new Map();\n peerNames.current = new Map();\n setConnected(provider.synced ?? false);\n\n // Remote updates arrive with `origin === provider`; local transactions have\n // a null origin — that is what labels the log entry.\n const onDocUpdate = (update: Uint8Array, origin: unknown) => {\n pushLog({\n kind: 'doc',\n origin: origin === provider ? 'remote' : 'local',\n detail: `doc update · ${update.byteLength} bytes`,\n });\n };\n doc.on('update', onDocUpdate);\n\n const onSync = (isSynced: boolean) => {\n setConnected(isSynced);\n pushLog({\n kind: 'sync',\n detail: isSynced ? 'synced with server' : 'disconnected',\n });\n };\n provider.on('sync', onSync);\n\n const onStatus = (event: { status?: string }) => {\n if (event?.status === 'disconnected') setConnected(false);\n };\n provider.on('status', onStatus);\n\n const onAwareness = () => {\n const others: CollabPeer[] = [];\n const present = new Map<number, string>();\n let freshest: CollabRemoteEdit | null = null;\n\n awareness.getStates().forEach((state, clientId) => {\n if (clientId === awareness.clientID) return; // skip this window\n const peer = state.user as CollabPeer | undefined;\n if (peer?.name) {\n others.push({ name: peer.name, color: peer.color });\n present.set(clientId, peer.name);\n }\n const activity = state.activity as EditActivity | undefined;\n if (\n activity &&\n activity.at > (activitySeen.current.get(clientId) ?? 0)\n ) {\n activitySeen.current.set(clientId, activity.at);\n if (!freshest || activity.at > freshest.at) {\n const sameUser = !!peer?.name && peer.name === selfNameRef.current;\n freshest = {\n fields: activity.fields,\n by: sameUser ? 'You (another window)' : peer?.name,\n at: activity.at,\n };\n }\n }\n });\n\n for (const [clientId, name] of present) {\n if (!peerNames.current.has(clientId)) {\n pushLog({\n kind: 'awareness',\n origin: 'remote',\n detail: `${name} joined the room`,\n });\n }\n }\n for (const [clientId, name] of peerNames.current) {\n if (!present.has(clientId)) {\n pushLog({\n kind: 'awareness',\n origin: 'remote',\n detail: `${name} left the room`,\n });\n }\n }\n peerNames.current = present;\n setPeers(others);\n\n if (freshest) {\n const edit = freshest as CollabRemoteEdit;\n setLastRemoteEdit(edit);\n pushLog({\n kind: 'awareness',\n origin: 'remote',\n detail: `${edit.by ?? 'peer'} edited ${edit.fields.join(', ')}`,\n });\n }\n };\n awareness.on('change', onAwareness);\n\n return () => {\n doc.off('update', onDocUpdate);\n provider.off('sync', onSync);\n provider.off('status', onStatus);\n awareness.off('change', onAwareness);\n awarenessRef.current = null;\n activitySeen.current = new Map();\n peerNames.current = new Map();\n setConnected(false);\n setPeers([]);\n setLastRemoteEdit(null);\n setLog([]);\n };\n }, [doc, provider, pushLog]);\n\n // Publish (and re-publish) this window's presence without tearing the room\n // down when the display name changes. Runs after the room effect above, which\n // is what populates `awarenessRef`.\n React.useEffect(() => {\n const awareness = awarenessRef.current;\n if (!awareness) return;\n const name = selfName || `User ${awareness.clientID}`;\n selfNameRef.current = name;\n awareness.setLocalStateField('user', { name, color: selfColor });\n }, [provider, selfName, selfColor]);\n\n const publishActivity = React.useCallback(\n (fields: string[]) => {\n awarenessRef.current?.setLocalStateField('activity', {\n at: Date.now(),\n fields,\n } satisfies EditActivity);\n pushLog({\n kind: 'patch',\n origin: 'local',\n detail: `edited ${fields.join(', ')}`,\n });\n },\n [pushLog]\n );\n\n const room: CollabRoomInfo | null =\n doc && provider\n ? {\n name: roomName ?? provider.roomname ?? 'room',\n url: url ?? provider.url,\n clientId: doc.clientID,\n userId,\n }\n : null;\n\n return { connected, peers, log, room, lastRemoteEdit, publishActivity };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/CollabStatus/CollabStatus.tsx","../src/components/CollabStatus/useYjsCollabStatus.ts"],"names":["useDirection","React","jsxs","cn","jsx","createPortal","WrapText","X","Fragment","AvatarGroup","React2"],"mappings":"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","file":"chunk-PJ4XEBMU.cjs","sourcesContent":["import * as React from 'react';\nimport { createPortal } from 'react-dom';\nimport { WrapText, X } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { useDirection } from '../../hooks/useDirection';\nimport { AvatarGroup, type AvatarPresence } from '../AvatarGroup/AvatarGroup';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Another participant currently present in the room. */\nexport interface CollabPeer {\n /** Display name published through presence. */\n name: string;\n /** Optional presence color (cursor/avatar tint). */\n color?: string;\n /**\n * What the peer is doing. Peers without a mode count as editing; `viewing`\n * peers are left out of the \"… are editing\" summary.\n */\n mode?: AvatarPresence;\n /** Avatar image URL. */\n avatarUrl?: string;\n}\n\n/** Static identity of the open collaboration room, shown in the debug panel. */\nexport interface CollabRoomInfo {\n /** Room name on the sync server (e.g. `case/4`). */\n name: string;\n /** Transport URL the client connected to. */\n url?: string;\n /** This window's client id (stable per document), or null before connect. */\n clientId?: number | null;\n /** The acting application user id passed to the sync server. */\n userId?: string;\n}\n\n/** Category of a collaboration event in the debug log. */\nexport type CollabLogKind = 'doc' | 'awareness' | 'sync' | 'patch';\n\n/** A single entry in the collaboration debug log. */\nexport interface CollabLogEntry {\n /** Stable key for rendering. */\n id: number | string;\n /** Wall-clock time of the event (epoch ms). */\n at: number;\n /** Event category. */\n kind: CollabLogKind;\n /** Whether this window or a peer originated it. */\n origin?: 'local' | 'remote';\n /** Human-readable detail line. */\n detail: string;\n}\n\n/** Every user-facing string, so apps can translate the widget. */\nexport interface CollabStatusLabels {\n /** Trigger text once the initial sync completed. */\n live: string;\n /** Trigger text before the initial sync completes. */\n connecting: string;\n /** Summary of who else is editing, e.g. `Ann, Bo are editing`. */\n editing: (names: string[]) => string;\n /** Accessible name / tooltip of the trigger button. */\n triggerLabel: string;\n /** Heading of the room-occupants section. */\n peersTitle: (count: number) => string;\n /** Shown in the occupants section when nobody else is in the room. */\n alone: React.ReactNode;\n /** Accessible name of an occupant with a `mode`, e.g. `Ann is viewing`. */\n presence?: (name: string, mode: AvatarPresence) => string;\n /** Heading of the debug panel. */\n logTitle: (count: number) => string;\n /** Accessible name of the panel close button. */\n close: string;\n /** Accessible name of the toggle that unclips long values. */\n wrap: string;\n /** Shown when the log is empty. */\n empty: React.ReactNode;\n roomTerm: string;\n urlTerm: string;\n clientTerm: string;\n userTerm: string;\n /** Suffix appended to the client id once synced / while connecting. */\n clientSynced: string;\n clientConnecting: string;\n}\n\nexport const defaultCollabStatusLabels: CollabStatusLabels = {\n live: 'Live',\n connecting: 'Connecting…',\n editing: (names) =>\n `${names.join(', ')} ${names.length === 1 ? 'is' : 'are'} editing`,\n triggerLabel: 'Live-sync status — open the update log',\n peersTitle: (count) => `In the room (${count})`,\n alone: 'You are the only one here.',\n logTitle: (count) => `Update log (${count})`,\n close: 'Close update log',\n wrap: 'Wrap long values',\n empty: 'No updates yet.',\n roomTerm: 'Room',\n urlTerm: 'Socket',\n clientTerm: 'Client',\n userTerm: 'User',\n clientSynced: 'synced',\n clientConnecting: 'connecting',\n};\n\nexport interface CollabStatusProps {\n /** True once the room has completed its initial sync with the server. */\n connected: boolean;\n /** Other people in the room right now. */\n peers?: CollabPeer[];\n /** Recent collaboration events, newest first. */\n log?: CollabLogEntry[];\n /** Identity of the open room, shown at the top of the panel. */\n room?: CollabRoomInfo | null;\n /** Set false to render a status-only chip with no debug panel. */\n showLog?: boolean;\n /**\n * Render the trigger as the bare connection dot, moving the status text into\n * its accessible name. For headers with no room for a full chip.\n */\n compact?: boolean;\n /**\n * An app-level condition worth the same glance as the connection state, e.g.\n * `\"Unsaved changes\"`. While set, the dot turns amber and the text joins the\n * trigger's accessible name and heads the panel.\n */\n attention?: React.ReactNode;\n /** Overrides for any user-facing string. */\n labels?: Partial<CollabStatusLabels>;\n /** Additional className for the trigger wrapper. */\n className?: string;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/** One occupant: a person, however many windows they have open. */\ninterface Occupant extends CollabPeer {\n label: string;\n}\n\n/**\n * Collapse multiple windows of the same person into `Name (N)`; they count as\n * viewing only if every window is explicitly viewing.\n */\nfunction peerLabels(peers: CollabPeer[]): Occupant[] {\n const seen = new Map<string, CollabPeer & { count: number }>();\n for (const p of peers) {\n const entry = seen.get(p.name);\n if (!entry) seen.set(p.name, { ...p, count: 1 });\n else {\n entry.count += 1;\n if (entry.mode === 'viewing' && p.mode !== 'viewing') entry.mode = p.mode;\n entry.avatarUrl ??= p.avatarUrl;\n }\n }\n return [...seen.values()].map(({ count, ...p }) => ({\n ...p,\n label: count > 1 ? `${p.name} (${count})` : p.name,\n }));\n}\n\nconst PANEL_OFFSET = 6;\nconst VIEWPORT_PADDING = 8;\n\n/**\n * Position the panel under the trigger, inline-end-aligned to it (right edge\n * in LTR, left edge in RTL) but clamped to the viewport on both axes (it flips\n * above the trigger when it would overflow the bottom). Direction is reactive\n * (`useDirection`), so an open panel re-anchors when the nearest `dir`\n * changes; the returned `direction` must be restated on the portal root,\n * which cannot inherit a local `dir` from the trigger subtree. Position is\n * null until the panel has been measured.\n */\nfunction useAnchoredPanel(\n open: boolean,\n anchorRef: React.RefObject<HTMLElement | null>,\n panelRef: React.RefObject<HTMLElement | null>\n) {\n const direction = useDirection(anchorRef);\n const [pos, setPos] = React.useState<{ top: number; left: number } | null>(\n null\n );\n\n React.useLayoutEffect(() => {\n if (!open) {\n setPos(null);\n return;\n }\n const update = () => {\n const anchor = anchorRef.current;\n const panel = panelRef.current;\n if (!anchor || !panel) return;\n const a = anchor.getBoundingClientRect();\n const { offsetWidth: width, offsetHeight: height } = panel;\n\n // Hug the trigger's inline-end edge; clamp result to the viewport.\n const anchoredLeft = direction === 'rtl' ? a.left : a.right - width;\n const maxLeft = window.innerWidth - width - VIEWPORT_PADDING;\n const left = Math.max(\n VIEWPORT_PADDING,\n Math.min(anchoredLeft, Math.max(VIEWPORT_PADDING, maxLeft))\n );\n\n let top = a.bottom + PANEL_OFFSET;\n if (top + height > window.innerHeight - VIEWPORT_PADDING) {\n top = Math.max(VIEWPORT_PADDING, a.top - height - PANEL_OFFSET);\n }\n\n setPos({ top, left });\n };\n\n // Measured after the (hidden) panel has been laid out.\n const raf = window.requestAnimationFrame(update);\n window.addEventListener('scroll', update, true);\n window.addEventListener('resize', update);\n return () => {\n window.cancelAnimationFrame(raf);\n window.removeEventListener('scroll', update, true);\n window.removeEventListener('resize', update);\n };\n }, [open, anchorRef, panelRef, direction]);\n\n return { pos, direction };\n}\n\nconst KIND_TONE: Record<CollabLogKind, string> = {\n doc: 'text-muted-foreground',\n awareness: 'text-primary-600 dark:text-primary-400',\n sync: 'text-success-700 dark:text-success-400',\n patch: 'text-muted-foreground',\n};\n\n// =============================================================================\n// Component\n// =============================================================================\n\n/**\n * Live-collaboration status chip: a connection dot, a `Live` / `Connecting…`\n * label, a summary of who else is editing, and a click-to-open panel with the\n * room identity, who is in the room, and a rolling log of collaboration\n * events. Pass `compact` to shrink the trigger down to the dot alone, and\n * `attention` to let an app condition (\"Unsaved changes\") share that dot.\n *\n * Transport-agnostic — it renders whatever presence state you hand it. For a\n * Yjs (`y-websocket`) room, {@link useYjsCollabStatus} produces these props\n * directly:\n *\n * @example\n * ```tsx\n * const doc = React.useMemo(() => new Y.Doc(), []);\n * const provider = React.useMemo(\n * () => new WebsocketProvider('ws://localhost:1234', 'case/4', doc),\n * [doc]\n * );\n * const status = useYjsCollabStatus({ doc, provider, user: { name: 'Ann' } });\n *\n * return <CollabStatus {...status} />;\n * ```\n */\nexport function CollabStatus({\n connected,\n peers = [],\n log = [],\n room = null,\n showLog = true,\n compact = false,\n attention = null,\n labels: labelOverrides,\n className,\n}: CollabStatusProps) {\n const labels = { ...defaultCollabStatusLabels, ...labelOverrides };\n const [open, setOpen] = React.useState(false);\n const [wrapped, setWrapped] = React.useState(false);\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const panelRef = React.useRef<HTMLDivElement>(null);\n const { pos, direction } = useAnchoredPanel(\n open && showLog,\n triggerRef,\n panelRef\n );\n const titleId = React.useId();\n\n // Escape closes and returns focus; a pointer outside dismisses.\n React.useEffect(() => {\n if (!open) return;\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n setOpen(false);\n triggerRef.current?.focus();\n };\n const onPointerDown = (e: Event) => {\n const target = e.target as Node;\n if (panelRef.current?.contains(target)) return;\n if (triggerRef.current?.contains(target)) return;\n setOpen(false);\n };\n document.addEventListener('keydown', onKeyDown);\n document.addEventListener('pointerdown', onPointerDown);\n return () => {\n document.removeEventListener('keydown', onKeyDown);\n document.removeEventListener('pointerdown', onPointerDown);\n };\n }, [open]);\n\n const occupants = peerLabels(peers);\n const names = occupants\n .filter((p) => p.mode !== 'viewing')\n .map((p) => p.label);\n // Long values are clipped to one line; the panel's wrap toggle unclips them.\n const clip = wrapped ? 'break-all whitespace-pre-wrap' : 'truncate';\n const statusText = connected ? labels.live : labels.connecting;\n const clientLine = `${room?.clientId ?? '—'} · ${\n connected ? labels.clientSynced : labels.clientConnecting\n }`;\n // Compact triggers have no visible text, so the status and who is editing\n // have to reach assistive tech (and the tooltip) through the label.\n const triggerLabel = compact\n ? [\n labels.triggerLabel,\n statusText,\n attention,\n names.length > 0 && labels.editing(names),\n ]\n .filter(Boolean)\n .join(' — ')\n : labels.triggerLabel;\n\n const trigger = (\n <button\n type=\"button\"\n ref={triggerRef}\n className={cn(\n 'text-muted-foreground inline-flex items-center gap-1.5 rounded-md px-1.5 py-0.5 text-xs',\n 'focus-visible:ring-ring focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-none',\n showLog && 'hover:bg-muted cursor-pointer',\n className\n )}\n onClick={showLog ? () => setOpen((v) => !v) : undefined}\n disabled={!showLog}\n title={showLog ? triggerLabel : undefined}\n aria-expanded={showLog ? open : undefined}\n aria-label={showLog ? triggerLabel : undefined}\n data-slot=\"collab-status-trigger\"\n >\n <span\n aria-hidden=\"true\"\n data-slot=\"collab-status-dot\"\n className={cn(\n 'h-2 w-2 shrink-0 rounded-full',\n !connected && 'bg-warning-500 animate-pulse',\n connected && attention && 'bg-warning-500',\n connected && !attention && 'bg-success-500'\n )}\n />\n {!compact && <span>{statusText}</span>}\n {!compact && attention && (\n <span className=\"text-warning-700 dark:text-warning-400 truncate\">\n · {attention}\n </span>\n )}\n {!compact && names.length > 0 && (\n <span className=\"truncate\">{`· ${labels.editing(names)}`}</span>\n )}\n </button>\n );\n\n if (!showLog) return trigger;\n\n return (\n <span\n className=\"relative inline-flex items-center\"\n data-slot=\"collab-status\"\n >\n {trigger}\n {open &&\n typeof document !== 'undefined' &&\n createPortal(\n <div\n ref={panelRef}\n role=\"dialog\"\n aria-labelledby={titleId}\n data-slot=\"collab-status-panel\"\n // Portals under <body> don't inherit a local `dir` from the\n // trigger subtree; restate the resolved direction.\n dir={direction}\n className={cn(\n 'bg-card text-card-foreground border-border fixed z-50 w-[26rem] max-w-[calc(100vw-1rem)]',\n 'rounded-lg border p-3 text-xs shadow-xl'\n )}\n style={{\n top: pos?.top ?? 0,\n // rtl-ignore -- fixed viewport coords; direction resolved reactively in useAnchoredPanel\n left: pos?.left ?? 0,\n visibility: pos ? undefined : 'hidden',\n }}\n >\n <div className=\"mb-2 flex items-center justify-between gap-2\">\n <strong id={titleId} className=\"text-foreground text-sm\">\n {labels.logTitle(log.length)}\n </strong>\n <span className=\"flex items-center gap-0.5\">\n <button\n type=\"button\"\n className={cn(\n 'hover:text-foreground focus-visible:ring-ring rounded p-0.5 focus-visible:ring-2 focus-visible:outline-none',\n wrapped\n ? 'text-foreground bg-muted'\n : 'text-muted-foreground'\n )}\n onClick={() => setWrapped((v) => !v)}\n aria-pressed={wrapped}\n aria-label={labels.wrap}\n title={labels.wrap}\n data-slot=\"collab-status-wrap\"\n >\n <WrapText className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground focus-visible:ring-ring rounded p-0.5 focus-visible:ring-2 focus-visible:outline-none\"\n onClick={() => {\n setOpen(false);\n triggerRef.current?.focus();\n }}\n aria-label={labels.close}\n >\n <X className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n </span>\n </div>\n\n {attention && (\n <p\n data-slot=\"collab-status-attention\"\n className=\"text-warning-700 dark:text-warning-400 mb-2\"\n >\n {attention}\n </p>\n )}\n\n {room && (\n <dl className=\"border-border text-muted-foreground mb-2 grid grid-cols-[auto_1fr] gap-x-3 gap-y-0.5 border-b pb-2\">\n <dt className=\"opacity-70\">{labels.roomTerm}</dt>\n {/* The values are clipped, so hovering must reveal the rest. */}\n <dd className={clip} title={room.name}>\n {room.name}\n </dd>\n {room.url && (\n <>\n <dt className=\"opacity-70\">{labels.urlTerm}</dt>\n <dd className={clip} title={room.url}>\n {room.url}\n </dd>\n </>\n )}\n <dt className=\"opacity-70\">{labels.clientTerm}</dt>\n <dd className={clip} title={clientLine}>\n {clientLine}\n </dd>\n {room.userId && (\n <>\n <dt className=\"opacity-70\">{labels.userTerm}</dt>\n <dd className={clip} title={room.userId}>\n {room.userId}\n </dd>\n </>\n )}\n </dl>\n )}\n\n <section className=\"border-border mb-2 border-b pb-2\">\n <strong className=\"text-foreground mb-1 block\">\n {labels.peersTitle(peers.length)}\n </strong>\n {peers.length === 0 ? (\n <p className=\"text-muted-foreground\">{labels.alone}</p>\n ) : (\n <div data-slot=\"collab-status-peers\">\n <AvatarGroup\n size=\"sm\"\n max={8}\n className=\"flex-wrap ps-0.5\"\n labels={{\n list: labels.peersTitle(peers.length),\n ...(labels.presence && { presence: labels.presence }),\n }}\n items={occupants.map((peer) => ({\n id: peer.name,\n name: peer.name,\n label: peer.label,\n src: peer.avatarUrl,\n presence: peer.mode,\n color: peer.color,\n }))}\n />\n </div>\n )}\n </section>\n\n {log.length === 0 ? (\n <p className=\"text-muted-foreground\">{labels.empty}</p>\n ) : (\n <ul className=\"max-h-72 space-y-0.5 overflow-y-auto font-mono\">\n {log.map((e) => (\n <li\n key={e.id}\n className=\"grid grid-cols-[auto_auto_1fr] gap-2\"\n >\n <span className=\"text-muted-foreground opacity-70\">\n {new Date(e.at).toLocaleTimeString()}\n </span>\n <span\n className={cn(\n 'whitespace-nowrap',\n e.origin === 'remote'\n ? 'text-primary-600 dark:text-primary-400'\n : KIND_TONE[e.kind]\n )}\n >\n {e.kind}\n {e.origin ? `/${e.origin}` : ''}\n </span>\n <span\n className={cn('text-foreground', clip)}\n title={e.detail}\n >\n {e.detail}\n </span>\n </li>\n ))}\n </ul>\n )}\n </div>,\n document.body\n )}\n </span>\n );\n}\n","import * as React from 'react';\nimport type {\n CollabLogEntry,\n CollabPeer,\n CollabRoomInfo,\n} from './CollabStatus';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n// =============================================================================\n// Structural Yjs types\n// =============================================================================\n//\n// Declared structurally (as methods, so parameter bivariance applies) rather\n// than imported from `yjs` / `y-protocols`, so `@mieweb/ui` needs no Yjs\n// dependency at all. A real `Y.Doc`, `Awareness` and `WebsocketProvider`\n// satisfy these as-is.\n\n/** The subset of `Y.Doc` this hook observes. */\nexport interface YjsDocLike {\n clientID: number;\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler: (...args: any[]) => void): void;\n}\n\n/** The subset of `y-protocols/awareness`.`Awareness` this hook uses. */\nexport interface YjsAwarenessLike {\n clientID: number;\n getStates(): Map<number, Record<string, any>>;\n setLocalStateField(field: string, value: unknown): void;\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler: (...args: any[]) => void): void;\n}\n\n/** The subset of `y-websocket`.`WebsocketProvider` this hook uses. */\nexport interface YjsProviderLike {\n awareness: YjsAwarenessLike;\n /** True once the initial sync completed (y-websocket exposes this). */\n synced?: boolean;\n /** Room name, used as the default label in the debug panel. */\n roomname?: string;\n /** Server URL, used as the default label in the debug panel. */\n url?: string;\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler: (...args: any[]) => void): void;\n}\n\n/** Awareness payload published whenever this window makes a local edit. */\ninterface EditActivity {\n at: number;\n fields: string[];\n}\n\n/** A remote collaborator's edit that just changed the open document. */\nexport interface CollabRemoteEdit {\n /** Human-readable labels of the fields that changed. */\n fields: string[];\n /** Who made the change, when attributable from presence. */\n by?: string;\n /** Timestamp; a new value signals a fresh growl/toast. */\n at: number;\n}\n\nexport interface UseYjsCollabStatusOptions {\n /** The shared document. Pass null to keep the hook inert. */\n doc: YjsDocLike | null | undefined;\n /** The sync provider (e.g. `y-websocket`). Pass null to keep it inert. */\n provider: YjsProviderLike | null | undefined;\n /**\n * Presence identity published for this window. Defaults to\n * `User <clientID>` so windows are distinguishable without a login.\n */\n user?: { name?: string; color?: string };\n /** Room label for the debug panel. Defaults to `provider.roomname`. */\n roomName?: string;\n /** URL label for the debug panel. Defaults to `provider.url`. */\n url?: string;\n /** Application user id shown in the debug panel. */\n userId?: string;\n /** Maximum log entries kept in memory. Default 100. */\n logCap?: number;\n}\n\nexport interface YjsCollabStatus {\n /** True once the initial server sync completed. */\n connected: boolean;\n /** Other windows currently present in the room. */\n peers: CollabPeer[];\n /** Recent collaboration events, newest first. */\n log: CollabLogEntry[];\n /** Room identity for the debug panel. */\n room: CollabRoomInfo | null;\n /** The most recent remote edit, or null. */\n lastRemoteEdit: CollabRemoteEdit | null;\n /**\n * Announce a local edit and the fields it touched, so other windows can\n * attribute it. Also records a `patch` log entry.\n */\n publishActivity: (fields: string[]) => void;\n}\n\n// =============================================================================\n// Hook\n// =============================================================================\n\n/**\n * Bind {@link CollabStatus} to a Yjs room: tracks initial-sync state, publishes\n * this window's presence, tracks peers joining/leaving, attributes remote edits,\n * and keeps a capped log of document/awareness/sync events.\n *\n * The return value is spreadable straight into the component.\n *\n * @example\n * ```tsx\n * import * as Y from 'yjs';\n * import { WebsocketProvider } from 'y-websocket';\n * import { CollabStatus, useYjsCollabStatus } from '@mieweb/ui';\n *\n * function Header({ caseId }: { caseId: string }) {\n * const doc = React.useMemo(() => new Y.Doc(), []);\n * const provider = React.useMemo(\n * () => new WebsocketProvider('ws://localhost:1234', `case/${caseId}`, doc),\n * [doc, caseId]\n * );\n * React.useEffect(() => () => provider.destroy(), [provider]);\n *\n * const status = useYjsCollabStatus({ doc, provider, user: { name: 'Ann' } });\n * return <CollabStatus {...status} />;\n * }\n * ```\n */\nexport function useYjsCollabStatus({\n doc,\n provider,\n user,\n roomName,\n url,\n userId,\n logCap = 100,\n}: UseYjsCollabStatusOptions): YjsCollabStatus {\n const [connected, setConnected] = React.useState(false);\n const [peers, setPeers] = React.useState<CollabPeer[]>([]);\n const [lastRemoteEdit, setLastRemoteEdit] =\n React.useState<CollabRemoteEdit | null>(null);\n const [log, setLog] = React.useState<CollabLogEntry[]>([]);\n\n const logIdRef = React.useRef(0);\n const awarenessRef = React.useRef<YjsAwarenessLike | null>(null);\n /** Effective display name published to presence. */\n const selfNameRef = React.useRef('');\n /** Last activity timestamp seen per remote client, to detect new edits. */\n const activitySeen = React.useRef(new Map<number, number>());\n /** Names present, keyed by clientID, to detect join/leave. */\n const peerNames = React.useRef(new Map<number, string>());\n\n const pushLog = React.useCallback(\n (entry: Omit<CollabLogEntry, 'id' | 'at'>) => {\n const full: CollabLogEntry = {\n id: ++logIdRef.current,\n at: Date.now(),\n ...entry,\n };\n setLog((prev) => [full, ...prev].slice(0, logCap));\n },\n [logCap]\n );\n\n const selfName = user?.name?.trim();\n const selfColor = user?.color;\n\n React.useEffect(() => {\n if (!doc || !provider) {\n setConnected(false);\n setPeers([]);\n setLastRemoteEdit(null);\n return;\n }\n\n const awareness = provider.awareness;\n awarenessRef.current = awareness;\n activitySeen.current = new Map();\n peerNames.current = new Map();\n setConnected(provider.synced ?? false);\n\n // Remote updates arrive with `origin === provider`; local transactions have\n // a null origin — that is what labels the log entry.\n const onDocUpdate = (update: Uint8Array, origin: unknown) => {\n pushLog({\n kind: 'doc',\n origin: origin === provider ? 'remote' : 'local',\n detail: `doc update · ${update.byteLength} bytes`,\n });\n };\n doc.on('update', onDocUpdate);\n\n const onSync = (isSynced: boolean) => {\n setConnected(isSynced);\n pushLog({\n kind: 'sync',\n detail: isSynced ? 'synced with server' : 'disconnected',\n });\n };\n provider.on('sync', onSync);\n\n const onStatus = (event: { status?: string }) => {\n if (event?.status === 'disconnected') setConnected(false);\n };\n provider.on('status', onStatus);\n\n const onAwareness = () => {\n const others: CollabPeer[] = [];\n const present = new Map<number, string>();\n let freshest: CollabRemoteEdit | null = null;\n\n awareness.getStates().forEach((state, clientId) => {\n if (clientId === awareness.clientID) return; // skip this window\n const peer = state.user as CollabPeer | undefined;\n if (peer?.name) {\n others.push({ name: peer.name, color: peer.color });\n present.set(clientId, peer.name);\n }\n const activity = state.activity as EditActivity | undefined;\n if (\n activity &&\n activity.at > (activitySeen.current.get(clientId) ?? 0)\n ) {\n activitySeen.current.set(clientId, activity.at);\n if (!freshest || activity.at > freshest.at) {\n const sameUser = !!peer?.name && peer.name === selfNameRef.current;\n freshest = {\n fields: activity.fields,\n by: sameUser ? 'You (another window)' : peer?.name,\n at: activity.at,\n };\n }\n }\n });\n\n for (const [clientId, name] of present) {\n if (!peerNames.current.has(clientId)) {\n pushLog({\n kind: 'awareness',\n origin: 'remote',\n detail: `${name} joined the room`,\n });\n }\n }\n for (const [clientId, name] of peerNames.current) {\n if (!present.has(clientId)) {\n pushLog({\n kind: 'awareness',\n origin: 'remote',\n detail: `${name} left the room`,\n });\n }\n }\n peerNames.current = present;\n setPeers(others);\n\n if (freshest) {\n const edit = freshest as CollabRemoteEdit;\n setLastRemoteEdit(edit);\n pushLog({\n kind: 'awareness',\n origin: 'remote',\n detail: `${edit.by ?? 'peer'} edited ${edit.fields.join(', ')}`,\n });\n }\n };\n awareness.on('change', onAwareness);\n\n return () => {\n doc.off('update', onDocUpdate);\n provider.off('sync', onSync);\n provider.off('status', onStatus);\n awareness.off('change', onAwareness);\n awarenessRef.current = null;\n activitySeen.current = new Map();\n peerNames.current = new Map();\n setConnected(false);\n setPeers([]);\n setLastRemoteEdit(null);\n setLog([]);\n };\n }, [doc, provider, pushLog]);\n\n // Publish (and re-publish) this window's presence without tearing the room\n // down when the display name changes. Runs after the room effect above, which\n // is what populates `awarenessRef`.\n React.useEffect(() => {\n const awareness = awarenessRef.current;\n if (!awareness) return;\n const name = selfName || `User ${awareness.clientID}`;\n selfNameRef.current = name;\n awareness.setLocalStateField('user', { name, color: selfColor });\n }, [provider, selfName, selfColor]);\n\n const publishActivity = React.useCallback(\n (fields: string[]) => {\n awarenessRef.current?.setLocalStateField('activity', {\n at: Date.now(),\n fields,\n } satisfies EditActivity);\n pushLog({\n kind: 'patch',\n origin: 'local',\n detail: `edited ${fields.join(', ')}`,\n });\n },\n [pushLog]\n );\n\n const room: CollabRoomInfo | null =\n doc && provider\n ? {\n name: roomName ?? provider.roomname ?? 'room',\n url: url ?? provider.url,\n clientId: doc.clientID,\n userId,\n }\n : null;\n\n return { connected, peers, log, room, lastRemoteEdit, publishActivity };\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { notifyComposerMigrationOnce, DragDropZone, ChatComposer, DEFAULT_MAX_FILE_SIZE, DEFAULT_ACCEPTED_FILE_TYPES, CameraButton } from './chunk-
|
|
1
|
+
import { notifyComposerMigrationOnce, DragDropZone, ChatComposer, DEFAULT_MAX_FILE_SIZE, DEFAULT_ACCEPTED_FILE_TYPES, CameraButton } from './chunk-KP72MDFB.js';
|
|
2
2
|
import { cn } from './chunk-TQONQSJO.js';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { cva } from 'class-variance-authority';
|
|
@@ -2043,5 +2043,5 @@ function MessagingSplitView({
|
|
|
2043
2043
|
MessagingSplitView.displayName = "MessagingSplitView";
|
|
2044
2044
|
|
|
2045
2045
|
export { AttachmentPreview, ConversationHeader, ConversationListItem, ConversationListSkeleton, DateSeparator, EmptyState, LightboxModal, LoadMoreButton, MessageBubble, MessageList, MessageStatusIcon, MessageThread, MessagingSplitView, ReadReceiptIndicator, SkeletonMessage, TypingIndicator, bubbleVariants, formatDateLabel, formatFileSize, formatLastSeen, getConversationSubtitle, getConversationTitle, groupMessagesByDate, headerVariants, isSameSenderGroup, useMessageScroll, useMessages, useReadReceipts, useTypingEmulation, useTypingIndicator };
|
|
2046
|
-
//# sourceMappingURL=chunk-
|
|
2047
|
-
//# sourceMappingURL=chunk-
|
|
2046
|
+
//# sourceMappingURL=chunk-PSCSU63K.js.map
|
|
2047
|
+
//# sourceMappingURL=chunk-PSCSU63K.js.map
|