@lovett/ui 0.0.11 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-RBYWGBQ2.js +2752 -0
- package/dist/chunk-RBYWGBQ2.js.map +1 -0
- package/dist/index.d.ts +5574 -57
- package/dist/index.js +21650 -11206
- package/dist/index.js.map +1 -1
- package/dist/rich-composer-impl-5NO443A6.js +1859 -0
- package/dist/rich-composer-impl-5NO443A6.js.map +1 -0
- package/dist/styles.css +1570 -0
- package/dist/tokens.css +112 -0
- package/package.json +8 -1
- package/src/__tests__/avatar.test.tsx +272 -0
- package/src/__tests__/bar-chart.test.tsx +809 -0
- package/src/__tests__/board.test.tsx +420 -0
- package/src/__tests__/chart-math.test.ts +922 -0
- package/src/__tests__/chart-series.test.ts +339 -0
- package/src/__tests__/code-block.test.tsx +134 -0
- package/src/__tests__/display-popover.test.tsx +195 -0
- package/src/__tests__/display-store.test.tsx +307 -0
- package/src/__tests__/donut-chart.test.tsx +397 -0
- package/src/__tests__/dropdown-menu.test.tsx +156 -2
- package/src/__tests__/filter-menu.test.tsx +175 -0
- package/src/__tests__/gauge-ring.test.tsx +233 -0
- package/src/__tests__/line-chart.test.tsx +612 -0
- package/src/__tests__/ranked-bars.test.tsx +343 -0
- package/src/__tests__/remark-underline.test.ts +194 -0
- package/src/__tests__/sortable.test.tsx +394 -0
- package/src/__tests__/sparkline.test.tsx +368 -0
- package/src/__tests__/stat-layer.test.tsx +271 -0
- package/src/__tests__/stat-strip.test.tsx +175 -0
- package/src/__tests__/status.test.tsx +293 -0
- package/src/__tests__/tabs.test.tsx +303 -0
- package/src/__tests__/token-shape.test.ts +132 -2
- package/src/avatar.tsx +352 -0
- package/src/bar-chart.tsx +1214 -0
- package/src/board.tsx +658 -0
- package/src/chart-frame.tsx +960 -0
- package/src/chart-legend.tsx +304 -0
- package/src/chart-tooltip.tsx +267 -0
- package/src/code-block.tsx +62 -8
- package/src/delta-chip.tsx +263 -0
- package/src/detail/__tests__/activity-pane.test.tsx +369 -0
- package/src/detail/__tests__/detail-chrome.test.tsx +134 -0
- package/src/detail/__tests__/detail-surface.test.tsx +529 -0
- package/src/detail/__tests__/field-row.test.tsx +357 -0
- package/src/detail/activity-pane.tsx +611 -0
- package/src/detail/calendar.tsx +355 -0
- package/src/detail/detail-divider.tsx +261 -0
- package/src/detail/detail-header.tsx +287 -0
- package/src/detail/detail-menu.tsx +254 -0
- package/src/detail/detail-surface.tsx +1110 -0
- package/src/detail/field-list.tsx +196 -0
- package/src/detail/field-row.tsx +1131 -0
- package/src/detail/index.ts +58 -0
- package/src/detail/segmented-choice.tsx +94 -0
- package/src/detail/types.ts +129 -0
- package/src/display-popover.tsx +487 -0
- package/src/display-store.tsx +301 -0
- package/src/donut-chart.tsx +988 -0
- package/src/dropdown-menu.tsx +290 -19
- package/src/filter-core/EXPORTS.md +85 -0
- package/src/filter-core/__tests__/columns.test.ts +159 -0
- package/src/filter-core/__tests__/faceting.test.ts +193 -0
- package/src/filter-core/__tests__/filter-fns.test.ts +519 -0
- package/src/filter-core/__tests__/operators.test.ts +235 -0
- package/src/filter-core/__tests__/state.test.ts +268 -0
- package/src/filter-core/__tests__/url.test.ts +350 -0
- package/src/filter-core/columns.ts +134 -0
- package/src/filter-core/date-utils.ts +38 -0
- package/src/filter-core/examples/task-filter-columns.ts +121 -0
- package/src/filter-core/faceting.ts +120 -0
- package/src/filter-core/filter-fns.ts +335 -0
- package/src/filter-core/index.ts +105 -0
- package/src/filter-core/operators.ts +433 -0
- package/src/filter-core/state.ts +280 -0
- package/src/filter-core/types.ts +247 -0
- package/src/filter-core/url.ts +261 -0
- package/src/filter-dropdown.tsx +12 -0
- package/src/filter-menu.tsx +649 -0
- package/src/floating-drawer.tsx +19 -1
- package/src/gauge-ring.tsx +435 -0
- package/src/hue.ts +52 -0
- package/src/index.ts +303 -0
- package/src/kbd.tsx +27 -4
- package/src/lib/chart.ts +866 -0
- package/src/lib/focus.ts +43 -1
- package/src/lib/layer-stack.ts +30 -3
- package/src/lib/remark-underline.ts +443 -0
- package/src/lib/series.ts +169 -0
- package/src/line-chart.tsx +1176 -0
- package/src/markdown.tsx +26 -7
- package/src/modal.tsx +42 -18
- package/src/progress-ledger.tsx +304 -0
- package/src/ranked-bars.tsx +386 -0
- package/src/segmented-pill.tsx +32 -9
- package/src/sortable.tsx +520 -1
- package/src/sparkline.tsx +416 -0
- package/src/stat-card.tsx +376 -0
- package/src/stat-strip.tsx +327 -0
- package/src/status.tsx +215 -0
- package/src/styles.css +1570 -0
- package/src/tabs.tsx +206 -25
- package/src/task-card.tsx +610 -0
- package/src/thread/__tests__/comment-body-hostile.test.tsx +331 -0
- package/src/thread/__tests__/comment-tree.test.ts +151 -0
- package/src/thread/__tests__/emoji.test.ts +187 -0
- package/src/thread/__tests__/fixtures/thread-fixture.ts +252 -0
- package/src/thread/__tests__/link-preview-source.test.ts +120 -0
- package/src/thread/__tests__/link-preview.test.tsx +600 -0
- package/src/thread/__tests__/markdown-format.test.ts +82 -0
- package/src/thread/__tests__/markdown-spec.test.ts +469 -0
- package/src/thread/__tests__/relative-time.test.ts +71 -0
- package/src/thread/__tests__/rich-composer.test.tsx +799 -0
- package/src/thread/__tests__/scroll-caret.test.ts +58 -0
- package/src/thread/__tests__/suggestion-list.test.tsx +648 -0
- package/src/thread/__tests__/thread-scroll-ownership.test.tsx +88 -0
- package/src/thread/__tests__/thread.test.tsx +742 -0
- package/src/thread/__tests__/use-attachments.test.tsx +679 -0
- package/src/thread/actions.tsx +196 -0
- package/src/thread/attachments.tsx +1071 -0
- package/src/thread/comment-body.tsx +148 -0
- package/src/thread/comment-tree.ts +182 -0
- package/src/thread/comment.tsx +967 -0
- package/src/thread/composer-footer.tsx +125 -0
- package/src/thread/composer.tsx +319 -0
- package/src/thread/emoji.ts +283 -0
- package/src/thread/index.ts +153 -0
- package/src/thread/link-preview.tsx +341 -0
- package/src/thread/markdown-format.ts +155 -0
- package/src/thread/markdown-spec.ts +754 -0
- package/src/thread/rail.tsx +372 -0
- package/src/thread/reactions.tsx +415 -0
- package/src/thread/relative-time.tsx +94 -0
- package/src/thread/rich-composer-impl.tsx +1601 -0
- package/src/thread/rich-composer.tsx +195 -0
- package/src/thread/scroll-caret.ts +37 -0
- package/src/thread/suggestion-list.tsx +182 -0
- package/src/thread/thread.tsx +718 -0
- package/src/thread/types.ts +232 -0
- package/src/thread/use-attachments.ts +598 -0
- package/src/thread/use-now.ts +73 -0
- package/src/thread/use-thread.ts +316 -0
- package/src/tokens.css +112 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The thread OWNS its scroll — the permanent fix for "the entire viewport is
|
|
3
|
+
* scrolling down" (owner, 2026-09-07).
|
|
4
|
+
*
|
|
5
|
+
* Three things have to be true at once, and they fail independently:
|
|
6
|
+
* 1. the section has a height CEILING that does not depend on the host
|
|
7
|
+
* (`max-block-size` with a viewport fallback) — otherwise an unbounded
|
|
8
|
+
* host lets it grow to content and scrolls the whole thread;
|
|
9
|
+
* 2. the body is the scroll region and the ROOT COMPOSER is outside it,
|
|
10
|
+
* after it — otherwise the composer scrolls away on a long thread;
|
|
11
|
+
* 3. the rich composer's editor has a ceiling too — a contenteditable with
|
|
12
|
+
* only a floor grows with every line typed.
|
|
13
|
+
*
|
|
14
|
+
* jsdom does no layout, so (1) and (3) are asserted against the stylesheet
|
|
15
|
+
* text — the same technique `token-shape.test.ts` uses — and (2) against the
|
|
16
|
+
* DOM order.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { readFileSync } from 'node:fs'
|
|
20
|
+
import { resolve } from 'node:path'
|
|
21
|
+
import { render, screen } from '@testing-library/react'
|
|
22
|
+
import { describe, expect, it } from 'vitest'
|
|
23
|
+
import { Thread } from '../thread'
|
|
24
|
+
import { THREAD_FIXTURE, FIXTURE_NOW } from './fixtures/thread-fixture'
|
|
25
|
+
|
|
26
|
+
// vitest runs each package from its own directory (also under `pnpm -r`), so
|
|
27
|
+
// the stylesheet is cwd-relative — same approach as token-shape.test.ts.
|
|
28
|
+
const css = readFileSync(resolve(process.cwd(), 'src/styles.css'), 'utf8')
|
|
29
|
+
|
|
30
|
+
function block(selector: string): string {
|
|
31
|
+
// Anchored at LINE START: a bare indexOf matched the `.my-drawer .ds-thread { … }`
|
|
32
|
+
// example inside an earlier comment and read that as the rule.
|
|
33
|
+
const escaped = selector.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
34
|
+
const match = new RegExp(`^${escaped} \\{`, 'm').exec(css)
|
|
35
|
+
if (match === null) throw new Error(`no rule for ${selector}`)
|
|
36
|
+
const start = match.index
|
|
37
|
+
return css.slice(start, css.indexOf('\n}', start))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
describe('thread scroll ownership', () => {
|
|
41
|
+
it('(1) .ds-thread has a viewport-relative height ceiling with a host override', () => {
|
|
42
|
+
const rule = block('.ds-thread')
|
|
43
|
+
expect(rule).toMatch(/--thread-max-block-size:\s*100dvh/)
|
|
44
|
+
expect(rule).toMatch(/max-block-size:\s*var\(--thread-max-block-size\)/)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('(2) the root composer sits AFTER the scroll region, not inside it', () => {
|
|
48
|
+
render(
|
|
49
|
+
<Thread comments={THREAD_FIXTURE} now={FIXTURE_NOW} onSubmit={() => undefined} />,
|
|
50
|
+
)
|
|
51
|
+
const section = screen.getByRole('region', { name: 'Comments' })
|
|
52
|
+
const scroller = section.querySelector('.ds-thread__scroll')
|
|
53
|
+
expect(scroller).not.toBeNull()
|
|
54
|
+
expect(scroller?.className).toMatch(/\boverflow-y-auto\b/)
|
|
55
|
+
expect(scroller?.className).toMatch(/\bmin-h-0\b/)
|
|
56
|
+
const composer = screen.getByRole('textbox', { name: /comment/i })
|
|
57
|
+
// Outside the scroller…
|
|
58
|
+
expect(scroller?.contains(composer)).toBe(false)
|
|
59
|
+
// …and after it in document order, so it is pinned below, never above.
|
|
60
|
+
expect(
|
|
61
|
+
scroller!.compareDocumentPosition(composer) & Node.DOCUMENT_POSITION_FOLLOWING,
|
|
62
|
+
).toBeTruthy()
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
it('(3a) both scroll regions CONTAIN their overscroll', () => {
|
|
66
|
+
// Ceilings decide where a scrollbar appears; containment decides whether a
|
|
67
|
+
// gesture that reaches the end of one leaks into the page behind it. The
|
|
68
|
+
// Enter-key path is handled in JS (handleScrollToSelection); this is the
|
|
69
|
+
// wheel/touch path, and both are needed.
|
|
70
|
+
expect(block('.ds-thread-rich-composer .ProseMirror')).toMatch(
|
|
71
|
+
/overscroll-behavior:\s*contain/,
|
|
72
|
+
)
|
|
73
|
+
render(
|
|
74
|
+
<Thread comments={THREAD_FIXTURE} now={FIXTURE_NOW} onSubmit={() => undefined} />,
|
|
75
|
+
)
|
|
76
|
+
const scroller = screen
|
|
77
|
+
.getByRole('region', { name: 'Comments' })
|
|
78
|
+
.querySelector('.ds-thread__scroll')
|
|
79
|
+
expect(scroller?.className).toMatch(/\boverscroll-contain\b/)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('(3) the rich editor has a ceiling and scrolls internally past it', () => {
|
|
83
|
+
const rule = block('.ds-thread-rich-composer .ProseMirror')
|
|
84
|
+
expect(rule).toMatch(/max-block-size:\s*calc\(var\(--composer-max-rows\)/)
|
|
85
|
+
expect(block('.ds-thread-rich-composer')).toMatch(/--composer-max-rows:\s*12/)
|
|
86
|
+
expect(rule).toMatch(/overflow-y:\s*auto/)
|
|
87
|
+
})
|
|
88
|
+
})
|