@tangle-network/ui 11.51.0 → 11.51.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @tangle-network/ui
2
2
 
3
+ ## 11.51.1
4
+
5
+ ### Patch Changes
6
+
7
+ - dfdfc77: Keep streamed blockquotes stable under host typography styles by suppressing generated quotation marks. Explicit quotation marks in Markdown content remain visible.
8
+
3
9
  ## 11.51.0
4
10
 
5
11
  ### Minor Changes
@@ -166,7 +166,7 @@ function MarkdownImage({ node: _node, src, alt, className, ...props }) {
166
166
  */
167
167
  const Markdown = memo(({ children, className, urlTransform, linkChip }) => {
168
168
  return /* @__PURE__ */ jsx("div", {
169
- className: cn("tangle-prose max-w-none text-sm", className),
169
+ className: cn("tangle-prose max-w-none text-sm [&_blockquote_p]:before:content-none [&_blockquote_p]:after:content-none", className),
170
170
  children: /* @__PURE__ */ jsx(LinkChipContext.Provider, {
171
171
  value: linkChip,
172
172
  children: /* @__PURE__ */ jsx(ReactMarkdown, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/ui",
3
- "version": "11.51.0",
3
+ "version": "11.51.1",
4
4
  "description": "Generic React UI components for Tangle products — primitives, chat, run, files, editor, markdown.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -166,7 +166,7 @@
166
166
  "peerDependencies": {
167
167
  "@hocuspocus/provider": ">=2.15.0 <5.0.0",
168
168
  "@nanostores/react": ">=0.8.4 <3.0.0",
169
- "@tangle-network/brand": "^1.31.0",
169
+ "@tangle-network/brand": "^1.31.1",
170
170
  "@tiptap/core": ">=3.20.4 <4.0.0",
171
171
  "@tiptap/extension-collaboration": ">=3.20.4 <4.0.0",
172
172
  "@tiptap/extension-collaboration-caret": ">=3.7.0 <4.0.0",
@@ -1,4 +1,5 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react'
2
+ import { useEffect, useState } from 'react'
2
3
  import { Markdown } from './markdown'
3
4
  import { CodeBlock, CopyButton } from './code-block'
4
5
  import { codePresentation } from '../lib/code-presentation'
@@ -11,7 +12,7 @@ const markdownMeta: Meta<typeof Markdown> = {
11
12
  parameters: { layout: 'centered', backgrounds: { default: 'dark' } },
12
13
  decorators: [
13
14
  (Story) => (
14
- <div className="w-[680px] rounded-xl bg-card p-6 text-foreground">
15
+ <div className="w-[680px] max-w-full rounded-xl bg-card p-6 text-foreground">
15
16
  <Story />
16
17
  </div>
17
18
  ),
@@ -262,3 +263,33 @@ export const CodeBlockLight: Story = {
262
263
  </div>
263
264
  ),
264
265
  }
266
+
267
+
268
+ /** Host typography must not add a moving closing quote to streamed text. */
269
+ function StreamingBlockquoteFixture() {
270
+ const text = '> **A researcher collects the evidence and a writer prepares the draft.**\n> You decide when the work leaves the workspace. Each person sees the source, the proposed action and the result before approving it.'
271
+ const [length, setLength] = useState(0)
272
+ useEffect(() => {
273
+ let interval: ReturnType<typeof setInterval>
274
+ const delay = setTimeout(() => {
275
+ let shown = 0
276
+ interval = setInterval(() => {
277
+ shown = Math.min(shown + 4, text.length); setLength(shown)
278
+ if (shown === text.length) clearInterval(interval)
279
+ }, 30)
280
+ }, 1500)
281
+ return () => { clearTimeout(delay); clearInterval(interval) }
282
+ }, [])
283
+ return <div className="streaming-blockquote-fixture" data-stream-length={length} data-stream-complete={length === text.length}>
284
+ <style>{`@layer base {
285
+ .streaming-blockquote-fixture blockquote p::before { content: open-quote; }
286
+ .streaming-blockquote-fixture blockquote p::after { content: close-quote; }
287
+ }`}</style>
288
+ <Markdown>{text.slice(0, length)}</Markdown>
289
+ </div>
290
+ }
291
+
292
+ export const StreamingBlockquote: Story = {
293
+ parameters: { layout: 'fullscreen' },
294
+ render: () => <StreamingBlockquoteFixture />,
295
+ }
@@ -240,7 +240,7 @@ export interface MarkdownProps {
240
240
  export const Markdown = memo(({ children, className, urlTransform, linkChip }: MarkdownProps) => {
241
241
  return (
242
242
  <div
243
- className={cn("tangle-prose max-w-none text-sm", className)}
243
+ className={cn("tangle-prose max-w-none text-sm [&_blockquote_p]:before:content-none [&_blockquote_p]:after:content-none", className)}
244
244
  >
245
245
  <LinkChipContext.Provider value={linkChip}>
246
246
  <ReactMarkdown