This changes the design of lexical upload nodes to better show the actual media instead of the metadata. ## Updated Design https://github.com/user-attachments/assets/49096378-35c2-4eb0-b4b6-5f138d49bdad Light mode: <img width="780" height="962" alt="Screenshot 2025-09-24 at 10 11 32@2x" src="https://github.com/user-attachments/assets/7611e659-3914-46e9-9c8c-db88c180227b" /> ## Previous Design > Before: > > <img width="1358" height="860" alt="Screenshot 2025-09-22 at 16 01 16@2x" src="https://github.com/user-attachments/assets/7831761c-6c3c-4072-82ed-68b88e3842b7" /> > > After: > > <img width="1776" height="1632" alt="Screenshot 2025-09-22 at 16 01 00@2x" src="https://github.com/user-attachments/assets/b434b6d5-a965-4c2b-adba-c1bf2a3be4bc" /> > > > https://github.com/user-attachments/assets/f2749a38-c191-4b50-a521-8f722ed42a8f > --- - To see the specific tasks where the Asana app for GitHub is being used, see below: - https://app.asana.com/0/0/1211429812808983
91 lines
2.7 KiB
TypeScript
91 lines
2.7 KiB
TypeScript
'use client'
|
|
import type { DOMConversionMap, LexicalNode } from 'lexical'
|
|
import type { JSX } from 'react'
|
|
|
|
import ObjectID from 'bson-objectid'
|
|
import { $applyNodeReplacement } from 'lexical'
|
|
import * as React from 'react'
|
|
|
|
import type {
|
|
Internal_UploadData,
|
|
SerializedUploadNode,
|
|
UploadData,
|
|
} from '../../server/nodes/UploadNode.js'
|
|
|
|
import { $convertUploadElement } from '../../server/nodes/conversions.js'
|
|
import { UploadServerNode } from '../../server/nodes/UploadNode.js'
|
|
import { PendingUploadComponent } from '../component/pending/index.js'
|
|
|
|
const RawUploadComponent = React.lazy(() =>
|
|
import('../../client/component/index.js').then((module) => ({ default: module.UploadComponent })),
|
|
)
|
|
|
|
export class UploadNode extends UploadServerNode {
|
|
static override clone(node: UploadServerNode): UploadServerNode {
|
|
return super.clone(node)
|
|
}
|
|
|
|
static override getType(): string {
|
|
return super.getType()
|
|
}
|
|
|
|
static override importDOM(): DOMConversionMap<HTMLImageElement> {
|
|
return {
|
|
img: (node) => ({
|
|
conversion: (domNode) => $convertUploadElement(domNode, $createUploadNode),
|
|
priority: 0,
|
|
}),
|
|
}
|
|
}
|
|
|
|
static override importJSON(serializedNode: SerializedUploadNode): UploadNode {
|
|
if (serializedNode.version === 1 && (serializedNode?.value as unknown as { id: string })?.id) {
|
|
serializedNode.value = (serializedNode.value as unknown as { id: string }).id
|
|
}
|
|
if (serializedNode.version === 2 && !serializedNode?.id) {
|
|
serializedNode.id = new ObjectID.default().toHexString()
|
|
serializedNode.version = 3
|
|
}
|
|
|
|
const importedData: Internal_UploadData = {
|
|
id: serializedNode.id,
|
|
fields: serializedNode.fields,
|
|
pending: (serializedNode as Internal_UploadData).pending,
|
|
relationTo: serializedNode.relationTo,
|
|
value: serializedNode.value,
|
|
}
|
|
|
|
const node = $createUploadNode({ data: importedData })
|
|
node.setFormat(serializedNode.format)
|
|
|
|
return node
|
|
}
|
|
|
|
override decorate(): JSX.Element {
|
|
if ((this.__data as Internal_UploadData).pending) {
|
|
return <PendingUploadComponent />
|
|
}
|
|
return <RawUploadComponent data={this.__data} format={this.__format} nodeKey={this.getKey()} />
|
|
}
|
|
|
|
override exportJSON(): SerializedUploadNode {
|
|
return super.exportJSON()
|
|
}
|
|
}
|
|
|
|
export function $createUploadNode({
|
|
data,
|
|
}: {
|
|
data: Omit<UploadData, 'id'> & Partial<Pick<UploadData, 'id'>>
|
|
}): UploadNode {
|
|
if (!data?.id) {
|
|
data.id = new ObjectID.default().toHexString()
|
|
}
|
|
|
|
return $applyNodeReplacement(new UploadNode({ data: data as UploadData }))
|
|
}
|
|
|
|
export function $isUploadNode(node: LexicalNode | null | undefined): node is UploadNode {
|
|
return node instanceof UploadNode
|
|
}
|