mirror of
https://github.com/hanzoai/gui.git
synced 2026-10-25 02:31:41 +00:00
This repo could never sync. There was NO merge-base with tamagui — 372 commits
here against 15,791 there, unrelated histories — because it began as a
copy-paste rebrand with a flattened layout. Every "sync" since was a hand
re-application that drifted, which is why the tree sat on 7.3.1 while upstream
shipped fixes we then rediscovered by hand.
This commit's PARENT IS TAMAGUI. A future sync is `git merge tama/main` then
`node scripts/rebrand.mjs` — a real merge, because the history is now shared.
174 packages: 166 upstream, our 8 restored (chrome, shell, telemetry, recipes,
get, font-geist-{sans,mono}, @hanzo/booker), bento-get gained. 170/170 build.
Our patches to files UPSTREAM ALSO OWNS are carried, which the package-level
delta missed and which was where the value actually was:
- useMedia's server snapshot (`initState ?? getMedia()`). Upstream still
returns undefined there, so every Tamagui Dialog kills a prerender — the
exact crash hanzo.app spent a day on.
- data-slot on web host nodes, absent upstream entirely.
Both applied ONTO upstream's newer files (it rewrote useMedia +150/-63 and
createComponent +160/-55), marked `PATCH (ours, carried across the transplant)`.
Seven traps are encoded in scripts/rebrand.mjs, each found by a gate:
skip itself and lockfiles; special-case the double-branded names in BOTH scoped
and bare form; map path strings, not just paths; drop a level for the flattened
group; check disk rather than a stale index.
Rust build artifacts are NOT committed. An earlier draft of this commit swept
apps/desktop/src-tauri/target/debug in via `git add -A` — 3,859 files including
a 272MB .a, over GitHub's 100MB cap, so the push could never have landed. They
are gitignored now.
Co-Authored-By: Hanzo Dev <[email protected]>
108 lines
3.0 KiB
TypeScript
108 lines
3.0 KiB
TypeScript
import { Adapt } from '@hanzogui/adapt'
|
|
import { getDefaultGuiConfig } from '@hanzogui/config-default'
|
|
import { GuiProvider, createGui } from '@hanzogui/core'
|
|
import { PortalProvider } from '@hanzogui/portal'
|
|
import { Select } from '@hanzogui/select'
|
|
import { Sheet } from '@hanzogui/sheet'
|
|
import TestRenderer, { act } from 'react-test-renderer'
|
|
import { describe, expect, test } from 'vitest'
|
|
|
|
const conf = createGui(getDefaultGuiConfig())
|
|
|
|
async function renderSelect(element: React.ReactElement) {
|
|
let rendered: TestRenderer.ReactTestRenderer | null = null
|
|
|
|
await act(async () => {
|
|
rendered = TestRenderer.create(
|
|
<GuiProvider config={conf} defaultTheme="light">
|
|
<PortalProvider shouldAddRootHost>{element}</PortalProvider>
|
|
</GuiProvider>
|
|
)
|
|
})
|
|
|
|
return rendered!
|
|
}
|
|
|
|
function hasDisplayNone(style: any) {
|
|
if (!style) return false
|
|
if (Array.isArray(style)) {
|
|
return style.some(hasDisplayNone)
|
|
}
|
|
return style.display === 'none'
|
|
}
|
|
|
|
function isHidden(node: TestRenderer.ReactTestInstance) {
|
|
let current: TestRenderer.ReactTestInstance | null = node
|
|
while (current) {
|
|
if (current.props.display === 'none' || hasDisplayNone(current.props.style)) {
|
|
return true
|
|
}
|
|
current = current.parent
|
|
}
|
|
return false
|
|
}
|
|
|
|
function visibleTextExists(rendered: TestRenderer.ReactTestRenderer, text: string) {
|
|
return (
|
|
rendered.root.findAll((node) => {
|
|
const children = node.props.children
|
|
const hasText = Array.isArray(children)
|
|
? children.includes(text)
|
|
: children === text
|
|
return hasText && !isHidden(node)
|
|
}).length > 0
|
|
)
|
|
}
|
|
|
|
describe('Select native content', () => {
|
|
test('does not render closed items through the native portal fallback', async () => {
|
|
const rendered = await renderSelect(
|
|
<Select value="">
|
|
<Select.Trigger>
|
|
<Select.Value placeholder="Search..." />
|
|
</Select.Trigger>
|
|
|
|
<Adapt when="sm">
|
|
<Sheet>
|
|
<Sheet.Frame>
|
|
<Adapt.Contents />
|
|
</Sheet.Frame>
|
|
<Sheet.Overlay />
|
|
</Sheet>
|
|
</Adapt>
|
|
|
|
<Select.Content>
|
|
<Select.Viewport>
|
|
<Select.Item index={0} value="apple">
|
|
<Select.ItemText>Apple</Select.ItemText>
|
|
</Select.Item>
|
|
</Select.Viewport>
|
|
</Select.Content>
|
|
</Select>
|
|
)
|
|
|
|
expect(visibleTextExists(rendered, 'Apple')).toBe(false)
|
|
})
|
|
|
|
test('renders the selected item label while closed', async () => {
|
|
const rendered = await renderSelect(
|
|
<Select value="apple">
|
|
<Select.Trigger>
|
|
<Select.Value placeholder="Search..." />
|
|
</Select.Trigger>
|
|
|
|
<Select.Content>
|
|
<Select.Viewport>
|
|
<Select.Item index={0} value="apple">
|
|
<Select.ItemText>Apple</Select.ItemText>
|
|
</Select.Item>
|
|
</Select.Viewport>
|
|
</Select.Content>
|
|
</Select>
|
|
)
|
|
|
|
expect(visibleTextExists(rendered, 'Apple')).toBe(true)
|
|
expect(visibleTextExists(rendered, 'apple')).toBe(false)
|
|
})
|
|
})
|