import React, { useCallback, useMemo } from 'react' import { Stack, Text, Card, Box } from '@sanity/ui' import type { PortableTextBlock } from 'sanity' interface CharacterCountInputProps { value?: any onChange: (event: any) => void schemaType: any renderDefault: (props: any) => React.ReactElement } const BLUESKY_LIMIT = 300 function extractTextFromBlocks (blocks: PortableTextBlock[]): string { if (!blocks || !Array.isArray(blocks)) return '' return blocks .filter(block => block._type === 'block') .map(block => { if (!block.children || !Array.isArray(block.children)) return '' return block.children .filter(child => child._type === 'span') .map(child => child.text || '') .join('') }) .join('\n\n') } export function CharacterCountInput (props: CharacterCountInputProps) { const { value, onChange, schemaType, renderDefault } = props const textContent = useMemo(() => { return extractTextFromBlocks(value || []) + '\n\nroe.dev/ama\n\n#ama' }, [value]) const characterCount = textContent.length const remaining = BLUESKY_LIMIT - characterCount const getStatusColor = (remaining: number) => { if (remaining < 0) return '#e03131' // Red - over limit if (remaining < 30) return '#fd7e14' // Orange - warning return '#51cf66' // Green - good } const handleChange = useCallback((event: any) => { onChange(event) }, [onChange]) return ( {renderDefault({ ...props, value, onChange: handleChange, schemaType, })} Character count {characterCount} / {BLUESKY_LIMIT} {remaining < 0 && ( ⚠️ Over limit by {' '} {Math.abs(remaining)} {' '} characters )} {remaining >= 0 && remaining < 30 && ( ⚠️ {' '} {remaining} {' '} characters remaining )} ) }