in
src/collections/audio.tsI have:
import type { CollectionConfig } from "payload"
export const Audios: CollectionConfig = {
slug: "audios",
upload: {
mimeTypes: ["audio/ogg"],
staticDir: "data/audio"
},
fields: [
...
{
name: "fft_data",
type: "json",
required: true,
admin: {
components: {
Field: "@components/fftdata#FFTDataComponent"
}
}
}
]
}And my component is:
src/components/fftdata.tsx"use client"
export const FFTDataComponent: JSONFieldClientComponent = props => {...}in my
tsconfig.jsonI defined
@componentsas:
{
"compilerOptions": {
//...
"paths": {
"@/*": [
"./src/*"
],
"@payload-config": [
"./src/payload.config.ts"
],
"@components": [
"./src/components/"
]
},
//...What am I doing wrong? I run
pnpm generate:importmapbefore
pnpm dev, but get this import issue.
Hey
@247020304507863040
Two things:
1. Looks like you're using visual studio code - can you try just ctrl + clicking onto the component path to see if vscode takes you to the right file
2. Can you share your package.json
For #1 try in the importmap where it imports the component
wrong assumption, I'm using neovim :p
package.json{
"name": "@nuphory/backend",
"version": "1.0.0",
"description": "A blank template to get started with Payload 3.0",
"license": "MIT",
"type": "module",
"exports": {
".": {
"import": "./src/index.ts",
"types": "./src/index.ts",
"default": "./src/index.ts"
}
},
"scripts": {
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
"dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
"devsafe": "rm -rf .next && cross-env NODE_OPTIONS=--no-deprecation next dev",
"generate:importmap": "cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap",
"generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
"fmt": "biome format --write",
"payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
},
"dependencies": {
"@euterpe.js/visualizer": "^1.1.1",
"@payloadcms/db-sqlite": "3.33.0",
"@payloadcms/next": "3.33.0",
"@payloadcms/payload-cloud": "3.33.0",
"@payloadcms/richtext-lexical": "3.33.0",
"cross-env": "^7.0.3",
"graphql": "^16.8.1",
"next": "15.3.0",
"payload": "3.33.0",
"react": "19.1.0",
"react-dom": "19.1.0",
"sharp": "0.32.6"
},
"devDependencies": {
"@eslint/eslintrc": "^3.2.0",
"@types/node": "^22.5.4",
"@types/react": "19.1.0",
"@types/react-dom": "19.1.2",
"eslint": "^9.16.0",
"eslint-config-next": "15.3.0",
"prettier": "^3.4.2",
"typescript": "5.7.3"
},
}I don't think I can go to definition on import path, so I'll try to import it manually and assign it
import type { CollectionConfig } from "payload"
import { FFTDataComponent } from "@/components/fftdata"
export const Audios: CollectionConfig = {
//...
fields: [
//...
{
name: "fft_data",
type: "json",
required: true,
admin: {
components: {
Field: FFTDataComponent,
}
}
}
]
}this creates error:
ts: Type 'JSONFieldClientComponent' is not assignable to type '(CustomComponent & PayloadComponent<FieldClientComponent | FieldServerComponent>) | undefined'.
Type 'ComponentClass<JSONFieldBaseClientProps & { readonly field: Omit<JSONFieldClient, "type"> & Partial<Pick<JSONFieldClient, "type">>; } & Omit<...>, any>' is not assignable to type '(CustomComponent & PayloadComponent<FieldClientComponent | FieldServerComponent>) | undefined'.
TypeScript Error Translation(s):
• I was expecting a type matching '(CustomComponent & PayloadComponent<FieldClientComponent | FieldServerComponent>) | undefined', but instead you passed 'JSONFieldClientComponent'.
• I was expecting a type matching '(CustomComponent & PayloadComponent<FieldClientComponent | FieldServerComponent>) | undefined', but instead you passed 'ComponentClass<JSONFieldBaseClientProps & { readonly field: Omit<JSONFieldClient, "type"> & Partial<Pick<JSONFieldClient, "type">>; } & Omit<...>, any>'.
[2322]so prolly not meant to be used this way
{
name: "fft_data",
type: "json",
required: true,
admin: {
components: {
Field: FFTDataComponent,
}
}
}This is wrong
Should be a path to the component from the root
Try without using
@{
name: "fft_data",
type: "json",
required: true,
admin: {
components: {
Field: "/components/fftdata#FFTDataComponent"
}
}
}By root I mean wherever your payload.config.ts is
ahaa I got it to import I think
not sure what this means but it seems to have imported with
Field: "src/components/fftdata#FFTDataComponent"Ok, nice, clear your importmap and regenerate it
Might be a good idea to delete .next folder
Also, you are calling useField but you haven't installed
@payloadcms/uiokay deleted .next, pnpm i
@967091941873426493/ui (lsp didn't complain it's not there and knew the types, weird), epmtied importMap.js, pnpm generate:importmap, pnpm dev aaand
still
It knew the types and didn't complain probably because the export is threaded through the
payloadpackage I think
Did you install
uiversion 3.33.0 to match the rest of your payload versions?
Payload deps need to be on the same version
pnpm seems to have done that for me, but forced it manually just in case. Still doesn't work
Can you share the component code
useFieldis imported through
@payloadcms/uiso it definitely should've complained
sure, but I'll cut some fat cuz it's a bit large
I need to see imports
"use client"
import { AudioVisualBuilder, ShapeType, SmoothingAlgorythm, WaveformOrientation, WaveformShape } from "@euterpe.js/visualizer"
import { FieldLabel, JSONField, useField } from "@payloadcms/ui"
import type { JSONFieldClientComponent, JSONFieldLabelClientComponent } from "payload"
import React, { useRef } from "react"
import { useEffect } from "react"
export const FFTDataComponent: JSONFieldClientComponent = props => {
const audio_el = useRef<HTMLAudioElement>(null)
const canvas_el = useRef<SVGSVGElement>(null)
let duration = 0
const { value: fft_data, setValue: set_fft_data } = useField<number[]>()const { value: fft_data, setValue: set_fft_data } = useField<number[]>()Is missing an arg
Should be
const { value: fft_data, setValue: set_fft_data } = useField<number[]>({ path })(alias) useField<number[]>(options?: Options): FieldType<number[]>Optional tho?
export const FFTDataComponent: JSONFieldClientComponent = props => {
const audio_el = useRef<HTMLAudioElement>(null)
const canvas_el = useRef<SVGSVGElement>(null)
let duration = 0
const path = props.path
const { value: fft_data, setValue: set_fft_data } = useField<number[]>({ path })
...path to what
from props?
Path is the path to the field from Payloads perspective
It gets populated by payload automatically into your component props on the server
Go ahead and log the props to see what else you get
You get a bunch of useful stuff, even mroe if the component is an RSC (React Server Component)
I did path: props.path
and I'm now in the admin panel
Sounds like progress
hid this error, but I guess these things are just my lack of nextjs /react knowledge
Thanks for the help though!
My pleasure!
We can figure that one out
Paste your style attribute in here
I will correct it for you and explain why this is happening, this is a simple runtime error
return (
<div
style={{
display: "flex",
"flex-flow": "column nowrap",
"justify-content": "space-between",
gap: "1rem"
}}
>
<svg ref={canvas_el} viewBox="0 0 500 500" preserveAspectRatio="none" />
<button
type="button"
onClick={async () => {
// biome-ignore lint/style/noNonNullAssertion: <explanation>
// ;[fft_data, duration] = await analyze(audio_el.current!, song_url, fft_data_array)
console.log("clicked! Shame you don't know what to do about it :(")
}}
>
Create waveform
</button>
<input type="text" disabled={true} value={JSON.stringify(fft_data)} />
{/* biome-ignore lint/a11y/useMediaCaption: <explanation> */}
<audio />
</div>
)In React, we don't use hyphens for attributes and style names. The typing for the
styleattribute is
CSSPropertiesimported from
'react'display: "flex",
flexFlow: "column nowrap",
justifyContent: "space-between",
gap: "1rem"
then?
This
<div
style={{
display: "flex",
"flex-flow": "column nowrap",
"justify-content": "space-between",
gap: "1rem"
}}
>Should be:
<div
style={{
display: "flex",
flexFlow: "column nowrap",
justifyContent: "space-between",
gap: "1rem"
}}
>You got it
it's in wohoo
If you're more comfortable with CSS/SCSS (Payload uses SCSS for the Admin) you can declare an index.scss in the root of your component and just import it as
import './index.scss'Very nice!
I love Audio visualizers
Built a few for my DJ friends back in the day
eheheh, I made a whole audio visual library for some client work
Via fast fourier transforms
Oh sweet!
Let me know if you run into anything else! Glad we got it working here.
thank youu
Some of the ones I made :D
https://api.djkato.net/media/2025-03-02%2021-51-46.mp4
Star
Discord
online
Get dedicated engineering support directly from the Payload team.