| @@ -1,27 +1,58 @@ | ||
| 1 | -import { selectedContent } from '@agent/icons'; | |
| 1 | +import { findBlockEl, scopeOf } from '@agent/lib/block-el'; | |
| 2 | +import { buildSubtreeManifest } from '@agent/lib/subtree-manifest'; | |
| 2 | 3 | import { useQuickEditStore } from '@quick-edit/state/store'; |
| 3 | -import { __ } from '@wordpress/i18n'; | |
| 4 | +import { useMemo } from '@wordpress/element'; | |
| 5 | +import { __, _n, sprintf } from '@wordpress/i18n'; | |
| 4 | 6 | import { close, Icon } from '@wordpress/icons'; |
| 7 | +import classNames from 'classnames'; | |
| 5 | 8 | |
| 6 | 9 | export const PageDocument = ({ busy }) => { |
| 7 | 10 | const setBlock = useQuickEditStore((s) => s.setAgentBlock); |
| 11 | + const block = useQuickEditStore((s) => s.agentBlock); | |
| 12 | + | |
| 13 | + // The same manifest the agent works from, so the count matches what it | |
| 14 | + // can actually address — not every node in the subtree. | |
| 15 | + const count = useMemo(() => { | |
| 16 | + if (!block?.id) return 1; | |
| 17 | + const node = findBlockEl(block.id, document, scopeOf(block)); | |
| 18 | + return Math.max(node ? buildSubtreeManifest(node).length : 1, 1); | |
| 19 | + }, [block]); | |
| 20 | + | |
| 8 | 21 | return ( |
| 9 | - <div className="flex w-fit items-center justify-start gap-1 rounded-sm border border-gray-500 bg-gray-100 p-1 text-sm text-gray-900"> | |
| 10 | - <div className="flex items-center gap-1"> | |
| 11 | - <Icon icon={selectedContent} /> | |
| 12 | - <div>{__('Selected content', 'extendify-local')}</div> | |
| 13 | - </div> | |
| 22 | + // The input darkens to gray-300 while disabled; a gray-200 chip vanishes into it. | |
| 23 | + <div | |
| 24 | + className={classNames( | |
| 25 | + 'flex w-fit max-w-full items-center gap-1 whitespace-nowrap rounded-sm py-1.5 pe-1.5 ps-2.5 text-xs leading-tight', | |
| 26 | + { | |
| 27 | + 'bg-gray-100 text-gray-600': busy, | |
| 28 | + 'bg-gray-200 text-gray-900': !busy, | |
| 29 | + }, | |
| 30 | + )} | |
| 31 | + > | |
| 32 | + <span className="truncate"> | |
| 33 | + {sprintf( | |
| 34 | + // translators: %d is the number of blocks the user selected on the page. | |
| 35 | + _n( | |
| 36 | + '%d block selected', | |
| 37 | + '%d blocks selected', | |
| 38 | + count, | |
| 39 | + 'extendify-local', | |
| 40 | + ), | |
| 41 | + count, | |
| 42 | + )} | |
| 43 | + </span> | |
| 44 | + {/* Stays mounted while disabled: dropping it reflows the chip mid-run. */} | |
| 14 | 45 | <button |
| 15 | 46 | type="button" |
| 16 | 47 | disabled={busy} |
| 17 | - className="flex h-full items-center rounded-none border-0 bg-transparent outline-hidden ring-design-main focus:shadow-none focus:outline-hidden focus-visible:outline-design-main" | |
| 48 | + className="flex shrink-0 items-center rounded-none border-0 bg-transparent p-0 outline-hidden ring-design-main focus:shadow-none focus:outline-hidden focus-visible:outline-design-main disabled:cursor-not-allowed disabled:opacity-40" | |
| 18 | 49 | onClick={() => setBlock(null)} |
| 19 | 50 | > |
| 20 | 51 | <Icon |
| 21 | 52 | className="pointer-events-none fill-current leading-none" |
| 22 | 53 | icon={close} |
| 23 | - size={18} | |
| 54 | + size={16} | |
| 24 | 55 | /> |
| 25 | 56 | <span className="sr-only">{__('Remove', 'extendify-local')}</span> |
| 26 | 57 | </button> |
| 27 | 58 | </div> |