PluginProbe
Extendify / 3.0.4
Extendify v3.0.4
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
extendify / src / Agent / workflows / theme / components / SelectThemeVariation.jsx

SelectThemeVariation.jsx in Extendify 3.0.4, at src/Agent/workflows/theme/components/SelectThemeVariation.jsx

139 lines 4.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useThemeVariations } from '@agent/hooks/useThemeVariations';
2 import { useVariationOverride } from '@agent/hooks/useVariationOverride';
3 import { useChatStore } from '@agent/state/chat';
4 import { useEffect, useMemo, useRef, useState } from '@wordpress/element';
5 import { __ } from '@wordpress/i18n';
6
7 export const SelectThemeVariation = ({ onConfirm, onCancel, onLoad }) => {
8 const [css, setCss] = useState('');
9 const [selected, setSelected] = useState(null);
10 const [duotoneTheme, setDuotoneTheme] = useState(null);
11 const { undoChange } = useVariationOverride({ css, duotoneTheme });
12
13 const confirmed = useRef(false);
14 useEffect(() => {
15 return () => {
16 if (!confirmed.current) undoChange();
17 };
18 }, []);
19 const { variations, isLoading } = useThemeVariations();
20 const noVariations = !variations || variations.length === 0;
21 const { addMessage, messages } = useChatStore();
22
23 const shuffled = useMemo(
24 () => (variations ? variations.sort(() => Math.random() - 0.5) : []),
25 [variations],
26 );
27
28 const handleConfirm = () => {
29 if (!selected) return;
30 const variation = variations.find((v) => v.title === selected);
31 if (!variation) {
32 // translators: A chat message shown to the user when their selected color variation cannot be applied
33 const content = __(
34 'We were unable to apply your selected colors. Please try again.',
35 'extendify-local',
36 );
37 addMessage('message', { role: 'assistant', content, error: true });
38 onCancel();
39 return;
40 }
41 confirmed.current = true;
42 onConfirm({ data: { variation }, shouldRefreshPage: true });
43 };
44
45 useEffect(() => {
46 if (isLoading) return;
47 onLoad();
48 }, [isLoading, onLoad]);
49
50 useEffect(() => {
51 if (isLoading || !noVariations) return;
52 const timer = setTimeout(() => onCancel(), 100);
53 // translators: A chat message shown to the user
54 const content = __(
55 'We were unable to find any colors for your theme',
56 'extendify-local',
57 );
58 const last = messages.at(-1)?.details?.content;
59 if (content === last) return () => clearTimeout(timer);
60 addMessage('message', { role: 'assistant', content, error: true });
61 return () => clearTimeout(timer);
62 }, [addMessage, onCancel, noVariations, messages, isLoading]);
63
64 if (isLoading) {
65 return (
66 <div className="min-h-24 p-2 text-center text-sm">
67 {__('Loading available colors...', 'extendify-local')}
68 </div>
69 );
70 }
71
72 if (noVariations) return null;
73
74 return (
75 <div className="mb-4 ml-10 mr-2 flex flex-col rounded-lg border border-gray-300 bg-gray-50 rtl:ml-2 rtl:mr-10">
76 <div className="rounded-lg border-b border-gray-300 bg-white">
77 <div className="grid grid-cols-2 gap-2 p-3">
78 {shuffled?.slice(0, 10)?.map(({ title, css, settings }) => (
79 <button
80 key={title}
81 style={{ backgroundColor: getColor(settings, 'background') }}
82 type="button"
83 className={`relative flex w-full items-center justify-center overflow-hidden rounded-lg border border-gray-300 bg-none p-2 text-center text-sm ${
84 selected === title ? 'ring ring-design-main ring-wp' : ''
85 }`}
86 onClick={() => {
87 setSelected(title);
88 setCss(css);
89 setDuotoneTheme(settings?.color?.duotone?.theme);
90 }}
91 >
92 <div className="flex max-w-fit items-center justify-center -space-x-4 rounded-lg rtl:space-x-reverse">
93 {getColors(settings)?.map((color, i) => (
94 <div
95 key={title + color + i}
96 style={{ backgroundColor: color }}
97 className="size-6 shrink-0 overflow-visible rounded-full border border-white md:size-7"
98 ></div>
99 ))}
100 </div>
101 </button>
102 ))}
103 </div>
104 </div>
105 <div className="flex justify-start gap-2 p-3">
106 <button
107 type="button"
108 className="w-full rounded-sm border border-gray-500 bg-white p-2 text-sm text-gray-900"
109 onClick={onCancel}
110 >
111 {__('Cancel', 'extendify-local')}
112 </button>
113 <button
114 type="button"
115 className="w-full rounded-sm border border-design-main bg-design-main p-2 text-sm text-white"
116 disabled={!selected}
117 onClick={handleConfirm}
118 >
119 {__('Save', 'extendify-local')}
120 </button>
121 </div>
122 </div>
123 );
124 };
125
126 const getColor = (settings, colorName) => {
127 return settings?.color?.palette?.theme.find((item) => item.slug === colorName)
128 ?.color;
129 };
130
131 const getColors = (settings) => {
132 return settings?.color?.palette?.theme
133 ?.filter((item) => item.slug !== 'background')
134 ?.reduce((acc, item) => {
135 acc.push(item.color);
136 return acc;
137 }, []);
138 };
139