diff --git a/examples/dashboard/vite.config.ts b/examples/dashboard/vite.config.ts
index dc9fef9d..9a823cca 100644
--- a/examples/dashboard/vite.config.ts
+++ b/examples/dashboard/vite.config.ts
@@ -2,8 +2,6 @@ import { defineConfig } from 'vite'
import path from 'path'
import react from '@vitejs/plugin-react'
-console.log(path.resolve(__dirname, '../../packages/uikit'))
-
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
diff --git a/examples/lucide/vite.config.ts b/examples/lucide/vite.config.ts
index dc9fef9d..9a823cca 100644
--- a/examples/lucide/vite.config.ts
+++ b/examples/lucide/vite.config.ts
@@ -2,8 +2,6 @@ import { defineConfig } from 'vite'
import path from 'path'
import react from '@vitejs/plugin-react'
-console.log(path.resolve(__dirname, '../../packages/uikit'))
-
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
diff --git a/examples/market/index.html b/examples/market/index.html
new file mode 100644
index 00000000..cf853ae4
--- /dev/null
+++ b/examples/market/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
+
diff --git a/examples/market/package.json b/examples/market/package.json
new file mode 100644
index 00000000..8df37172
--- /dev/null
+++ b/examples/market/package.json
@@ -0,0 +1,18 @@
+{
+ "type": "module",
+ "dependencies": {
+ "@react-three/drei": "^9.96.1",
+ "@react-three/fiber": "^8.15.13",
+ "@react-three/postprocessing": "^2.16.0",
+ "@react-three/uikit": "workspace:^",
+ "@react-three/uikit-lucide": "workspace:^",
+ "@types/three": "^0.160.0",
+ "r3f-perf": "^7.1.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "three": "^0.160.0"
+ },
+ "scripts": {
+ "dev": "vite --host"
+ }
+}
diff --git a/examples/market/src/App.tsx b/examples/market/src/App.tsx
new file mode 100644
index 00000000..820e21a3
--- /dev/null
+++ b/examples/market/src/App.tsx
@@ -0,0 +1,122 @@
+import { Environment, OrbitControls } from '@react-three/drei'
+import { Canvas } from '@react-three/fiber'
+import { EffectComposer, TiltShift2 } from '@react-three/postprocessing'
+import { Root, Container, Image, Text, Fullscreen, DefaultProperties } from '@react-three/uikit'
+import { PlusCircle } from '@react-three/uikit-lucide'
+import { DefaultColors, colors } from '@/defaults.js'
+import { DialogAnchor } from '@/dialog.js'
+import { Tabs, TabsList, TabsContent, TabsTrigger } from '@/tabs.js'
+import { Separator } from '@/separator.js'
+import { Button } from '@/button.js'
+import { AlbumArtwork } from './components/album-artwork'
+import { listenNowAlbums, madeForYouAlbums } from './data/albums'
+import { Sidebar } from './components/sidebar'
+import { playlists } from './data/playlists'
+import { Menu } from './components/menu'
+
+export default function App() {
+ return (
+
+ )
+}
+
+export function MarketPage() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ Models
+
+
+ HDRIS
+
+
+ Materials
+
+
+
+
+
+
+
+
+
+
+ Trending
+
+
+ Top picks for you. Updated daily.
+
+
+
+
+
+ {listenNowAlbums.map((album) => (
+
+ ))}
+
+
+
+ Made By You
+
+
+ Your personal models.
+
+
+
+
+ {madeForYouAlbums.map((album) => (
+
+ ))}
+
+
+
+
+
+
+ )
+}
diff --git a/examples/market/src/components/album-artwork.tsx b/examples/market/src/components/album-artwork.tsx
new file mode 100644
index 00000000..7f95aecc
--- /dev/null
+++ b/examples/market/src/components/album-artwork.tsx
@@ -0,0 +1,35 @@
+import { Container, Text, Image } from '@react-three/uikit'
+import { Album } from '../data/albums.js'
+import { ComponentPropsWithoutRef } from 'react'
+import { colors } from '@/defaults.js'
+
+export function AlbumArtwork({
+ album,
+ aspectRatio = 'portrait',
+ width,
+ height,
+ ...props
+}: {
+ album: Album
+ aspectRatio?: 'portrait' | 'square'
+} & Omit, 'aspectRatio'>) {
+ return (
+
+
+
+
+ {album.name}
+
+
+ {album.artist}
+
+
+
+ )
+}
diff --git a/examples/market/src/components/menu.tsx b/examples/market/src/components/menu.tsx
new file mode 100644
index 00000000..3c7719d8
--- /dev/null
+++ b/examples/market/src/components/menu.tsx
@@ -0,0 +1,39 @@
+import { Menubar, MenubarMenu, MenubarTrigger } from '@/menubar.js'
+import { SvgIconFromText, Text } from '@react-three/uikit'
+
+export function Menu() {
+ return (
+
+
+
+
+
+
+
+
+ File
+
+
+
+
+ Edit
+
+
+
+
+ View
+
+
+
+
+ Account
+
+
+
+ )
+}
diff --git a/examples/market/src/components/sidebar.tsx b/examples/market/src/components/sidebar.tsx
new file mode 100644
index 00000000..c08c6ae2
--- /dev/null
+++ b/examples/market/src/components/sidebar.tsx
@@ -0,0 +1,92 @@
+import { Container, Text } from '@react-three/uikit'
+import { Button } from '@/button.js'
+import { Playlist } from '../data/playlists.js'
+import { ComponentPropsWithoutRef } from 'react'
+import { Eclipse, Package, Star, User, Image as ImageIcon } from '@react-three/uikit-lucide'
+
+export function Sidebar({
+ playlists,
+ ...props
+}: ComponentPropsWithoutRef & {
+ playlists: Playlist[]
+}) {
+ return (
+
+
+
+
+ Discover
+
+
+
+
+
+
+
+
+
+ Collections
+
+
+
+
+
+
+
+
+
+
+
+ Favorits
+
+
+ {playlists?.map((playlist, i) => (
+
+ ))}
+
+
+
+
+ )
+}
diff --git a/examples/market/src/data/albums.ts b/examples/market/src/data/albums.ts
new file mode 100644
index 00000000..b9ab3613
--- /dev/null
+++ b/examples/market/src/data/albums.ts
@@ -0,0 +1,61 @@
+export interface Album {
+ name: string
+ artist: string
+ cover: string
+}
+
+export const listenNowAlbums: Album[] = [
+ {
+ name: 'React Rendezvous',
+ artist: 'Ethan Byte',
+ cover: 'https://images.unsplash.com/photo-1611348586804-61bf6c080437?w=300&dpr=2&q=80',
+ },
+ {
+ name: 'Async Awakenings',
+ artist: 'Nina Netcode',
+ cover: 'https://images.unsplash.com/photo-1468817814611-b7edf94b5d60?w=300&dpr=2&q=80',
+ },
+ {
+ name: 'The Art of Reusability',
+ artist: 'Lena Logic',
+ cover: 'https://images.unsplash.com/photo-1528143358888-6d3c7f67bd5d?w=300&dpr=2&q=80',
+ },
+ {
+ name: 'Stateful Symphony',
+ artist: 'Beth Binary',
+ cover: 'https://images.unsplash.com/photo-1490300472339-79e4adc6be4a?w=300&dpr=2&q=80',
+ },
+]
+
+export const madeForYouAlbums: Album[] = [
+ {
+ name: 'Thinking Components',
+ artist: 'Lena Logic',
+ cover: 'https://images.unsplash.com/photo-1615247001958-f4bc92fa6a4a?w=300&dpr=2&q=80',
+ },
+ {
+ name: 'Functional Fury',
+ artist: 'Beth Binary',
+ cover: 'https://images.unsplash.com/photo-1513745405825-efaf9a49315f?w=300&dpr=2&q=80',
+ },
+ {
+ name: 'React Rendezvous',
+ artist: 'Ethan Byte',
+ cover: 'https://images.unsplash.com/photo-1614113489855-66422ad300a4?w=300&dpr=2&q=80',
+ },
+ {
+ name: 'Stateful Symphony',
+ artist: 'Beth Binary',
+ cover: 'https://images.unsplash.com/photo-1446185250204-f94591f7d702?w=300&dpr=2&q=80',
+ },
+ {
+ name: 'Async Awakenings',
+ artist: 'Nina Netcode',
+ cover: 'https://images.unsplash.com/photo-1468817814611-b7edf94b5d60?w=300&dpr=2&q=80',
+ },
+ {
+ name: 'The Art of Reusability',
+ artist: 'Lena Logic',
+ cover: 'https://images.unsplash.com/photo-1490300472339-79e4adc6be4a?w=300&dpr=2&q=80',
+ },
+]
diff --git a/examples/market/src/data/playlists.ts b/examples/market/src/data/playlists.ts
new file mode 100644
index 00000000..d395ac4c
--- /dev/null
+++ b/examples/market/src/data/playlists.ts
@@ -0,0 +1,16 @@
+export type Playlist = (typeof playlists)[number]
+
+export const playlists = [
+ 'Recently Added',
+ 'Recently Played',
+ 'Top Songs',
+ 'Top Albums',
+ 'Top Artists',
+ 'Logic Discography',
+ 'Bedtime Beats',
+ 'Feeling Happy',
+ 'I miss Y2K Pop',
+ 'Runtober',
+ 'Mellow Days',
+ 'Eminem Essentials',
+]
diff --git a/examples/market/src/index.tsx b/examples/market/src/index.tsx
new file mode 100644
index 00000000..da84256b
--- /dev/null
+++ b/examples/market/src/index.tsx
@@ -0,0 +1,10 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import './styles.css'
+import App from './App'
+
+createRoot(document.getElementById('root')!).render(
+
+
+ ,
+)
diff --git a/examples/market/src/styles.css b/examples/market/src/styles.css
new file mode 100644
index 00000000..e69de29b
diff --git a/examples/market/tsconfig.json b/examples/market/tsconfig.json
new file mode 100644
index 00000000..38ab47e6
--- /dev/null
+++ b/examples/market/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "paths": {
+ "@/*": ["../../packages/kits/default/*"]
+ }
+ }
+}
diff --git a/examples/market/vite.config.ts b/examples/market/vite.config.ts
new file mode 100644
index 00000000..9a823cca
--- /dev/null
+++ b/examples/market/vite.config.ts
@@ -0,0 +1,14 @@
+import { defineConfig } from 'vite'
+import path from 'path'
+import react from '@vitejs/plugin-react'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ resolve: {
+ alias: [
+ { find: '@', replacement: path.resolve(__dirname, '../../packages/kits/default') },
+ { find: '@react-three/uikit', replacement: path.resolve(__dirname, '../../packages/uikit/src/index.ts') },
+ ],
+ },
+})
diff --git a/examples/uikit/package.json b/examples/uikit/package.json
index 3142e866..44d5ad81 100644
--- a/examples/uikit/package.json
+++ b/examples/uikit/package.json
@@ -11,5 +11,8 @@
},
"scripts": {
"dev": "vite --host"
+ },
+ "devDependencies": {
+ "@types/three": "^0.160.0"
}
}
diff --git a/examples/uikit/src/App.tsx b/examples/uikit/src/App.tsx
index 735248af..883605d3 100644
--- a/examples/uikit/src/App.tsx
+++ b/examples/uikit/src/App.tsx
@@ -12,8 +12,11 @@ import {
Image,
Fullscreen,
} from '@react-three/uikit'
+import { RenderTexture } from '@react-three/drei'
+import { Texture } from 'three'
export default function App() {
+ const [texture, setTexture] = useState(null)
const [show, setShow] = useState(false)
const s = useMemo(() => signal(5), [])
const x = useMemo(() => signal('red'), [])
@@ -24,6 +27,9 @@ export default function App() {
+
+
+
+
{
t.value += 'X'
@@ -50,18 +57,6 @@ export default function App() {
>
{t}
- {show ? (
-
- (s.value += 10)}
- backgroundColor="yellow"
- width={300}
- minHeight={300}
- height={300}
- />
-
-
- ) : undefined}
(x.value = hover ? 'yellow' : undefined)}
backgroundColor={x}
@@ -96,7 +91,6 @@ export default function App() {
Hello world
+
+ {show ? (
+
+ (s.value += 10)}
+ backgroundColor="yellow"
+ width={300}
+ minHeight={300}
+ height={300}
+ />
+
+
+ ) : undefined}
)
diff --git a/examples/uikit/vite.config.ts b/examples/uikit/vite.config.ts
index dc9fef9d..9a823cca 100644
--- a/examples/uikit/vite.config.ts
+++ b/examples/uikit/vite.config.ts
@@ -2,8 +2,6 @@ import { defineConfig } from 'vite'
import path from 'path'
import react from '@vitejs/plugin-react'
-console.log(path.resolve(__dirname, '../../packages/uikit'))
-
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
diff --git a/packages/kits/default/menu-bar.tsx b/packages/kits/default/menubar.tsx
similarity index 80%
rename from packages/kits/default/menu-bar.tsx
rename to packages/kits/default/menubar.tsx
index 30b2c70c..92b37a73 100644
--- a/packages/kits/default/menu-bar.tsx
+++ b/packages/kits/default/menubar.tsx
@@ -1,13 +1,47 @@
-'use client'
+import { Container, DefaultProperties } from '@react-three/uikit'
+import { ComponentPropsWithoutRef, ReactNode } from 'react'
+import { colors } from './defaults'
-import * as React from 'react'
-import * as MenubarPrimitive from '@radix-ui/react-menubar'
-import { Check, ChevronRight, Circle } from 'lucide-react'
-
-import { cn } from '@/lib/utils'
+export function MenubarMenu({ children }: { children?: ReactNode }) {
+ return <>{children}>
+}
-const MenubarMenu = MenubarPrimitive.Menu
+export function Menubar(props: ComponentPropsWithoutRef) {
+ return (
+
+ )
+}
+export function MenubarTrigger({ children, ...props }: ComponentPropsWithoutRef) {
+ //TODO: data-[state=open]:bg-accent data-[state=open]:text-accent-foreground
+ return (
+
+
+ {children}
+
+
+ )
+}
+/*
const MenubarGroup = MenubarPrimitive.Group
const MenubarPortal = MenubarPrimitive.Portal
@@ -16,33 +50,6 @@ const MenubarSub = MenubarPrimitive.Sub
const MenubarRadioGroup = MenubarPrimitive.RadioGroup
-const Menubar = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-Menubar.displayName = MenubarPrimitive.Root.displayName
-
-const MenubarTrigger = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName
-
const MenubarSubTrigger = React.forwardRef<
React.ElementRef,
React.ComponentPropsWithoutRef & {
@@ -188,22 +195,4 @@ const MenubarShortcut = ({ className, ...props }: React.HTMLAttributes
}
MenubarShortcut.displayname = 'MenubarShortcut'
-
-export {
- Menubar,
- MenubarMenu,
- MenubarTrigger,
- MenubarContent,
- MenubarItem,
- MenubarSeparator,
- MenubarLabel,
- MenubarCheckboxItem,
- MenubarRadioGroup,
- MenubarRadioItem,
- MenubarPortal,
- MenubarSubContent,
- MenubarSubTrigger,
- MenubarGroup,
- MenubarSub,
- MenubarShortcut,
-}
+*/
diff --git a/packages/kits/default/package.json b/packages/kits/default/package.json
index 57d3fda7..d2e676bc 100644
--- a/packages/kits/default/package.json
+++ b/packages/kits/default/package.json
@@ -1,8 +1,5 @@
{
- "scripts": {
- "fix:prettier": "prettier --write .",
- "fix:eslint": "eslint ./**/*.tsx --fix"
- },
+ "scripts": {},
"devDependencies": {
"@preact/signals-core": "^1.5.1",
"@react-three/fiber": "^8.15.13",
diff --git a/packages/uikit/src/components/image.tsx b/packages/uikit/src/components/image.tsx
index ed9c4854..3daaf972 100644
--- a/packages/uikit/src/components/image.tsx
+++ b/packages/uikit/src/components/image.tsx
@@ -73,7 +73,7 @@ const materialPropertyTransformation: PropertyTransformation = (key, value, hasP
export const Image = forwardRef<
ComponentInternals,
ImageProperties & {
- src: string | Signal
+ src?: string | Signal | Texture | Signal
materialClass?: MaterialClass
zIndexOffset?: ZIndexOffset
} & EventHandlers &
@@ -89,7 +89,8 @@ export const Image = forwardRef<
if (tex == null) {
return undefined
}
- return tex.image.width / tex.image.height
+ const image = tex.source.data as { width: number; height: number }
+ return image.width / image.height
}),
[texture],
)
@@ -227,9 +228,15 @@ function transformInsideBorder(borderInset: Signal, size: Signal {
texture.colorSpace = SRGBColorSpace
texture.matrixAutoUpdate = false
diff --git a/packages/uikit/src/components/input.tsx b/packages/uikit/src/components/input.tsx
index 2e6f6457..5b7f8f40 100644
--- a/packages/uikit/src/components/input.tsx
+++ b/packages/uikit/src/components/input.tsx
@@ -32,7 +32,7 @@ import { useRootGroupRef, useSignalEffect } from '../utils.js'
import { useApplyResponsiveProperties } from '../responsive.js'
import { Group } from 'three'
import { ElementType, ZIndexOffset, useOrderInfo } from '../order.js'
-
+/*
export type TextProperties = WithConditionals<
WithClasses<
WithAllAliases>
@@ -242,3 +242,4 @@ export function useHtmlInputElement(
useEffect(() => () => element.remove(), [element])
return element
}
+*/
diff --git a/packages/uikit/src/components/root.tsx b/packages/uikit/src/components/root.tsx
index f1ec760d..6d0660cc 100644
--- a/packages/uikit/src/components/root.tsx
+++ b/packages/uikit/src/components/root.tsx
@@ -85,8 +85,8 @@ export const Root = forwardRef<
ScrollListeners
>((properties, ref) => {
const collection = createCollection()
- const renderer = useThree((state) => state.gl)
-
+ const renderer = useThree((state) => state.gl)
+
useEffect(() => patchRenderOrder(renderer), [renderer])
const { sizeX, sizeY } = properties
const [precision, pixelSize] = useMemo(
diff --git a/packages/uikit/src/flex/node.ts b/packages/uikit/src/flex/node.ts
index 35db000b..fbd84e81 100644
--- a/packages/uikit/src/flex/node.ts
+++ b/packages/uikit/src/flex/node.ts
@@ -259,7 +259,12 @@ export class FlexNode implements WithImmediateProperties {
updateVector2Signal(this.scrollable, false, false)
}
- return [x + Math.max(width, maxContentWidth), y + Math.max(height, maxContentHeight)]
+ const overflowVisible = this.overflow.value === OVERFLOW_VISIBLE
+
+ return [
+ x + Math.max(width, overflowVisible ? maxContentWidth : 0),
+ y + Math.max(height, overflowVisible ? maxContentHeight : 0),
+ ]
}
addLayoutChangeListener(listener: () => void) {
diff --git a/packages/uikit/src/index.ts b/packages/uikit/src/index.ts
index 50cc4d99..e8fc20ba 100644
--- a/packages/uikit/src/index.ts
+++ b/packages/uikit/src/index.ts
@@ -7,4 +7,4 @@ export type { LayoutListeners, ViewportListeners } from './components/utils.js'
export type { ScrollListeners } from './scroll.js'
export type { AllOptionalProperties } from './properties/default.js'
export { DefaultProperties } from './properties/default.js'
-export * from './components/index.js'
\ No newline at end of file
+export * from './components/index.js'
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d32f319c..ef27d84c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -168,6 +168,39 @@ importers:
specifier: ^18.2.0
version: 18.2.0(react@18.2.0)
+ examples/market:
+ dependencies:
+ '@react-three/drei':
+ specifier: ^9.96.1
+ version: 9.96.1(@react-three/fiber@8.15.13)(@types/react@18.2.47)(@types/three@0.160.0)(react-dom@18.2.0)(react@18.2.0)(three@0.160.0)
+ '@react-three/fiber':
+ specifier: ^8.15.13
+ version: 8.15.13(react-dom@18.2.0)(react@18.2.0)(three@0.160.0)
+ '@react-three/postprocessing':
+ specifier: ^2.16.0
+ version: 2.16.0(@react-three/fiber@8.15.13)(@types/three@0.160.0)(react@18.2.0)(three@0.160.0)
+ '@react-three/uikit':
+ specifier: workspace:^
+ version: link:../../packages/uikit
+ '@react-three/uikit-lucide':
+ specifier: workspace:^
+ version: link:../../packages/icons/lucide
+ '@types/three':
+ specifier: ^0.160.0
+ version: 0.160.0
+ r3f-perf:
+ specifier: ^7.1.2
+ version: 7.1.2(@react-three/fiber@8.15.13)(@types/react@18.2.47)(@types/three@0.160.0)(react-dom@18.2.0)(react@18.2.0)(three@0.160.0)
+ react:
+ specifier: ^18.2.0
+ version: 18.2.0
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.2.0(react@18.2.0)
+ three:
+ specifier: ^0.160.0
+ version: 0.160.0
+
examples/uikit:
dependencies:
'@preact/signals-core':
@@ -191,6 +224,10 @@ importers:
three:
specifier: ^0.160.0
version: 0.160.0
+ devDependencies:
+ '@types/three':
+ specifier: ^0.160.0
+ version: 0.160.0
packages/fonts:
dependencies: