// createImage loads an image as a SolidJS 2.0 async value and returns an accessor
// for its GPU texture id. It handles fetch, decode, GPU upload, and cleanup for
// you. A string source is fetched; a Uint8Array is decoded directly. The texture
// carries its own pixel size, so <texture> needs no width/height to show it at
// natural size - pass them only to scale it.
//
// Reading img() suspends until ready, so read it inside a <Loading> boundary
// (this is the 2.0 async mechanic, not a manual undefined-signal + <Show>); a
// load failure surfaces to <Errored>. Pass an accessor (createImage(() => src()))
// to make the source reactive - the image reloads and the old texture is freed.
//
// The rule: createImage always suspends (needs <Loading>), because it is an
// async value. For bytes you already hold - a `with { type: "binary" }` import
// or anything in memory - skip it: decodeImage(bytes) + createTexture (both
// synchronous) build the texture with no boundary at all. See inline-image.tsx.
// createImage earns its async only when it fetches a string URL or swaps source
// reactively; decodeImage + createTexture are the primitives underneath.
//
// Raster vs vector: a texture has a fixed source resolution, so it softens when
// drawn larger than (displayed size x env.displayScale) on a hi-DPI display.
// Author raster at 2-3x the largest size you will draw it. When the render size
// is fluid or DPI varies, prefer a vector (svg.tsx / <d-path>) instead - it
// stays crisp at any size.
import { render, createImage, Loading } from "@solidrt/core"

function App() {
  let img = createImage("https://picsum.photos/seed/solidrt/400/300")

  return (
    <window alignItems="center" justifyContent="center">
      <Loading fallback={<text color="#888">loading...</text>}>
        <texture src={img()} />
      </Loading>
    </window>
  )
}

render(() => <App />)