@lobehub/ui 5.32.4 → 5.32.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/es/Markdown/SyntaxMarkdown/StreamdownRender.mjs +15 -294
  2. package/es/Markdown/SyntaxMarkdown/StreamdownRender.mjs.map +1 -1
  3. package/es/Markdown/type.d.mts +2 -3
  4. package/es/base-ui/ContextMenu/renderItems.mjs +24 -1
  5. package/es/base-ui/ContextMenu/renderItems.mjs.map +1 -1
  6. package/es/base-ui/Input/style.d.mts +2 -2
  7. package/es/base-ui/Segmented/Segmented.mjs +4 -0
  8. package/es/base-ui/Segmented/Segmented.mjs.map +1 -1
  9. package/es/base-ui/Segmented/style.mjs +4 -0
  10. package/es/base-ui/Segmented/style.mjs.map +1 -1
  11. package/es/base-ui/Tabs/style.mjs +12 -0
  12. package/es/base-ui/Tabs/style.mjs.map +1 -1
  13. package/es/base-ui/Tooltip/style.mjs +104 -20
  14. package/es/base-ui/Tooltip/style.mjs.map +1 -1
  15. package/es/hooks/useMarkdown/useMarkdownContent.mjs +4 -16
  16. package/es/hooks/useMarkdown/useMarkdownContent.mjs.map +1 -1
  17. package/es/hooks/useMarkdown/utils.mjs +1 -1
  18. package/es/hooks/useMarkdown/utils.mjs.map +1 -1
  19. package/es/index.d.mts +1 -1
  20. package/es/index.mjs +1 -1
  21. package/package.json +2 -88
  22. package/es/Markdown/SyntaxMarkdown/CachedMarkdown.mjs +0 -83
  23. package/es/Markdown/SyntaxMarkdown/CachedMarkdown.mjs.map +0 -1
  24. package/es/Markdown/SyntaxMarkdown/fenceState.mjs +0 -42
  25. package/es/Markdown/SyntaxMarkdown/fenceState.mjs.map +0 -1
  26. package/es/Markdown/SyntaxMarkdown/streamAnimationMeta.mjs +0 -14
  27. package/es/Markdown/SyntaxMarkdown/streamAnimationMeta.mjs.map +0 -1
  28. package/es/Markdown/SyntaxMarkdown/style.mjs +0 -28
  29. package/es/Markdown/SyntaxMarkdown/style.mjs.map +0 -1
  30. package/es/Markdown/SyntaxMarkdown/useSmoothStreamContent.mjs +0 -314
  31. package/es/Markdown/SyntaxMarkdown/useSmoothStreamContent.mjs.map +0 -1
  32. package/es/Markdown/SyntaxMarkdown/useStreamQueue.mjs +0 -88
  33. package/es/Markdown/SyntaxMarkdown/useStreamQueue.mjs.map +0 -1
  34. package/es/Markdown/plugins/rehypeStreamAnimated.d.mts +0 -33
  35. package/es/Markdown/plugins/rehypeStreamAnimated.mjs +0 -115
  36. package/es/Markdown/plugins/rehypeStreamAnimated.mjs.map +0 -1
  37. package/es/Markdown/streamProfiler/StreamdownProfilerProvider.mjs +0 -19
  38. package/es/Markdown/streamProfiler/StreamdownProfilerProvider.mjs.map +0 -1
  39. package/es/hooks/useMarkdown/latex.mjs +0 -294
  40. package/es/hooks/useMarkdown/latex.mjs.map +0 -1
  41. package/es/node_modules/.pnpm/@types_hast@3.0.5/node_modules/@types/hast/index.d.mts +0 -869
  42. package/es/utils/getNow.mjs +0 -8
  43. package/es/utils/getNow.mjs.map +0 -1
@@ -1,307 +1,28 @@
1
1
  "use client";
2
- import { isDeepEqual } from "../../utils/isDeepEqual.mjs";
3
- import { useStableValue } from "../../hooks/useStableValue.mjs";
4
2
  import { useMarkdownContext } from "../components/MarkdownProvider.mjs";
5
3
  import { useMarkdownComponents } from "../../hooks/useMarkdown/useMarkdownComponents.mjs";
6
4
  import { useMarkdownContent } from "../../hooks/useMarkdown/useMarkdownContent.mjs";
7
5
  import { useMarkdownRehypePlugins } from "../../hooks/useMarkdown/useMarkdownRehypePlugins.mjs";
8
6
  import { useMarkdownRemarkPlugins } from "../../hooks/useMarkdown/useMarkdownRemarkPlugins.mjs";
9
- import { getNow } from "../../utils/getNow.mjs";
10
- import { rehypeStreamAnimated } from "../plugins/rehypeStreamAnimated.mjs";
11
- import { useStreamdownProfiler } from "../streamProfiler/StreamdownProfilerProvider.mjs";
12
- import { CachedMarkdown } from "./CachedMarkdown.mjs";
13
- import { resolveBlockAnimationMeta } from "./streamAnimationMeta.mjs";
14
- import { styles } from "./style.mjs";
15
- import { countChars, useSmoothStreamContent } from "./useSmoothStreamContent.mjs";
16
- import { useStreamQueue } from "./useStreamQueue.mjs";
17
- import { Profiler, createElement, memo, useCallback, useEffect, useId, useMemo, useRef } from "react";
7
+ import { memo } from "react";
18
8
  import { jsx } from "react/jsx-runtime";
19
- import { marked } from "marked";
20
- import remend from "remend";
9
+ import { Streamdown } from "@lobehub/streamdown";
21
10
  //#region src/Markdown/SyntaxMarkdown/StreamdownRender.tsx
22
- const isSamePlugin = (prevPlugin, nextPlugin) => {
23
- const prevTuple = Array.isArray(prevPlugin) ? prevPlugin : [prevPlugin];
24
- const nextTuple = Array.isArray(nextPlugin) ? nextPlugin : [nextPlugin];
25
- if (prevTuple.length !== nextTuple.length) return false;
26
- if (prevTuple[0] !== nextTuple[0]) return false;
27
- return isDeepEqual(prevTuple.slice(1), nextTuple.slice(1));
28
- };
29
- const isSamePlugins = (prevPlugins, nextPlugins) => {
30
- if (prevPlugins === nextPlugins) return true;
31
- if (!prevPlugins || !nextPlugins) return !prevPlugins && !nextPlugins;
32
- if (prevPlugins.length !== nextPlugins.length) return false;
33
- for (let i = 0; i < prevPlugins.length; i++) if (!isSamePlugin(prevPlugins[i], nextPlugins[i])) return false;
34
- return true;
35
- };
36
- const useStablePlugins = (plugins) => {
37
- const stableRef = useRef(plugins);
38
- if (!isSamePlugins(stableRef.current, plugins)) stableRef.current = plugins;
39
- return stableRef.current;
40
- };
41
- const StreamdownBlock = memo(({ children, ...rest }) => {
42
- return /* @__PURE__ */ jsx(CachedMarkdown, {
43
- ...rest,
44
- children
45
- });
46
- }, (prevProps, nextProps) => prevProps.children === nextProps.children && prevProps.components === nextProps.components && isSamePlugins(prevProps.rehypePlugins, nextProps.rehypePlugins) && isSamePlugins(prevProps.remarkPlugins, nextProps.remarkPlugins));
47
- StreamdownBlock.displayName = "StreamdownBlock";
48
- const MIN_STREAM_CHAR_PACE_MS = 2;
49
- const MAX_REVEAL_GAP_MS = 160;
50
- const updateBlockAnimation = ({ blocks, charDelay, getBlockState, pluginsCache, renderNow, revealClock, runtimes }) => {
51
- const blockAnimationMeta = /* @__PURE__ */ new Map();
52
- const alive = /* @__PURE__ */ new Set();
53
- let revealedNewChars = false;
54
- for (const [index, block] of blocks.entries()) {
55
- alive.add(block.startOffset);
56
- const state = getBlockState(index);
57
- if (state === "queued") continue;
58
- let runtime = runtimes.get(block.startOffset);
59
- if (!runtime) {
60
- runtime = {
61
- births: [],
62
- charCount: 0,
63
- rawLength: -1,
64
- settled: false,
65
- styles: []
66
- };
67
- runtimes.set(block.startOffset, runtime);
68
- }
69
- if (runtime.rawLength !== block.content.length) {
70
- runtime.charCount = countChars(block.content);
71
- runtime.rawLength = block.content.length;
72
- }
73
- const blockCharCount = runtime.charCount;
74
- const births = runtime.births;
75
- if (births.length > blockCharCount) {
76
- births.length = blockCharCount;
77
- runtime.styles.length = blockCharCount;
78
- }
79
- if (births.length < blockCharCount) {
80
- const newChars = blockCharCount - births.length;
81
- let pace = charDelay;
82
- let cap = renderNow + 180;
83
- if (state === "streaming") {
84
- revealedNewChars = true;
85
- const gapMs = Math.min(Math.max(renderNow - revealClock.lastTs, 16), MAX_REVEAL_GAP_MS);
86
- pace = Math.min(charDelay, Math.max(gapMs / newChars, MIN_STREAM_CHAR_PACE_MS));
87
- cap = renderNow + gapMs + 180;
88
- }
89
- for (let i = births.length; i < blockCharCount; i++) {
90
- const chained = (i > 0 ? births[i - 1] : renderNow - pace) + pace;
91
- births.push(Math.min(cap, Math.max(chained, renderNow)));
92
- }
93
- }
94
- let meta;
95
- if (runtime.settled) meta = {
96
- charDelay: runtime.charDelay ?? charDelay,
97
- settled: true
98
- };
99
- else {
100
- const lastBirthTs = births.length > 0 ? births.at(-1) ?? renderNow : renderNow;
101
- meta = resolveBlockAnimationMeta({
102
- currentCharDelay: charDelay,
103
- fadeDuration: 180,
104
- lastElapsedMs: renderNow - lastBirthTs,
105
- previousCharDelay: runtime.charDelay,
106
- state
107
- });
108
- runtime.settled = meta.settled;
109
- }
110
- runtime.charDelay = meta.charDelay;
111
- blockAnimationMeta.set(block.startOffset, meta);
112
- }
113
- if (revealedNewChars) revealClock.lastTs = renderNow;
114
- for (const key of runtimes.keys()) if (!alive.has(key)) {
115
- runtimes.delete(key);
116
- pluginsCache.delete(key);
117
- }
118
- return blockAnimationMeta;
119
- };
120
- const StreamdownBlocks = memo(({ content: smoothedContent, markdownOptions: rest }) => {
121
- const { streamAnimationGranularity = "char" } = useMarkdownContext();
122
- const profiler = useStreamdownProfiler();
123
- const components = useMarkdownComponents();
124
- const baseRehypePlugins = useStablePlugins(useMarkdownRehypePlugins());
125
- const remarkPlugins = useStablePlugins(useMarkdownRemarkPlugins());
126
- const generatedId = useId();
127
- const processedContentResult = useMemo(() => {
128
- const start = profiler ? getNow() : 0;
129
- const value = remend(smoothedContent);
130
- return {
131
- durationMs: profiler ? getNow() - start : 0,
132
- value
133
- };
134
- }, [profiler, smoothedContent]);
135
- const processedContent = processedContentResult.value;
136
- const blocksResult = useMemo(() => {
137
- const start = profiler ? getNow() : 0;
138
- const tokens = marked.lexer(processedContent);
139
- let offset = 0;
140
- const value = tokens.map((token) => {
141
- const block = {
142
- content: token.raw,
143
- startOffset: offset
144
- };
145
- offset += token.raw.length;
146
- return block;
147
- });
148
- return {
149
- durationMs: profiler ? getNow() - start : 0,
150
- value
151
- };
152
- }, [processedContent, profiler]);
153
- const blocks = blocksResult.value;
154
- const { getBlockState, charDelay } = useStreamQueue(blocks);
155
- const blockRuntimesRef = useRef(/* @__PURE__ */ new Map());
156
- const blockPluginsRef = useRef(/* @__PURE__ */ new Map());
157
- const revealClockRef = useRef({ lastTs: 0 });
158
- const renderNow = getNow();
159
- const animationStart = profiler ? getNow() : 0;
160
- const blockAnimationMeta = updateBlockAnimation({
161
- blocks,
162
- charDelay,
163
- getBlockState,
164
- pluginsCache: blockPluginsRef.current,
165
- renderNow,
166
- revealClock: revealClockRef.current,
167
- runtimes: blockRuntimesRef.current
168
- });
169
- const blockAnimationDurationMs = profiler ? getNow() - animationStart : 0;
170
- useEffect(() => {
171
- if (!profiler) return;
172
- profiler.recordCalculation({
173
- durationMs: processedContentResult.durationMs,
174
- name: "content-normalize",
175
- textLength: processedContent.length
176
- });
177
- }, [
178
- processedContent.length,
179
- processedContentResult.durationMs,
180
- profiler
181
- ]);
182
- useEffect(() => {
183
- if (!profiler) return;
184
- profiler.recordCalculation({
185
- durationMs: blocksResult.durationMs,
186
- itemCount: blocks.length,
187
- name: "block-lex",
188
- textLength: processedContent.length
189
- });
190
- }, [
191
- blocks.length,
192
- blocksResult.durationMs,
193
- processedContent.length,
194
- profiler
195
- ]);
196
- useEffect(() => {
197
- if (!profiler) return;
198
- profiler.recordCalculation({
199
- durationMs: blockAnimationDurationMs,
200
- itemCount: blocks.length,
201
- name: "block-births",
202
- textLength: processedContent.length
203
- });
204
- }, [
205
- blockAnimationDurationMs,
206
- blocks.length,
207
- processedContent.length,
208
- profiler
209
- ]);
210
- const resolveBlockPlugins = (startOffset, settled) => {
211
- if (settled) return baseRehypePlugins;
212
- const cache = blockPluginsRef.current;
213
- const entry = cache.get(startOffset);
214
- if (entry && entry.base === baseRehypePlugins && entry.granularity === streamAnimationGranularity) return entry.value;
215
- const runtime = blockRuntimesRef.current.get(startOffset);
216
- const value = [...baseRehypePlugins, [rehypeStreamAnimated, {
217
- fadeDuration: 180,
218
- granularity: streamAnimationGranularity,
219
- runtime
220
- }]];
221
- cache.set(startOffset, {
222
- base: baseRehypePlugins,
223
- granularity: streamAnimationGranularity,
224
- value
225
- });
226
- return value;
227
- };
228
- const handleRootRender = useCallback((_, phase, actualDuration, baseDuration) => {
229
- profiler?.recordRootCommit({
230
- actualDuration,
231
- baseDuration,
232
- blockCount: blocks.length,
233
- phase,
234
- textLength: processedContent.length
235
- });
236
- }, [
237
- blocks.length,
238
- processedContent.length,
239
- profiler
240
- ]);
241
- const handleBlockRender = useCallback((id, phase, actualDuration, baseDuration) => {
242
- if (!profiler) return;
243
- const [, indexText, offsetText] = id.split(":");
244
- const blockIndex = Number(indexText);
245
- if (!Number.isFinite(blockIndex)) return;
246
- const block = blocks[blockIndex];
247
- if (!block) return;
248
- profiler.recordBlockCommit({
249
- actualDuration,
250
- baseDuration,
251
- blockChars: countChars(block.content),
252
- blockIndex,
253
- blockKey: offsetText ?? String(block.startOffset),
254
- phase,
255
- state: getBlockState(blockIndex)
256
- });
257
- }, [
258
- blocks,
259
- getBlockState,
260
- profiler
261
- ]);
262
- const content = /* @__PURE__ */ jsx("div", {
263
- className: styles.animated,
264
- children: blocks.map((block, index) => {
265
- const animationMeta = blockAnimationMeta.get(block.startOffset);
266
- if (!animationMeta) return null;
267
- const plugins = resolveBlockPlugins(block.startOffset, animationMeta.settled);
268
- const key = `${generatedId}-${block.startOffset}`;
269
- if (!profiler) return /* @__PURE__ */ createElement(StreamdownBlock, {
270
- ...rest,
271
- components,
272
- key,
273
- rehypePlugins: plugins,
274
- remarkPlugins
275
- }, block.content);
276
- return /* @__PURE__ */ jsx(Profiler, {
277
- id: `streamdown-block:${index}:${block.startOffset}`,
278
- onRender: handleBlockRender,
279
- children: /* @__PURE__ */ jsx(StreamdownBlock, {
280
- ...rest,
281
- components,
282
- rehypePlugins: plugins,
283
- remarkPlugins,
284
- children: block.content
285
- })
286
- }, key);
287
- })
288
- });
289
- if (!profiler) return content;
290
- return /* @__PURE__ */ jsx(Profiler, {
291
- id: "streamdown-root",
292
- onRender: handleRootRender,
293
- children: content
294
- });
295
- });
296
- StreamdownBlocks.displayName = "StreamdownBlocks";
297
11
  const StreamdownRender = memo(({ children, ...rest }) => {
298
- const { streamSmoothingPreset = "balanced" } = useMarkdownContext();
12
+ const { enableLatex = true, streamAnimationGranularity = "char", streamSmoothingPreset = "balanced" } = useMarkdownContext();
299
13
  const escapedContent = useMarkdownContent(children || "");
300
- const smoothedContent = useSmoothStreamContent(typeof escapedContent === "string" ? escapedContent : "", { preset: streamSmoothingPreset });
301
- const markdownOptions = useStableValue(rest);
302
- return /* @__PURE__ */ jsx(StreamdownBlocks, {
303
- content: smoothedContent,
304
- markdownOptions
14
+ const components = useMarkdownComponents();
15
+ const rehypePlugins = useMarkdownRehypePlugins();
16
+ const remarkPlugins = useMarkdownRemarkPlugins();
17
+ return /* @__PURE__ */ jsx(Streamdown, {
18
+ ...rest,
19
+ components,
20
+ content: typeof escapedContent === "string" ? escapedContent : "",
21
+ granularity: streamAnimationGranularity,
22
+ latexGuard: enableLatex,
23
+ rehypePlugins,
24
+ remarkPlugins,
25
+ smoothing: streamSmoothingPreset
305
26
  });
306
27
  });
307
28
  StreamdownRender.displayName = "StreamdownRender";
@@ -1 +1 @@
1
- {"version":3,"file":"StreamdownRender.mjs","names":[],"sources":["../../../src/Markdown/SyntaxMarkdown/StreamdownRender.tsx"],"sourcesContent":["'use client';\n\nimport { marked } from 'marked';\nimport {\n memo,\n Profiler,\n type ProfilerOnRenderCallback,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n} from 'react';\nimport { type Options } from 'react-markdown';\nimport remend from 'remend';\nimport type { Pluggable, PluggableList } from 'unified';\n\nimport {\n useMarkdownComponents,\n useMarkdownContent,\n useMarkdownRehypePlugins,\n useMarkdownRemarkPlugins,\n} from '@/hooks/useMarkdown';\nimport { useStableValue } from '@/hooks/useStableValue';\nimport { useMarkdownContext } from '@/Markdown/components/MarkdownProvider';\nimport {\n rehypeStreamAnimated,\n type StreamAnimatedRuntime,\n} from '@/Markdown/plugins/rehypeStreamAnimated';\nimport { useStreamdownProfiler } from '@/Markdown/streamProfiler';\nimport { type StreamAnimationGranularity } from '@/Markdown/type';\nimport { getNow } from '@/utils/getNow';\nimport { isDeepEqual } from '@/utils/isDeepEqual';\n\nimport { CachedMarkdown } from './CachedMarkdown';\nimport { type BlockAnimationMeta, resolveBlockAnimationMeta } from './streamAnimationMeta';\nimport { STREAM_FADE_DURATION, styles } from './style';\nimport { countChars, useSmoothStreamContent } from './useSmoothStreamContent';\nimport { type BlockInfo, type BlockState, useStreamQueue } from './useStreamQueue';\n\nconst isSamePlugin = (prevPlugin: Pluggable, nextPlugin: Pluggable): boolean => {\n const prevTuple = Array.isArray(prevPlugin) ? prevPlugin : [prevPlugin];\n const nextTuple = Array.isArray(nextPlugin) ? nextPlugin : [nextPlugin];\n\n if (prevTuple.length !== nextTuple.length) return false;\n if (prevTuple[0] !== nextTuple[0]) return false;\n\n return isDeepEqual(prevTuple.slice(1), nextTuple.slice(1));\n};\n\nconst isSamePlugins = (\n prevPlugins?: PluggableList | null,\n nextPlugins?: PluggableList | null,\n): boolean => {\n if (prevPlugins === nextPlugins) return true;\n if (!prevPlugins || !nextPlugins) return !prevPlugins && !nextPlugins;\n if (prevPlugins.length !== nextPlugins.length) return false;\n\n for (let i = 0; i < prevPlugins.length; i++) {\n if (!isSamePlugin(prevPlugins[i], nextPlugins[i])) return false;\n }\n\n return true;\n};\n\nconst useStablePlugins = (plugins: PluggableList): PluggableList => {\n const stableRef = useRef<PluggableList>(plugins);\n\n if (!isSamePlugins(stableRef.current, plugins)) {\n stableRef.current = plugins;\n }\n\n return stableRef.current;\n};\n\nconst StreamdownBlock = memo<Options>(\n ({ children, ...rest }) => {\n return <CachedMarkdown {...rest}>{children}</CachedMarkdown>;\n },\n (prevProps, nextProps) =>\n prevProps.children === nextProps.children &&\n prevProps.components === nextProps.components &&\n isSamePlugins(prevProps.rehypePlugins, nextProps.rehypePlugins) &&\n isSamePlugins(prevProps.remarkPlugins, nextProps.remarkPlugins),\n);\n\nStreamdownBlock.displayName = 'StreamdownBlock';\n\ninterface BlockRuntime extends StreamAnimatedRuntime {\n charCount: number;\n charDelay?: number;\n rawLength: number;\n settled: boolean;\n}\n\ninterface BlockPluginsCacheEntry {\n base: PluggableList;\n granularity: StreamAnimationGranularity;\n value: PluggableList;\n}\n\ninterface UpdateBlockAnimationArgs {\n blocks: BlockInfo[];\n charDelay: number;\n getBlockState: (index: number) => BlockState;\n pluginsCache: Map<number, BlockPluginsCacheEntry>;\n renderNow: number;\n revealClock: { lastTs: number };\n runtimes: Map<number, BlockRuntime>;\n}\n\nconst MIN_STREAM_CHAR_PACE_MS = 2;\nconst MAX_REVEAL_GAP_MS = 160;\n\n// Runs in the render phase: extends each visible block's birth timeline in\n// place and resolves its animation meta in one pass. Mutations are\n// idempotent for a given block content/length, so discarded or StrictMode\n// double renders re-derive the same state.\nconst updateBlockAnimation = ({\n blocks,\n charDelay,\n getBlockState,\n pluginsCache,\n renderNow,\n revealClock,\n runtimes,\n}: UpdateBlockAnimationArgs): Map<number, BlockAnimationMeta> => {\n const blockAnimationMeta = new Map<number, BlockAnimationMeta>();\n const alive = new Set<number>();\n let revealedNewChars = false;\n\n for (const [index, block] of blocks.entries()) {\n alive.add(block.startOffset);\n\n // Queued blocks are not rendered. Defer birth assignment so that\n // when the block later transitions to animating/streaming, its\n // chars start fading from that moment instead of having already\n // \"aged out\" of the fade window.\n const state = getBlockState(index);\n if (state === 'queued') continue;\n\n let runtime = runtimes.get(block.startOffset);\n if (!runtime) {\n runtime = { births: [], charCount: 0, rawLength: -1, settled: false, styles: [] };\n runtimes.set(block.startOffset, runtime);\n }\n\n if (runtime.rawLength !== block.content.length) {\n runtime.charCount = countChars(block.content);\n runtime.rawLength = block.content.length;\n }\n\n const blockCharCount = runtime.charCount;\n const births = runtime.births;\n\n if (births.length > blockCharCount) {\n // Block content shrunk (stream restart or upstream rewrite).\n births.length = blockCharCount;\n runtime.styles.length = blockCharCount;\n }\n\n if (births.length < blockCharCount) {\n // Chain each new char monotonically after the previous one so fades\n // never race out of order. Cap how far the fade queue can run ahead\n // of renderNow to prevent stream-faster-than-fade producing seconds\n // of invisible backlog at the tail.\n //\n // The streaming tail paces its stagger from the observed reveal-commit\n // gap instead of the queue's fixed charDelay: a commit's chars are\n // spread to land exactly until the next commit arrives, so the flow\n // stays per-char continuous no matter how far apart the throttled\n // commits are.\n const newChars = blockCharCount - births.length;\n let pace = charDelay;\n let cap = renderNow + STREAM_FADE_DURATION;\n if (state === 'streaming') {\n revealedNewChars = true;\n const gapMs = Math.min(Math.max(renderNow - revealClock.lastTs, 16), MAX_REVEAL_GAP_MS);\n pace = Math.min(charDelay, Math.max(gapMs / newChars, MIN_STREAM_CHAR_PACE_MS));\n cap = renderNow + gapMs + STREAM_FADE_DURATION;\n }\n for (let i = births.length; i < blockCharCount; i++) {\n const prevBirth = i > 0 ? births[i - 1] : renderNow - pace;\n const chained = prevBirth + pace;\n births.push(Math.min(cap, Math.max(chained, renderNow)));\n }\n }\n\n let meta: BlockAnimationMeta;\n if (runtime.settled) {\n // Settled is monotone: a revealed block's births are frozen, so once\n // its last fade completed it stays settled until the runtime is\n // pruned by a stream restart.\n meta = { charDelay: runtime.charDelay ?? charDelay, settled: true };\n } else {\n const lastBirthTs = births.length > 0 ? (births.at(-1) ?? renderNow) : renderNow;\n meta = resolveBlockAnimationMeta({\n currentCharDelay: charDelay,\n fadeDuration: STREAM_FADE_DURATION,\n lastElapsedMs: renderNow - lastBirthTs,\n previousCharDelay: runtime.charDelay,\n state,\n });\n runtime.settled = meta.settled;\n }\n runtime.charDelay = meta.charDelay;\n\n blockAnimationMeta.set(block.startOffset, meta);\n }\n\n if (revealedNewChars) {\n revealClock.lastTs = renderNow;\n }\n\n for (const key of runtimes.keys()) {\n if (!alive.has(key)) {\n runtimes.delete(key);\n pluginsCache.delete(key);\n }\n }\n\n return blockAnimationMeta;\n};\n\ninterface StreamdownBlocksProps {\n content: string;\n markdownOptions: Omit<Options, 'children'>;\n}\n\nconst StreamdownBlocks = memo<StreamdownBlocksProps>(\n ({ content: smoothedContent, markdownOptions: rest }) => {\n const { streamAnimationGranularity = 'char' } = useMarkdownContext();\n const profiler = useStreamdownProfiler();\n const components = useMarkdownComponents();\n const baseRehypePlugins = useStablePlugins(useMarkdownRehypePlugins());\n const remarkPlugins = useStablePlugins(useMarkdownRemarkPlugins());\n const generatedId = useId();\n\n const processedContentResult = useMemo(() => {\n const start = profiler ? getNow() : 0;\n const value = remend(smoothedContent);\n\n return {\n durationMs: profiler ? getNow() - start : 0,\n value,\n };\n }, [profiler, smoothedContent]);\n const processedContent = processedContentResult.value;\n\n const blocksResult = useMemo(() => {\n const start = profiler ? getNow() : 0;\n const tokens = marked.lexer(processedContent);\n let offset = 0;\n\n const value = tokens.map((token) => {\n const block = { content: token.raw, startOffset: offset };\n offset += token.raw.length;\n return block;\n });\n\n return {\n durationMs: profiler ? getNow() - start : 0,\n value,\n };\n }, [processedContent, profiler]);\n const blocks: BlockInfo[] = blocksResult.value;\n\n const { getBlockState, charDelay } = useStreamQueue(blocks);\n const blockRuntimesRef = useRef<Map<number, BlockRuntime>>(new Map());\n const blockPluginsRef = useRef<Map<number, BlockPluginsCacheEntry>>(new Map());\n const revealClockRef = useRef<{ lastTs: number }>({ lastTs: 0 });\n\n const renderNow = getNow();\n\n const animationStart = profiler ? getNow() : 0;\n const blockAnimationMeta = updateBlockAnimation({\n blocks,\n charDelay,\n getBlockState,\n pluginsCache: blockPluginsRef.current,\n renderNow,\n revealClock: revealClockRef.current,\n runtimes: blockRuntimesRef.current,\n });\n const blockAnimationDurationMs = profiler ? getNow() - animationStart : 0;\n\n useEffect(() => {\n if (!profiler) return;\n\n profiler.recordCalculation({\n durationMs: processedContentResult.durationMs,\n name: 'content-normalize',\n textLength: processedContent.length,\n });\n }, [processedContent.length, processedContentResult.durationMs, profiler]);\n\n useEffect(() => {\n if (!profiler) return;\n\n profiler.recordCalculation({\n durationMs: blocksResult.durationMs,\n itemCount: blocks.length,\n name: 'block-lex',\n textLength: processedContent.length,\n });\n }, [blocks.length, blocksResult.durationMs, processedContent.length, profiler]);\n\n useEffect(() => {\n if (!profiler) return;\n\n profiler.recordCalculation({\n durationMs: blockAnimationDurationMs,\n itemCount: blocks.length,\n name: 'block-births',\n textLength: processedContent.length,\n });\n }, [blockAnimationDurationMs, blocks.length, processedContent.length, profiler]);\n\n const resolveBlockPlugins = (startOffset: number, settled: boolean): PluggableList => {\n if (settled) return baseRehypePlugins;\n\n const cache = blockPluginsRef.current;\n const entry = cache.get(startOffset);\n if (\n entry &&\n entry.base === baseRehypePlugins &&\n entry.granularity === streamAnimationGranularity\n ) {\n return entry.value;\n }\n\n const runtime = blockRuntimesRef.current.get(startOffset);\n const value: PluggableList = [\n ...baseRehypePlugins,\n [\n rehypeStreamAnimated,\n {\n fadeDuration: STREAM_FADE_DURATION,\n granularity: streamAnimationGranularity,\n runtime,\n },\n ],\n ];\n cache.set(startOffset, {\n base: baseRehypePlugins,\n granularity: streamAnimationGranularity,\n value,\n });\n return value;\n };\n\n const handleRootRender = useCallback<ProfilerOnRenderCallback>(\n (_, phase, actualDuration, baseDuration) => {\n profiler?.recordRootCommit({\n actualDuration,\n baseDuration,\n blockCount: blocks.length,\n phase,\n textLength: processedContent.length,\n });\n },\n [blocks.length, processedContent.length, profiler],\n );\n\n const handleBlockRender = useCallback<ProfilerOnRenderCallback>(\n (id, phase, actualDuration, baseDuration) => {\n if (!profiler) return;\n\n const [, indexText, offsetText] = id.split(':');\n const blockIndex = Number(indexText);\n\n if (!Number.isFinite(blockIndex)) return;\n\n const block = blocks[blockIndex];\n if (!block) return;\n\n profiler.recordBlockCommit({\n actualDuration,\n baseDuration,\n blockChars: countChars(block.content),\n blockIndex,\n blockKey: offsetText ?? String(block.startOffset),\n phase,\n state: getBlockState(blockIndex),\n });\n },\n [blocks, getBlockState, profiler],\n );\n\n const content = (\n <div className={styles.animated}>\n {blocks.map((block, index) => {\n const animationMeta = blockAnimationMeta.get(block.startOffset);\n if (!animationMeta) return null;\n\n const plugins = resolveBlockPlugins(block.startOffset, animationMeta.settled);\n const key = `${generatedId}-${block.startOffset}`;\n\n if (!profiler) {\n return (\n <StreamdownBlock\n {...rest}\n components={components}\n key={key}\n rehypePlugins={plugins}\n remarkPlugins={remarkPlugins}\n >\n {block.content}\n </StreamdownBlock>\n );\n }\n\n return (\n <Profiler\n id={`streamdown-block:${index}:${block.startOffset}`}\n key={key}\n onRender={handleBlockRender}\n >\n <StreamdownBlock\n {...rest}\n components={components}\n rehypePlugins={plugins}\n remarkPlugins={remarkPlugins}\n >\n {block.content}\n </StreamdownBlock>\n </Profiler>\n );\n })}\n </div>\n );\n\n if (!profiler) return content;\n\n return (\n <Profiler id={'streamdown-root'} onRender={handleRootRender}>\n {content}\n </Profiler>\n );\n },\n);\n\nStreamdownBlocks.displayName = 'StreamdownBlocks';\n\n// The outer component absorbs the upstream per-chunk prop churn: every\n// streamed chunk re-renders it, but it only feeds the smoother and renders\n// a memoized child keyed on the smoother's output — so the expensive block\n// pipeline runs per reveal commit, not per chunk AND per commit.\nexport const StreamdownRender = memo<Options>(({ children, ...rest }) => {\n const { streamSmoothingPreset = 'balanced' } = useMarkdownContext();\n const escapedContent = useMarkdownContent(children || '');\n const smoothedContent = useSmoothStreamContent(\n typeof escapedContent === 'string' ? escapedContent : '',\n { preset: streamSmoothingPreset },\n );\n const markdownOptions = useStableValue(rest);\n\n return <StreamdownBlocks content={smoothedContent} markdownOptions={markdownOptions} />;\n});\n\nStreamdownRender.displayName = 'StreamdownRender';\n\nexport default StreamdownRender;\n"],"mappings":"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"}
1
+ {"version":3,"file":"StreamdownRender.mjs","names":[],"sources":["../../../src/Markdown/SyntaxMarkdown/StreamdownRender.tsx"],"sourcesContent":["'use client';\n\nimport { Streamdown } from '@lobehub/streamdown';\nimport { memo } from 'react';\nimport { type Options } from 'react-markdown';\n\nimport {\n useMarkdownComponents,\n useMarkdownContent,\n useMarkdownRehypePlugins,\n useMarkdownRemarkPlugins,\n} from '@/hooks/useMarkdown';\nimport { useMarkdownContext } from '@/Markdown/components/MarkdownProvider';\n\nexport const StreamdownRender = memo<Options>(({ children, ...rest }) => {\n const {\n enableLatex = true,\n streamAnimationGranularity = 'char',\n streamSmoothingPreset = 'balanced',\n } = useMarkdownContext();\n const escapedContent = useMarkdownContent(children || '');\n const components = useMarkdownComponents();\n const rehypePlugins = useMarkdownRehypePlugins();\n const remarkPlugins = useMarkdownRemarkPlugins();\n\n return (\n <Streamdown\n {...rest}\n components={components}\n content={typeof escapedContent === 'string' ? escapedContent : ''}\n granularity={streamAnimationGranularity}\n latexGuard={enableLatex}\n rehypePlugins={rehypePlugins}\n remarkPlugins={remarkPlugins}\n smoothing={streamSmoothingPreset}\n />\n );\n});\n\nStreamdownRender.displayName = 'StreamdownRender';\n\nexport default StreamdownRender;\n"],"mappings":";;;;;;;;;;AAcA,MAAa,mBAAmB,MAAe,EAAE,UAAU,GAAG,WAAW;CACvE,MAAM,EACJ,cAAc,MACd,6BAA6B,QAC7B,wBAAwB,eACtB,mBAAmB;CACvB,MAAM,iBAAiB,mBAAmB,YAAY,EAAE;CACxD,MAAM,aAAa,sBAAsB;CACzC,MAAM,gBAAgB,yBAAyB;CAC/C,MAAM,gBAAgB,yBAAyB;CAE/C,OACE,oBAAC,YAAD;EACE,GAAI;EACQ;EACZ,SAAS,OAAO,mBAAmB,WAAW,iBAAiB;EAC/D,aAAa;EACb,YAAY;EACG;EACA;EACf,WAAW;CACZ,CAAA;AAEL,CAAC;AAED,iBAAiB,cAAc"}
@@ -12,6 +12,7 @@ import { VideoProps } from "../mdx/mdxComponents/Video.mjs";
12
12
  import "../mdx/index.mjs";
13
13
  import { CSSProperties, ElementType, FC, ReactNode, Ref } from "react";
14
14
  import { AnchorProps } from "antd";
15
+ import { StreamAnimationGranularity, StreamSmoothingPreset } from "@lobehub/streamdown";
15
16
  import { Components, Options } from "react-markdown";
16
17
  import { Pluggable } from "unified";
17
18
  //#region src/Markdown/type.d.ts
@@ -23,8 +24,6 @@ interface TypographyProps extends DivProps {
23
24
  marginMultiple?: number;
24
25
  ref?: Ref<HTMLDivElement>;
25
26
  }
26
- type StreamSmoothingPreset = 'realtime' | 'balanced' | 'silky';
27
- type StreamAnimationGranularity = 'char' | 'word';
28
27
  interface SyntaxMarkdownProps {
29
28
  allowHtml?: boolean;
30
29
  allowHtmlList?: ElementType[];
@@ -69,5 +68,5 @@ interface MarkdownProps extends SyntaxMarkdownProps, Omit<TypographyProps, 'chil
69
68
  style?: CSSProperties;
70
69
  }
71
70
  //#endregion
72
- export { MarkdownProps, StreamAnimationGranularity, StreamSmoothingPreset, SyntaxMarkdownProps, TypographyProps };
71
+ export { MarkdownProps, type StreamAnimationGranularity, type StreamSmoothingPreset, SyntaxMarkdownProps, TypographyProps };
73
72
  //# sourceMappingURL=type.d.mts.map
@@ -1,6 +1,7 @@
1
1
  import Icon from "../../Icon/Icon.mjs";
2
2
  import { preventDefaultAndStopPropagation } from "../../utils/dom.mjs";
3
3
  import Switch from "../Switch/Switch.mjs";
4
+ import { useLayerZIndex } from "../zIndex/useLayerZIndex.mjs";
4
5
  import { styles } from "../DropdownMenu/sharedStyle.mjs";
5
6
  import { SubmenuArrowIcon } from "../SubmenuArrowIcon.mjs";
6
7
  import { getItemKey, getItemLabel, hasAnyIcon, hasCheckboxAndIcon, renderIcon } from "../../Menu/renderUtils.mjs";
@@ -12,6 +13,28 @@ import { cx } from "antd-style";
12
13
  import { Check } from "lucide-react";
13
14
  import { ContextMenu } from "@base-ui/react/context-menu";
14
15
  //#region src/base-ui/ContextMenu/renderItems.tsx
16
+ /**
17
+ * Submenu positioners are portaled outside the root menu, so they must allocate
18
+ * their own layer z-index (same pattern as DropdownMenu) rather than relying on
19
+ * the fixed CSS fallback that can fall behind after repeated root openings (#608).
20
+ */
21
+ const ContextMenuSubmenuPositioner = memo(({ style, ...rest }) => {
22
+ const explicitZIndex = typeof style !== "function" && style?.zIndex != null && typeof style.zIndex === "number" ? style.zIndex : void 0;
23
+ const { zIndex, ref: zRef } = useLayerZIndex("floating", explicitZIndex);
24
+ const resolvedStyle = typeof style === "function" ? (state) => ({
25
+ zIndex,
26
+ ...style(state)
27
+ }) : {
28
+ zIndex,
29
+ ...style
30
+ };
31
+ return /* @__PURE__ */ jsx(ContextMenu.Positioner, {
32
+ ...rest,
33
+ ref: zRef,
34
+ style: resolvedStyle
35
+ });
36
+ });
37
+ ContextMenuSubmenuPositioner.displayName = "ContextMenuSubmenuPositioner";
15
38
  const EmptyMenuItem = memo(() => {
16
39
  const { t } = useTranslation(common_default);
17
40
  return /* @__PURE__ */ jsx(ContextMenu.Item, {
@@ -211,7 +234,7 @@ const renderContextMenuItems = (items, keyPath = [], options) => {
211
234
  reserveIconSpace,
212
235
  submenu: true
213
236
  })
214
- }), /* @__PURE__ */ jsx(ContextMenu.Portal, { children: /* @__PURE__ */ jsx(ContextMenu.Positioner, {
237
+ }), /* @__PURE__ */ jsx(ContextMenu.Portal, { children: /* @__PURE__ */ jsx(ContextMenuSubmenuPositioner, {
215
238
  alignOffset: -4,
216
239
  className: styles.positioner,
217
240
  "data-submenu": "",
@@ -1 +1 @@
1
- {"version":3,"file":"renderItems.mjs","names":["common"],"sources":["../../../src/base-ui/ContextMenu/renderItems.tsx"],"sourcesContent":["import { ContextMenu } from '@base-ui/react/context-menu';\nimport { cx } from 'antd-style';\nimport { Check } from 'lucide-react';\nimport { type MenuInfo } from 'rc-menu/es/interface';\nimport {\n type KeyboardEvent as ReactKeyboardEvent,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n} from 'react';\nimport { memo, useCallback, useState } from 'react';\n\nimport { styles } from '@/base-ui/DropdownMenu/sharedStyle';\nimport { SubmenuArrowIcon } from '@/base-ui/SubmenuArrowIcon';\nimport Switch from '@/base-ui/Switch';\nimport common from '@/i18n/resources/en/common';\nimport { useTranslation } from '@/i18n/useTranslation';\nimport Icon from '@/Icon';\nimport {\n type BaseMenuItemGroupType,\n type BaseSubMenuType,\n getItemKey,\n getItemLabel,\n hasAnyIcon,\n hasCheckboxAndIcon,\n type MenuDividerType,\n type MenuItemType,\n renderIcon,\n type RenderItemContentOptions,\n type RenderOptions,\n} from '@/Menu';\nimport { preventDefaultAndStopPropagation } from '@/utils/dom';\n\nimport {\n type ContextMenuCheckboxItem,\n type ContextMenuItem,\n type ContextMenuSwitchItem,\n} from './type';\n\nexport type { IconAlign, IconSpaceMode } from '@/Menu';\n\nconst EmptyMenuItem = memo(() => {\n const { t } = useTranslation(common);\n return (\n <ContextMenu.Item disabled className={cx(styles.item, styles.empty)}>\n <div className={styles.itemContent}>\n <span className={styles.label}>{t('common.empty')}</span>\n </div>\n </ContextMenu.Item>\n );\n});\n\nEmptyMenuItem.displayName = 'EmptyMenuItem';\n\ninterface ContextMenuSwitchItemInternalProps {\n checked?: boolean;\n children: ReactNode;\n closeOnClick?: boolean;\n danger?: boolean;\n defaultChecked?: boolean;\n disabled?: boolean;\n label?: string;\n onCheckedChange?: (checked: boolean) => void;\n}\n\nconst ContextMenuSwitchItemInternal = ({\n checked: checkedProp,\n children,\n closeOnClick = false,\n danger,\n defaultChecked,\n disabled,\n label,\n onCheckedChange,\n}: ContextMenuSwitchItemInternalProps) => {\n const [internalChecked, setInternalChecked] = useState(defaultChecked ?? false);\n const isControlled = checkedProp !== undefined;\n const checked = isControlled ? checkedProp : internalChecked;\n\n const handleCheckedChange = useCallback(\n (newChecked: boolean) => {\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n onCheckedChange?.(newChecked);\n },\n [isControlled, onCheckedChange],\n );\n\n return (\n <ContextMenu.Item\n className={cx(styles.item, danger && styles.danger)}\n closeOnClick={closeOnClick}\n disabled={disabled}\n label={label}\n onClick={(e) => {\n e.preventDefault();\n if (!disabled) {\n handleCheckedChange(!checked);\n }\n }}\n >\n {children}\n <span\n style={{ display: 'inline-flex', marginInlineStart: 16 }}\n onFocus={(e) => e.stopPropagation()}\n >\n <Switch\n checked={checked}\n disabled={disabled}\n size=\"small\"\n tabIndex={-1}\n onChange={handleCheckedChange}\n onClick={(_, e) => e.stopPropagation()}\n />\n </span>\n </ContextMenu.Item>\n );\n};\n\nconst renderItemContent = (\n item: MenuItemType | BaseSubMenuType | ContextMenuCheckboxItem | ContextMenuSwitchItem,\n options?: RenderItemContentOptions,\n iconNode?: ReactNode,\n) => {\n const label = getItemLabel(item);\n const desc = 'desc' in item ? item.desc : undefined;\n const extra = 'extra' in item ? item.extra : undefined;\n const indicatorOnRight = options?.indicatorOnRight;\n const alignStart = Boolean(desc) && options?.iconAlign === 'start';\n const hasCustomIcon = iconNode !== undefined && !indicatorOnRight;\n const hasIcon = hasCustomIcon ? Boolean(iconNode) : Boolean(item.icon);\n const shouldRenderIcon = hasCustomIcon\n ? Boolean(options?.reserveIconSpace || iconNode)\n : Boolean(hasIcon || options?.reserveIconSpace);\n\n const labelNode = desc ? (\n <div className={styles.labelGroup}>\n <span className={styles.label}>{label}</span>\n <span className={styles.desc}>{desc}</span>\n </div>\n ) : (\n <span className={styles.label}>{label}</span>\n );\n\n return (\n <div className={cx(styles.itemContent, alignStart && styles.itemContentAlignStart)}>\n {shouldRenderIcon ? (\n <span\n aria-hidden={!hasIcon}\n className={cx(styles.icon, alignStart && styles.iconAlignStart)}\n >\n {hasCustomIcon ? iconNode : hasIcon ? renderIcon(item.icon, 'small') : null}\n </span>\n ) : null}\n {labelNode}\n {extra ? <span className={styles.extra}>{extra}</span> : null}\n {indicatorOnRight && iconNode ? iconNode : null}\n {options?.submenu ? (\n <span className={styles.submenuArrow}>\n <SubmenuArrowIcon />\n </span>\n ) : null}\n </div>\n );\n};\n\nconst invokeItemClick = (\n item: MenuItemType,\n keyPath: string[],\n event: ReactMouseEvent<HTMLElement> | ReactKeyboardEvent<HTMLElement>,\n) => {\n if (!item.onClick) return;\n const key = item.key ?? keyPath.at(-1) ?? '';\n const info: MenuInfo = {\n domEvent: event,\n item: event.currentTarget as MenuInfo['item'],\n key: String(key),\n keyPath,\n };\n item.onClick(info);\n};\n\nexport const renderContextMenuItems = (\n items: ContextMenuItem[],\n keyPath: string[] = [],\n options?: RenderOptions,\n): ReactNode[] => {\n const iconAlign = options?.iconAlign;\n const iconSpaceMode = options?.iconSpaceMode ?? 'global';\n const reserveIconSpace =\n options?.reserveIconSpace ?? hasAnyIcon(items, iconSpaceMode === 'global');\n const indicatorOnRight = options?.indicatorOnRight ?? hasCheckboxAndIcon(items);\n\n return items.map((item, index) => {\n if (!item) return null;\n\n const fallbackKey = `${keyPath.join('-') || 'root'}-${index}`;\n const itemKey = getItemKey(item, fallbackKey);\n const nextKeyPath = [...keyPath, String(itemKey)];\n\n if ((item as ContextMenuCheckboxItem).type === 'checkbox') {\n const checkboxItem = item as ContextMenuCheckboxItem;\n const label = getItemLabel(checkboxItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = Boolean(checkboxItem.danger);\n const indicator = (\n <ContextMenu.CheckboxItemIndicator>\n <Icon icon={Check} size={'small'} />\n </ContextMenu.CheckboxItemIndicator>\n );\n\n return (\n <ContextMenu.CheckboxItem\n checked={checkboxItem.checked}\n className={cx(styles.item, isDanger && styles.danger)}\n closeOnClick={checkboxItem.closeOnClick}\n defaultChecked={checkboxItem.defaultChecked}\n disabled={checkboxItem.disabled}\n key={itemKey}\n label={labelText}\n onCheckedChange={(checked) => checkboxItem.onCheckedChange?.(checked)}\n >\n {renderItemContent(\n checkboxItem,\n { iconAlign, indicatorOnRight, reserveIconSpace },\n indicator,\n )}\n </ContextMenu.CheckboxItem>\n );\n }\n\n if ((item as ContextMenuSwitchItem).type === 'switch') {\n const switchItem = item as ContextMenuSwitchItem;\n const label = getItemLabel(switchItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = Boolean(switchItem.danger);\n\n return (\n <ContextMenuSwitchItemInternal\n checked={switchItem.checked}\n closeOnClick={switchItem.closeOnClick}\n danger={isDanger}\n defaultChecked={switchItem.defaultChecked}\n disabled={switchItem.disabled}\n key={itemKey}\n label={labelText}\n onCheckedChange={switchItem.onCheckedChange}\n >\n {renderItemContent(switchItem, { iconAlign, reserveIconSpace })}\n </ContextMenuSwitchItemInternal>\n );\n }\n\n if ((item as MenuDividerType).type === 'divider') {\n return <ContextMenu.Separator className={styles.separator} key={itemKey} />;\n }\n\n if ((item as BaseMenuItemGroupType).type === 'group') {\n const group = item as BaseMenuItemGroupType;\n const groupReserveIconSpace =\n iconSpaceMode === 'group'\n ? group.children\n ? hasAnyIcon(group.children)\n : false\n : reserveIconSpace;\n const groupIndicatorOnRight = group.children ? hasCheckboxAndIcon(group.children) : false;\n return (\n <ContextMenu.Group key={itemKey}>\n {group.label ? (\n <ContextMenu.GroupLabel className={styles.groupLabel}>\n {group.label}\n </ContextMenu.GroupLabel>\n ) : null}\n {group.children\n ? renderContextMenuItems(group.children, nextKeyPath, {\n iconAlign,\n iconSpaceMode,\n indicatorOnRight: groupIndicatorOnRight,\n reserveIconSpace: groupReserveIconSpace,\n })\n : null}\n </ContextMenu.Group>\n );\n }\n\n if (\n (item as BaseSubMenuType).type === 'submenu' ||\n ('children' in item && (item as BaseSubMenuType).children)\n ) {\n const submenu = item as BaseSubMenuType;\n const label = getItemLabel(submenu);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = 'danger' in submenu && Boolean(submenu.danger);\n const submenuHasSlots = submenu.header != null || submenu.footer != null;\n const submenuBody =\n submenu.children && submenu.children.length > 0 ? (\n renderContextMenuItems(submenu.children, nextKeyPath, {\n iconAlign,\n iconSpaceMode,\n })\n ) : (\n <EmptyMenuItem />\n );\n\n return (\n <ContextMenu.SubmenuRoot\n defaultOpen={submenu.defaultOpen}\n key={itemKey}\n open={submenu.open}\n onOpenChange={submenu.onOpenChange}\n >\n <ContextMenu.SubmenuTrigger\n {...submenu.triggerProps}\n className={cx(styles.item, isDanger && styles.danger)}\n closeDelay={submenu.closeDelay}\n delay={submenu.delay}\n disabled={submenu.disabled}\n label={labelText}\n openOnHover={submenu.openOnHover}\n onClick={submenu.onClick}\n >\n {renderItemContent(submenu, {\n iconAlign,\n reserveIconSpace,\n submenu: true,\n })}\n </ContextMenu.SubmenuTrigger>\n <ContextMenu.Portal>\n <ContextMenu.Positioner\n alignOffset={-4}\n className={styles.positioner}\n data-submenu=\"\"\n sideOffset={-1}\n onContextMenu={preventDefaultAndStopPropagation}\n >\n <ContextMenu.Popup\n className={submenuHasSlots ? cx(styles.popup, styles.popupWithSlots) : styles.popup}\n >\n {submenu.header == null ? null : (\n <div className={styles.header}>{submenu.header}</div>\n )}\n {submenuHasSlots ? (\n <div className={styles.slotViewport}>{submenuBody}</div>\n ) : (\n submenuBody\n )}\n {submenu.footer == null ? null : (\n <div className={styles.footer}>{submenu.footer}</div>\n )}\n </ContextMenu.Popup>\n </ContextMenu.Positioner>\n </ContextMenu.Portal>\n </ContextMenu.SubmenuRoot>\n );\n }\n\n const menuItem = item as MenuItemType;\n const label = getItemLabel(menuItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = 'danger' in menuItem && Boolean(menuItem.danger);\n\n return (\n <ContextMenu.Item\n className={cx(styles.item, isDanger && styles.danger)}\n closeOnClick={menuItem.closeOnClick}\n disabled={menuItem.disabled}\n key={itemKey}\n label={labelText}\n onClick={(event) => invokeItemClick(menuItem, nextKeyPath, event)}\n >\n {renderItemContent(menuItem, { iconAlign, reserveIconSpace })}\n </ContextMenu.Item>\n );\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"renderItems.mjs","names":["common"],"sources":["../../../src/base-ui/ContextMenu/renderItems.tsx"],"sourcesContent":["import { ContextMenu } from '@base-ui/react/context-menu';\nimport { cx } from 'antd-style';\nimport { Check } from 'lucide-react';\nimport { type MenuInfo } from 'rc-menu/es/interface';\nimport {\n type ComponentProps,\n type KeyboardEvent as ReactKeyboardEvent,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n} from 'react';\nimport { memo, useCallback, useState } from 'react';\n\nimport { styles } from '@/base-ui/DropdownMenu/sharedStyle';\nimport { SubmenuArrowIcon } from '@/base-ui/SubmenuArrowIcon';\nimport Switch from '@/base-ui/Switch';\nimport common from '@/i18n/resources/en/common';\nimport { useTranslation } from '@/i18n/useTranslation';\nimport Icon from '@/Icon';\nimport {\n type BaseMenuItemGroupType,\n type BaseSubMenuType,\n getItemKey,\n getItemLabel,\n hasAnyIcon,\n hasCheckboxAndIcon,\n type MenuDividerType,\n type MenuItemType,\n renderIcon,\n type RenderItemContentOptions,\n type RenderOptions,\n} from '@/Menu';\nimport { preventDefaultAndStopPropagation } from '@/utils/dom';\n\nimport { useLayerZIndex } from '../zIndex';\nimport {\n type ContextMenuCheckboxItem,\n type ContextMenuItem,\n type ContextMenuSwitchItem,\n} from './type';\n\ntype ContextMenuPositionerProps = ComponentProps<typeof ContextMenu.Positioner>;\n\n/**\n * Submenu positioners are portaled outside the root menu, so they must allocate\n * their own layer z-index (same pattern as DropdownMenu) rather than relying on\n * the fixed CSS fallback that can fall behind after repeated root openings (#608).\n */\nconst ContextMenuSubmenuPositioner = memo(({ style, ...rest }: ContextMenuPositionerProps) => {\n const explicitZIndex =\n typeof style !== 'function' && style?.zIndex != null && typeof style.zIndex === 'number'\n ? style.zIndex\n : undefined;\n const { zIndex, ref: zRef } = useLayerZIndex<HTMLDivElement>('floating', explicitZIndex);\n\n const resolvedStyle =\n typeof style === 'function'\n ? (state: any) => ({ zIndex, ...style(state) })\n : { zIndex, ...style };\n\n return <ContextMenu.Positioner {...rest} ref={zRef as any} style={resolvedStyle} />;\n});\n\nContextMenuSubmenuPositioner.displayName = 'ContextMenuSubmenuPositioner';\n\nexport type { IconAlign, IconSpaceMode } from '@/Menu';\n\nconst EmptyMenuItem = memo(() => {\n const { t } = useTranslation(common);\n return (\n <ContextMenu.Item disabled className={cx(styles.item, styles.empty)}>\n <div className={styles.itemContent}>\n <span className={styles.label}>{t('common.empty')}</span>\n </div>\n </ContextMenu.Item>\n );\n});\n\nEmptyMenuItem.displayName = 'EmptyMenuItem';\n\ninterface ContextMenuSwitchItemInternalProps {\n checked?: boolean;\n children: ReactNode;\n closeOnClick?: boolean;\n danger?: boolean;\n defaultChecked?: boolean;\n disabled?: boolean;\n label?: string;\n onCheckedChange?: (checked: boolean) => void;\n}\n\nconst ContextMenuSwitchItemInternal = ({\n checked: checkedProp,\n children,\n closeOnClick = false,\n danger,\n defaultChecked,\n disabled,\n label,\n onCheckedChange,\n}: ContextMenuSwitchItemInternalProps) => {\n const [internalChecked, setInternalChecked] = useState(defaultChecked ?? false);\n const isControlled = checkedProp !== undefined;\n const checked = isControlled ? checkedProp : internalChecked;\n\n const handleCheckedChange = useCallback(\n (newChecked: boolean) => {\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n onCheckedChange?.(newChecked);\n },\n [isControlled, onCheckedChange],\n );\n\n return (\n <ContextMenu.Item\n className={cx(styles.item, danger && styles.danger)}\n closeOnClick={closeOnClick}\n disabled={disabled}\n label={label}\n onClick={(e) => {\n e.preventDefault();\n if (!disabled) {\n handleCheckedChange(!checked);\n }\n }}\n >\n {children}\n <span\n style={{ display: 'inline-flex', marginInlineStart: 16 }}\n onFocus={(e) => e.stopPropagation()}\n >\n <Switch\n checked={checked}\n disabled={disabled}\n size=\"small\"\n tabIndex={-1}\n onChange={handleCheckedChange}\n onClick={(_, e) => e.stopPropagation()}\n />\n </span>\n </ContextMenu.Item>\n );\n};\n\nconst renderItemContent = (\n item: MenuItemType | BaseSubMenuType | ContextMenuCheckboxItem | ContextMenuSwitchItem,\n options?: RenderItemContentOptions,\n iconNode?: ReactNode,\n) => {\n const label = getItemLabel(item);\n const desc = 'desc' in item ? item.desc : undefined;\n const extra = 'extra' in item ? item.extra : undefined;\n const indicatorOnRight = options?.indicatorOnRight;\n const alignStart = Boolean(desc) && options?.iconAlign === 'start';\n const hasCustomIcon = iconNode !== undefined && !indicatorOnRight;\n const hasIcon = hasCustomIcon ? Boolean(iconNode) : Boolean(item.icon);\n const shouldRenderIcon = hasCustomIcon\n ? Boolean(options?.reserveIconSpace || iconNode)\n : Boolean(hasIcon || options?.reserveIconSpace);\n\n const labelNode = desc ? (\n <div className={styles.labelGroup}>\n <span className={styles.label}>{label}</span>\n <span className={styles.desc}>{desc}</span>\n </div>\n ) : (\n <span className={styles.label}>{label}</span>\n );\n\n return (\n <div className={cx(styles.itemContent, alignStart && styles.itemContentAlignStart)}>\n {shouldRenderIcon ? (\n <span\n aria-hidden={!hasIcon}\n className={cx(styles.icon, alignStart && styles.iconAlignStart)}\n >\n {hasCustomIcon ? iconNode : hasIcon ? renderIcon(item.icon, 'small') : null}\n </span>\n ) : null}\n {labelNode}\n {extra ? <span className={styles.extra}>{extra}</span> : null}\n {indicatorOnRight && iconNode ? iconNode : null}\n {options?.submenu ? (\n <span className={styles.submenuArrow}>\n <SubmenuArrowIcon />\n </span>\n ) : null}\n </div>\n );\n};\n\nconst invokeItemClick = (\n item: MenuItemType,\n keyPath: string[],\n event: ReactMouseEvent<HTMLElement> | ReactKeyboardEvent<HTMLElement>,\n) => {\n if (!item.onClick) return;\n const key = item.key ?? keyPath.at(-1) ?? '';\n const info: MenuInfo = {\n domEvent: event,\n item: event.currentTarget as MenuInfo['item'],\n key: String(key),\n keyPath,\n };\n item.onClick(info);\n};\n\nexport const renderContextMenuItems = (\n items: ContextMenuItem[],\n keyPath: string[] = [],\n options?: RenderOptions,\n): ReactNode[] => {\n const iconAlign = options?.iconAlign;\n const iconSpaceMode = options?.iconSpaceMode ?? 'global';\n const reserveIconSpace =\n options?.reserveIconSpace ?? hasAnyIcon(items, iconSpaceMode === 'global');\n const indicatorOnRight = options?.indicatorOnRight ?? hasCheckboxAndIcon(items);\n\n return items.map((item, index) => {\n if (!item) return null;\n\n const fallbackKey = `${keyPath.join('-') || 'root'}-${index}`;\n const itemKey = getItemKey(item, fallbackKey);\n const nextKeyPath = [...keyPath, String(itemKey)];\n\n if ((item as ContextMenuCheckboxItem).type === 'checkbox') {\n const checkboxItem = item as ContextMenuCheckboxItem;\n const label = getItemLabel(checkboxItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = Boolean(checkboxItem.danger);\n const indicator = (\n <ContextMenu.CheckboxItemIndicator>\n <Icon icon={Check} size={'small'} />\n </ContextMenu.CheckboxItemIndicator>\n );\n\n return (\n <ContextMenu.CheckboxItem\n checked={checkboxItem.checked}\n className={cx(styles.item, isDanger && styles.danger)}\n closeOnClick={checkboxItem.closeOnClick}\n defaultChecked={checkboxItem.defaultChecked}\n disabled={checkboxItem.disabled}\n key={itemKey}\n label={labelText}\n onCheckedChange={(checked) => checkboxItem.onCheckedChange?.(checked)}\n >\n {renderItemContent(\n checkboxItem,\n { iconAlign, indicatorOnRight, reserveIconSpace },\n indicator,\n )}\n </ContextMenu.CheckboxItem>\n );\n }\n\n if ((item as ContextMenuSwitchItem).type === 'switch') {\n const switchItem = item as ContextMenuSwitchItem;\n const label = getItemLabel(switchItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = Boolean(switchItem.danger);\n\n return (\n <ContextMenuSwitchItemInternal\n checked={switchItem.checked}\n closeOnClick={switchItem.closeOnClick}\n danger={isDanger}\n defaultChecked={switchItem.defaultChecked}\n disabled={switchItem.disabled}\n key={itemKey}\n label={labelText}\n onCheckedChange={switchItem.onCheckedChange}\n >\n {renderItemContent(switchItem, { iconAlign, reserveIconSpace })}\n </ContextMenuSwitchItemInternal>\n );\n }\n\n if ((item as MenuDividerType).type === 'divider') {\n return <ContextMenu.Separator className={styles.separator} key={itemKey} />;\n }\n\n if ((item as BaseMenuItemGroupType).type === 'group') {\n const group = item as BaseMenuItemGroupType;\n const groupReserveIconSpace =\n iconSpaceMode === 'group'\n ? group.children\n ? hasAnyIcon(group.children)\n : false\n : reserveIconSpace;\n const groupIndicatorOnRight = group.children ? hasCheckboxAndIcon(group.children) : false;\n return (\n <ContextMenu.Group key={itemKey}>\n {group.label ? (\n <ContextMenu.GroupLabel className={styles.groupLabel}>\n {group.label}\n </ContextMenu.GroupLabel>\n ) : null}\n {group.children\n ? renderContextMenuItems(group.children, nextKeyPath, {\n iconAlign,\n iconSpaceMode,\n indicatorOnRight: groupIndicatorOnRight,\n reserveIconSpace: groupReserveIconSpace,\n })\n : null}\n </ContextMenu.Group>\n );\n }\n\n if (\n (item as BaseSubMenuType).type === 'submenu' ||\n ('children' in item && (item as BaseSubMenuType).children)\n ) {\n const submenu = item as BaseSubMenuType;\n const label = getItemLabel(submenu);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = 'danger' in submenu && Boolean(submenu.danger);\n const submenuHasSlots = submenu.header != null || submenu.footer != null;\n const submenuBody =\n submenu.children && submenu.children.length > 0 ? (\n renderContextMenuItems(submenu.children, nextKeyPath, {\n iconAlign,\n iconSpaceMode,\n })\n ) : (\n <EmptyMenuItem />\n );\n\n return (\n <ContextMenu.SubmenuRoot\n defaultOpen={submenu.defaultOpen}\n key={itemKey}\n open={submenu.open}\n onOpenChange={submenu.onOpenChange}\n >\n <ContextMenu.SubmenuTrigger\n {...submenu.triggerProps}\n className={cx(styles.item, isDanger && styles.danger)}\n closeDelay={submenu.closeDelay}\n delay={submenu.delay}\n disabled={submenu.disabled}\n label={labelText}\n openOnHover={submenu.openOnHover}\n onClick={submenu.onClick}\n >\n {renderItemContent(submenu, {\n iconAlign,\n reserveIconSpace,\n submenu: true,\n })}\n </ContextMenu.SubmenuTrigger>\n <ContextMenu.Portal>\n <ContextMenuSubmenuPositioner\n alignOffset={-4}\n className={styles.positioner}\n data-submenu=\"\"\n sideOffset={-1}\n onContextMenu={preventDefaultAndStopPropagation}\n >\n <ContextMenu.Popup\n className={submenuHasSlots ? cx(styles.popup, styles.popupWithSlots) : styles.popup}\n >\n {submenu.header == null ? null : (\n <div className={styles.header}>{submenu.header}</div>\n )}\n {submenuHasSlots ? (\n <div className={styles.slotViewport}>{submenuBody}</div>\n ) : (\n submenuBody\n )}\n {submenu.footer == null ? null : (\n <div className={styles.footer}>{submenu.footer}</div>\n )}\n </ContextMenu.Popup>\n </ContextMenuSubmenuPositioner>\n </ContextMenu.Portal>\n </ContextMenu.SubmenuRoot>\n );\n }\n\n const menuItem = item as MenuItemType;\n const label = getItemLabel(menuItem);\n const labelText = typeof label === 'string' ? label : undefined;\n const isDanger = 'danger' in menuItem && Boolean(menuItem.danger);\n\n return (\n <ContextMenu.Item\n className={cx(styles.item, isDanger && styles.danger)}\n closeOnClick={menuItem.closeOnClick}\n disabled={menuItem.disabled}\n key={itemKey}\n label={labelText}\n onClick={(event) => invokeItemClick(menuItem, nextKeyPath, event)}\n >\n {renderItemContent(menuItem, { iconAlign, reserveIconSpace })}\n </ContextMenu.Item>\n );\n });\n};\n"],"mappings":"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"}
@@ -23,8 +23,8 @@ declare const styles: {
23
23
  };
24
24
  declare const rootVariants: (props?: ({
25
25
  shadow?: boolean | null | undefined;
26
- size?: "small" | "middle" | "large" | null | undefined;
27
- variant?: "filled" | "outlined" | "borderless" | null | undefined;
26
+ size?: "large" | "middle" | "small" | null | undefined;
27
+ variant?: "filled" | "borderless" | "outlined" | null | undefined;
28
28
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
29
29
  //#endregion
30
30
  export { rootVariants, styles };
@@ -29,12 +29,16 @@ const Segmented = ({ block = false, className, classNames, defaultValue, disable
29
29
  if (!list) return;
30
30
  const active = list.querySelector("[data-segmented-item][data-pressed]");
31
31
  if (!active) {
32
+ list.style.setProperty("--active-item-left", "0px");
33
+ list.style.setProperty("--active-item-top", "0px");
34
+ list.style.setProperty("--active-item-right", "0px");
32
35
  list.style.setProperty("--active-item-width", "0px");
33
36
  list.style.setProperty("--active-item-height", "0px");
34
37
  return;
35
38
  }
36
39
  list.style.setProperty("--active-item-left", `${active.offsetLeft}px`);
37
40
  list.style.setProperty("--active-item-top", `${active.offsetTop}px`);
41
+ list.style.setProperty("--active-item-right", `${list.clientWidth - active.offsetLeft - active.offsetWidth}px`);
38
42
  list.style.setProperty("--active-item-width", `${active.offsetWidth}px`);
39
43
  list.style.setProperty("--active-item-height", `${active.offsetHeight}px`);
40
44
  }, []);
@@ -1 +1 @@
1
- {"version":3,"file":"Segmented.mjs","names":["useControlledState"],"sources":["../../../src/base-ui/Segmented/Segmented.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport {\n type CSSProperties,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n} from 'react';\nimport useControlledState from 'use-merge-value';\n\nimport {\n SegmentedIndicator,\n SegmentedItem,\n SegmentedItemIcon,\n SegmentedItemLabel,\n SegmentedRoot,\n} from './atoms';\nimport type { SegmentedOption, SegmentedProps } from './type';\n\nconst normalizeOption = <Value extends string>(\n option: SegmentedOption<Value> | Value,\n): SegmentedOption<Value> =>\n typeof option === 'string' ? { label: option, value: option } : option;\n\nconst Segmented = <Value extends string = string>({\n block = false,\n className,\n classNames,\n defaultValue,\n disabled = false,\n glass = false,\n id,\n name,\n onChange,\n options,\n ref,\n shadow = false,\n size = 'middle',\n style,\n styles: customStyles,\n value,\n variant = 'filled',\n vertical = false,\n}: SegmentedProps<Value>) => {\n const [innerValue, setInnerValue] = useControlledState<Value | undefined>(defaultValue, {\n defaultValue,\n onChange: (next) => {\n if (next != null) onChange?.(next);\n },\n value,\n });\n\n const listRef = useRef<HTMLDivElement | null>(null);\n\n const mergedRef = useCallback(\n (node: HTMLDivElement | null) => {\n listRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) (ref as React.RefObject<HTMLDivElement | null>).current = node;\n },\n [ref],\n );\n\n const normalizedOptions = useMemo(\n () => (options ?? []).map((o) => normalizeOption<Value>(o)),\n [options],\n );\n\n const updateIndicator = useCallback(() => {\n const list = listRef.current;\n if (!list) return;\n const active = list.querySelector<HTMLElement>('[data-segmented-item][data-pressed]');\n if (!active) {\n list.style.setProperty('--active-item-width', '0px');\n list.style.setProperty('--active-item-height', '0px');\n return;\n }\n list.style.setProperty('--active-item-left', `${active.offsetLeft}px`);\n list.style.setProperty('--active-item-top', `${active.offsetTop}px`);\n list.style.setProperty('--active-item-width', `${active.offsetWidth}px`);\n list.style.setProperty('--active-item-height', `${active.offsetHeight}px`);\n }, []);\n\n useLayoutEffect(() => {\n updateIndicator();\n }, [innerValue, normalizedOptions, vertical, size, block, updateIndicator]);\n\n useEffect(() => {\n const list = listRef.current;\n if (!list || typeof ResizeObserver === 'undefined') return;\n const ro = new ResizeObserver(() => updateIndicator());\n ro.observe(list);\n return () => ro.disconnect();\n }, [updateIndicator]);\n\n const groupValue = useMemo<Value[]>(() => (innerValue != null ? [innerValue] : []), [innerValue]);\n\n const rootStyle: CSSProperties = { ...style, ...customStyles?.root };\n\n return (\n <SegmentedRoot<Value>\n block={block}\n className={cx(classNames?.root, className)}\n disabled={disabled}\n glass={glass}\n id={id}\n orientation={vertical ? 'vertical' : 'horizontal'}\n ref={mergedRef}\n shadow={shadow}\n style={rootStyle}\n value={groupValue}\n variant={variant}\n onValueChange={(next) => {\n const picked = next[0];\n if (picked != null) setInnerValue(picked);\n }}\n >\n <SegmentedIndicator className={classNames?.indicator} style={customStyles?.indicator} />\n {normalizedOptions.map((opt) => (\n <SegmentedItem<Value>\n aria-label={typeof opt.label === 'string' ? opt.label : undefined}\n block={block}\n className={cx(classNames?.item, opt.className)}\n data-segmented-item=\"\"\n disabled={disabled || opt.disabled}\n key={opt.value}\n name={name}\n size={size}\n style={customStyles?.item}\n title={opt.title}\n value={opt.value}\n >\n {opt.icon != null && (\n <SegmentedItemIcon className={classNames?.itemIcon} style={customStyles?.itemIcon}>\n {opt.icon}\n </SegmentedItemIcon>\n )}\n {opt.label != null && (\n <SegmentedItemLabel className={classNames?.itemLabel} style={customStyles?.itemLabel}>\n {opt.label}\n </SegmentedItemLabel>\n )}\n </SegmentedItem>\n ))}\n </SegmentedRoot>\n );\n};\n\nSegmented.displayName = 'Segmented';\n\nexport default Segmented;\n"],"mappings":"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"}
1
+ {"version":3,"file":"Segmented.mjs","names":["useControlledState"],"sources":["../../../src/base-ui/Segmented/Segmented.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport {\n type CSSProperties,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n} from 'react';\nimport useControlledState from 'use-merge-value';\n\nimport {\n SegmentedIndicator,\n SegmentedItem,\n SegmentedItemIcon,\n SegmentedItemLabel,\n SegmentedRoot,\n} from './atoms';\nimport type { SegmentedOption, SegmentedProps } from './type';\n\nconst normalizeOption = <Value extends string>(\n option: SegmentedOption<Value> | Value,\n): SegmentedOption<Value> =>\n typeof option === 'string' ? { label: option, value: option } : option;\n\nconst Segmented = <Value extends string = string>({\n block = false,\n className,\n classNames,\n defaultValue,\n disabled = false,\n glass = false,\n id,\n name,\n onChange,\n options,\n ref,\n shadow = false,\n size = 'middle',\n style,\n styles: customStyles,\n value,\n variant = 'filled',\n vertical = false,\n}: SegmentedProps<Value>) => {\n const [innerValue, setInnerValue] = useControlledState<Value | undefined>(defaultValue, {\n defaultValue,\n onChange: (next) => {\n if (next != null) onChange?.(next);\n },\n value,\n });\n\n const listRef = useRef<HTMLDivElement | null>(null);\n\n const mergedRef = useCallback(\n (node: HTMLDivElement | null) => {\n listRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) (ref as React.RefObject<HTMLDivElement | null>).current = node;\n },\n [ref],\n );\n\n const normalizedOptions = useMemo(\n () => (options ?? []).map((o) => normalizeOption<Value>(o)),\n [options],\n );\n\n const updateIndicator = useCallback(() => {\n const list = listRef.current;\n if (!list) return;\n const active = list.querySelector<HTMLElement>('[data-segmented-item][data-pressed]');\n if (!active) {\n list.style.setProperty('--active-item-left', '0px');\n list.style.setProperty('--active-item-top', '0px');\n list.style.setProperty('--active-item-right', '0px');\n list.style.setProperty('--active-item-width', '0px');\n list.style.setProperty('--active-item-height', '0px');\n return;\n }\n list.style.setProperty('--active-item-left', `${active.offsetLeft}px`);\n list.style.setProperty('--active-item-top', `${active.offsetTop}px`);\n list.style.setProperty(\n '--active-item-right',\n `${list.clientWidth - active.offsetLeft - active.offsetWidth}px`,\n );\n list.style.setProperty('--active-item-width', `${active.offsetWidth}px`);\n list.style.setProperty('--active-item-height', `${active.offsetHeight}px`);\n }, []);\n\n useLayoutEffect(() => {\n updateIndicator();\n }, [innerValue, normalizedOptions, vertical, size, block, updateIndicator]);\n\n useEffect(() => {\n const list = listRef.current;\n if (!list || typeof ResizeObserver === 'undefined') return;\n const ro = new ResizeObserver(() => updateIndicator());\n ro.observe(list);\n return () => ro.disconnect();\n }, [updateIndicator]);\n\n const groupValue = useMemo<Value[]>(() => (innerValue != null ? [innerValue] : []), [innerValue]);\n\n const rootStyle: CSSProperties = { ...style, ...customStyles?.root };\n\n return (\n <SegmentedRoot<Value>\n block={block}\n className={cx(classNames?.root, className)}\n disabled={disabled}\n glass={glass}\n id={id}\n orientation={vertical ? 'vertical' : 'horizontal'}\n ref={mergedRef}\n shadow={shadow}\n style={rootStyle}\n value={groupValue}\n variant={variant}\n onValueChange={(next) => {\n const picked = next[0];\n if (picked != null) setInnerValue(picked);\n }}\n >\n <SegmentedIndicator className={classNames?.indicator} style={customStyles?.indicator} />\n {normalizedOptions.map((opt) => (\n <SegmentedItem<Value>\n aria-label={typeof opt.label === 'string' ? opt.label : undefined}\n block={block}\n className={cx(classNames?.item, opt.className)}\n data-segmented-item=\"\"\n disabled={disabled || opt.disabled}\n key={opt.value}\n name={name}\n size={size}\n style={customStyles?.item}\n title={opt.title}\n value={opt.value}\n >\n {opt.icon != null && (\n <SegmentedItemIcon className={classNames?.itemIcon} style={customStyles?.itemIcon}>\n {opt.icon}\n </SegmentedItemIcon>\n )}\n {opt.label != null && (\n <SegmentedItemLabel className={classNames?.itemLabel} style={customStyles?.itemLabel}>\n {opt.label}\n </SegmentedItemLabel>\n )}\n </SegmentedItem>\n ))}\n </SegmentedRoot>\n );\n};\n\nSegmented.displayName = 'Segmented';\n\nexport default Segmented;\n"],"mappings":"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"}
@@ -22,6 +22,10 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
22
22
  transition-duration: 240ms;
23
23
  transition-property: inset-inline-start, inset-block-start, width, height;
24
24
 
25
+ [data-orientation='horizontal'] &:dir(rtl) {
26
+ inset-inline-start: var(--active-item-right);
27
+ }
28
+
25
29
  @media (prefers-reduced-motion: reduce) {
26
30
  transition-duration: 0s;
27
31
  }