import { CANVAS_CONFETTI, THROW } from '@agent/lib/confetti'; import { useCanvasStore } from '@agent/state/canvas'; import { useEffect, useRef, useState } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { check, chevronDown, Icon } from '@wordpress/icons'; import { useReducedMotion } from 'framer-motion'; // The step settles before the scroll moves the stack, or the two read as one blur. const DISABLE = 0.3; const CLOSE_DELAY = 3000; const SCROLL_TIME = 400; const STEP_INSET = 48; const scrollBox = (el) => { for (let node = el?.parentElement; node; node = node.parentElement) { const scrollable = /(auto|scroll)/.test(getComputedStyle(node).overflowY); if (scrollable && node.scrollHeight > node.clientHeight) return node; } return null; }; // Native smooth scroll times by distance, so long and short advances differ in speed. const scrollToTop = (card, instant) => { const box = scrollBox(card); if (!box) return () => {}; const from = box.scrollTop; const to = from + card.getBoundingClientRect().top - box.getBoundingClientRect().top - STEP_INSET; if (instant) { box.scrollTop = to; return () => {}; } const start = performance.now(); let frame = requestAnimationFrame(function step(now) { const progress = Math.min((now - start) / SCROLL_TIME, 1); box.scrollTop = from + (to - from) * (1 - (1 - progress) ** 3); if (progress < 1) frame = requestAnimationFrame(step); }); return () => cancelAnimationFrame(frame); }; export const steps = [ { id: 'business', title: __('Business details', 'extendify-local'), inputSchema: { type: 'object', properties: { businessName: { type: 'string', description: __('Business name', 'extendify-local'), }, tagline: { type: 'string', // translators: Form field label. A tagline is the short line describing what a business does. description: __('Tagline', 'extendify-local'), }, contactEmail: { type: 'string', format: 'email', description: __('Contact email', 'extendify-local'), }, phone: { type: 'string', description: __('Phone number', 'extendify-local'), }, }, }, }, { id: 'content', title: __('Content and audience', 'extendify-local'), inputSchema: { type: 'object', properties: { postCount: { type: 'string', description: __('Published posts', 'extendify-local'), }, topics: { type: 'string', // translators: Form field label. The subjects this website writes about. description: __('Main topics', 'extendify-local'), 'x-widget': 'textarea', }, latestPost: { type: 'string', description: __('Most recent post', 'extendify-local'), }, cadence: { type: 'string', // translators: Form field label. How often the website publishes something new. description: __('Publishing cadence', 'extendify-local'), enum: [ __('Weekly', 'extendify-local'), __('Monthly', 'extendify-local'), __('A few times a year', 'extendify-local'), __('Not publishing right now', 'extendify-local'), ], }, }, }, }, { id: 'technical', title: __('Technical', 'extendify-local'), inputSchema: { type: 'object', properties: { plugins: { type: 'string', description: __('Plugins in use', 'extendify-local'), 'x-widget': 'textarea', }, theme: { type: 'string', description: __('Active theme', 'extendify-local'), }, sellsOnline: { type: 'string', // translators: Form field label. Whether this website sells anything online. description: __('Sells online', 'extendify-local'), enum: [__('Yes', 'extendify-local'), __('No', 'extendify-local')], }, contactForm: { type: 'string', description: __('Contact form plugin', 'extendify-local'), }, }, }, }, ]; // The disabled colors land the moment the attribute flips, so without this the // fill jumps a frame before the step's fade even starts. const inputClass = 'w-full rounded-sm border border-gray-300 bg-white p-2 text-sm text-gray-900 transition-colors duration-300 disabled:border-gray-200 disabled:bg-gray-100 disabled:text-gray-700'; // JSON Schema has no way to say a string wants a textarea. const Field = ({ name, property, value, onChange }) => { const id = `extendify-demo-form-${name}`; const props = { id, className: inputClass, value, onChange: (event) => onChange(event.target.value), }; return (