PluginProbe ʕ •ᴥ•ʔ
VK Blocks / trunk
VK Blocks vtrunk
1.123.0 1.122.0 1.121.0 1.120.0 1.119.2 1.119.1 1.119.0 1.118.7 1.82.0.0 1.82.0.1 1.83.0.0 1.83.0.1 1.84.0.0 1.84.0.1 1.85.0.2 1.85.0.3 1.85.1.0 1.85.1.1 1.86.0.0 1.86.0.1 1.86.1.0 1.87.0.0 1.87.0.1 1.88.0.1 1.88.0.2 1.89.0.0 1.9.2 1.90.0.0 1.90.0.1 1.90.1.1 1.91.0.0 1.91.1.1 1.92.0.0 1.92.0.1 1.92.1.0 1.92.1.1 1.93.0.0 trunk 1.93.0.1 0.1.1 1.93.1.0 0.10.3 1.93.1.1 0.11.0 1.94.0.0 0.12.6 1.94.0.1 0.15.1 1.94.1.0 0.16.2 1.94.2.1 0.17.6 1.94.2.2 0.2.2 1.95.0.3 0.22.4 1.95.0.4 0.26.7 1.96.2.0 0.3.2 1.96.2.1 0.31.0 1.97.0.1 0.35.5 1.97.0.2 0.37.5 1.99.0.0 0.38.8 1.99.0.1 0.39.4 0.4.7 0.41.0 0.42.0 0.44.13 0.45.2 0.46.1 0.47.0 0.48.0 0.49.8 0.5.2 0.50.3 0.51.0 0.52.2 0.53.2 0.54.0 0.55.0 0.56.2 0.56.3 0.57.6 0.58.10 0.59.0 0.6.0 0.60.1 0.61.2 0.7.1 0.8.2 1.0.16 1.10.0 1.100.0.0 1.100.0.1 1.102.0.0 1.102.0.1 1.103.0.0 1.104.0.0 1.104.0.1 1.105.1.0 1.105.1.1 1.106.0.0 1.106.0.1 1.107.0.0 1.107.0.1 1.107.0.2 1.108.0.0 1.108.0.1 1.109.0.0 1.109.0.1 1.11.4 1.110.0.0 1.110.0.1 1.111.0.0 1.111.0.1 1.111.0.2 1.112.0.0 1.112.0.1 1.113.0.0 1.113.0.1 1.114.0.0 1.114.0.1 1.114.2.0 1.114.2.1 1.115.0.0 1.115.0.1 1.115.1.0 1.115.1.1 1.115.2.0 1.115.2.1 1.116.0.0 1.116.0.1 1.116.1.0 1.116.1.1 1.116.2.0 1.117.0.0 1.117.0.1 1.117.1.0 1.118.2 1.118.5 1.12.0 1.13.2 1.14.1 1.15.1 1.16.11 1.17.0 1.18.6 1.19.0 1.19.1 1.2.3 1.20.7 1.21.0 1.22.4 1.23.0 1.24.5 1.25.1 1.26.2 1.27.7.2 1.28.0.1 1.29.2.0 1.3.9 1.30.0.1 1.31.0.1 1.32.0.2 1.33.2.1 1.36.1.5 1.37.0.0 1.39.2.1 1.4.6 1.40.0.1 1.40.1.0 1.40.1.1 1.41.0.0 1.41.0.1 1.41.2.2 1.41.2.3 1.43.0.0 1.43.0.1 1.43.0.2 1.44.0.0 1.44.0.1 1.45.0.0 1.45.0.1 1.46.0.0 1.46.0.1 1.47.0.0 1.47.0.1 1.47.1.0 1.48.0.0 1.48.0.1 1.48.0.2 1.48.1.0 1.48.1.1 1.5.0 1.50.0.0 1.50.0.1 1.51.0.0 1.51.0.1 1.52.0.0 1.52.0.1 1.53.0.0 1.53.0.1 1.54.0.0 1.54.0.1 1.55.0.0 1.55.0.1 1.56.0.0 1.56.0.1 1.57.0.0 1.57.0.2 1.57.0.3 1.57.0.4 1.57.0.5 1.57.1.0 1.57.1.1 1.57.1.2 1.58.0.0 1.58.0.1 1.59.0.0 1.59.0.1 1.6.0 1.60.0.0 1.60.0.1 1.63.0.0 1.63.0.1 1.64.0.0 1.64.0.1 1.64.1.0 1.64.1.2 1.67.0.0 1.67.0.1 1.68.0.0 1.68.0.1 1.69.0.0 1.69.0.1 1.69.1.1 1.69.1.2 1.7.1 1.70.0.0 1.70.0.1 1.71.0.0 1.71.0.1 1.72.0.0 1.72.1.0 1.72.1.1 1.73.0.0 1.73.0.1 1.74.0.0 1.74.0.1 1.75.0.0 1.75.1.0 1.75.1.1 1.76.0.0 1.76.0.1 1.76.1.0 1.76.1.1 1.76.2.0 1.76.2.1 1.77.0.0 1.77.0.1 1.78.0.0 1.78.0.1 1.79.0.0 1.79.0.1 1.79.0.2 1.79.0.3 1.79.1.0 1.79.1.1 1.8.2 1.80.1.0 1.80.1.1 1.80.1.2 1.81.0.1 1.81.0.2
vk-blocks / src / blocks / slider / edit-multiItem.js
vk-blocks / src / blocks / slider Last commit date
deprecated 2 weeks ago _swiper._scss 2 months ago block.json 2 weeks ago edit-multiItem.js 2 weeks ago edit-slider.js 2 weeks ago edit.js 1 week ago icon.svg 2 months ago index.js 2 months ago index.php 2 months ago loop-min-slides.js 2 months ago pause-button.js 1 week ago save.js 1 week ago style.scss 2 months ago view.js 1 week ago
edit-multiItem.js
355 lines
1 import { __, sprintf } from '@wordpress/i18n';
2 import {
3 PanelBody,
4 BaseControl,
5 TextControl,
6 RadioControl,
7 ToggleControl,
8 } from '@wordpress/components';
9 import { useSelect } from '@wordpress/data';
10 import { getMinSlidesForLoop } from './loop-min-slides';
11
12 export const MultiItemSetting = (props) => {
13 const { attributes, setAttributes, clientId } = props;
14 const {
15 slidesPerGroup,
16 slidesPerViewMobile,
17 slidesPerViewTablet,
18 slidesPerViewPC,
19 loop,
20 effect,
21 centeredSlides,
22 zoomAnimation,
23 } = attributes;
24
25 // インナーブロックを取得
26 const innerBlocks = useSelect((select) =>
27 select('core/block-editor').getBlocks(clientId)
28 );
29
30 // 1スライドあたりの表示枚数がスライダーの総枚数の約数出なかったときに表示するアラート
31 const slidesPerViewAlert = (
32 <div className="text-danger font-size-11px">
33 {__(
34 'Enter integer divisors for the number of placed slide items for each display size.',
35 'vk-blocks'
36 )}
37 </div>
38 );
39
40 const isNotDivisor = (value) => {
41 if (value === null || value === undefined || value === '') {
42 return false;
43 }
44 const n = parseInt(value, 10);
45 return !Number.isNaN(n) && innerBlocks.length % n !== 0;
46 };
47
48 const slidesPerViewMobileAlert =
49 slidesPerGroup === 'slides-per-view' &&
50 isNotDivisor(slidesPerViewMobile)
51 ? slidesPerViewAlert
52 : '';
53 const slidesPerViewTabletAlert =
54 slidesPerGroup === 'slides-per-view' &&
55 isNotDivisor(slidesPerViewTablet)
56 ? slidesPerViewAlert
57 : '';
58 const slidesPerViewPCAlert =
59 slidesPerGroup === 'slides-per-view' && isNotDivisor(slidesPerViewPC)
60 ? slidesPerViewAlert
61 : '';
62
63 const makeLoopAlert = (spv, spg) => {
64 const minRequired = getMinSlidesForLoop(spv, spg, !!centeredSlides);
65 if (innerBlocks.length >= minRequired) {
66 return '';
67 }
68 return (
69 <div className="alert alert-danger font-size-11px">
70 {sprintf(
71 /* translators: %d: minimum number of slides required for loop mode */
72 __(
73 'Loop mode requires at least %d slides with the current slider settings. Please add more slides or disable loop.',
74 'vk-blocks'
75 ),
76 minRequired
77 )}
78 </div>
79 );
80 };
81
82 // toSpv: spv を最低 1 にクランプする(小数はそのまま保持し getMinSlidesForLoop 側で正規化)。
83 // toSpg: spv を正整数に正規化する。null/undefined/'' または有限数でない場合は undefined を返す。
84 const toSpv = (spv) => Math.max(1, spv);
85 const toSpg = (spv) => {
86 if (spv === null || spv === undefined || spv === '') {
87 return undefined;
88 }
89 const n = Number(spv);
90 return Number.isFinite(n) ? Math.max(1, Math.floor(n)) : undefined;
91 };
92
93 /* ループ時のアラート */
94 const slidesPerViewMobileLoopAlert = loop
95 ? makeLoopAlert(
96 toSpv(slidesPerViewMobile || 1),
97 slidesPerGroup === 'slides-per-view'
98 ? (toSpg(slidesPerViewMobile || 1) ?? 1)
99 : 1
100 )
101 : '';
102 const slidesPerViewTabletLoopAlert =
103 loop &&
104 slidesPerViewTablet !== null &&
105 slidesPerViewTablet !== undefined &&
106 slidesPerViewTablet !== ''
107 ? makeLoopAlert(
108 toSpv(slidesPerViewTablet),
109 slidesPerGroup === 'slides-per-view'
110 ? (toSpg(slidesPerViewTablet) ?? 1)
111 : 1
112 )
113 : '';
114 const slidesPerViewPCLoopAlert =
115 loop &&
116 slidesPerViewPC !== null &&
117 slidesPerViewPC !== undefined &&
118 slidesPerViewPC !== ''
119 ? makeLoopAlert(
120 toSpv(slidesPerViewPC),
121 slidesPerGroup === 'slides-per-view'
122 ? (toSpg(slidesPerViewPC) ?? 1)
123 : 1
124 )
125 : '';
126
127 // 複数枚表示設定
128 let multiItemSetting = '';
129
130 // フェードエフェクトでない場合の設定UI
131 const multiItemUI =
132 effect !== 'fade' ? (
133 <>
134 <BaseControl
135 label={__(
136 'Number of Items to display per view',
137 'vk-blocks'
138 )}
139 id={`vk_slider-MultiItem`}
140 >
141 <p className="font-size-11px">
142 {__(
143 'Enter the number of slide items to display on each device.',
144 'vk-blocks'
145 )}
146 </p>
147 <p className="font-size-11px">
148 {__(
149 'In one-by-one mode, you can set decimals (e.g. 1.5). If you specify a decimal, please enable "Centering the active slide".',
150 'vk-blocks'
151 )}
152 </p>
153 <p className="font-size-11px">
154 {__(
155 'In slides-per-view mode, enter a divisor of the total number of placed slides. If the number is not a divisor, the sliding behavior will be unnatural.',
156 'vk-blocks'
157 )}
158 </p>
159 <p className="font-size-11px">
160 {__(
161 'When "Centering the active slide" is enabled and the number of items to display is even, it is automatically treated as the next odd number internally. This may increase the minimum number of slides required for loop mode.',
162 'vk-blocks'
163 )}
164 </p>
165 <TextControl
166 type={'number'}
167 label={__('PC', 'vk-blocks')}
168 value={slidesPerViewPC}
169 onChange={(value) => {
170 if (
171 Number.isNaN(Number(value)) ||
172 Number(value) < 1
173 ) {
174 setAttributes({
175 slidesPerViewPC: 1,
176 });
177 } else if (slidesPerGroup === 'slides-per-view') {
178 setAttributes({
179 slidesPerViewPC: parseInt(
180 Number(value),
181 10
182 ),
183 });
184 } else {
185 setAttributes({
186 slidesPerViewPC: parseFloat(Number(value)),
187 });
188 }
189 }}
190 min={1}
191 step={slidesPerGroup === 'slides-per-view' ? 1 : 0.1}
192 />
193 {slidesPerViewPCAlert}
194 {slidesPerViewPCLoopAlert}
195 <TextControl
196 type={'number'}
197 label={__('Tablet', 'vk-blocks')}
198 value={slidesPerViewTablet}
199 onChange={(value) => {
200 if (
201 Number.isNaN(Number(value)) ||
202 Number(value) < 1
203 ) {
204 setAttributes({
205 slidesPerViewTablet: 1,
206 });
207 } else if (slidesPerGroup === 'slides-per-view') {
208 setAttributes({
209 slidesPerViewTablet: parseInt(
210 Number(value),
211 10
212 ),
213 });
214 } else {
215 setAttributes({
216 slidesPerViewTablet: parseFloat(
217 Number(value)
218 ),
219 });
220 }
221 }}
222 min={1}
223 step={slidesPerGroup === 'slides-per-view' ? 1 : 0.1}
224 />
225 {slidesPerViewTabletAlert}
226 {slidesPerViewTabletLoopAlert}
227 <TextControl
228 type={'number'}
229 label={__('Mobile', 'vk-blocks')}
230 value={slidesPerViewMobile}
231 onChange={(value) => {
232 if (
233 Number.isNaN(Number(value)) ||
234 Number(value) < 1
235 ) {
236 setAttributes({
237 slidesPerViewMobile: 1,
238 });
239 } else if (slidesPerGroup === 'slides-per-view') {
240 setAttributes({
241 slidesPerViewMobile: parseInt(
242 Number(value),
243 10
244 ),
245 });
246 } else {
247 setAttributes({
248 slidesPerViewMobile: parseFloat(
249 Number(value)
250 ),
251 });
252 }
253 }}
254 min={1}
255 step={slidesPerGroup === 'slides-per-view' ? 1 : 0.1}
256 />
257 {slidesPerViewMobileAlert}
258 {slidesPerViewMobileLoopAlert}
259 </BaseControl>
260 <BaseControl
261 label={__(
262 'Number of items to change in a transition',
263 'vk-blocks'
264 )}
265 id={`vk_slider-slidesPerGroup`}
266 >
267 <RadioControl
268 selected={slidesPerGroup}
269 className={'vk-radioControl'}
270 options={[
271 {
272 label: __('One by One', 'vk-blocks'),
273 value: 'one-by-one',
274 },
275 {
276 label: __(
277 'Same as the number of items to display',
278 'vk-blocks'
279 ),
280 value: 'slides-per-view',
281 },
282 ]}
283 onChange={(value) => {
284 const attrs = { slidesPerGroup: value };
285 if (value === 'slides-per-view') {
286 const pcVal = toSpg(slidesPerViewPC);
287 if (pcVal !== undefined) {
288 attrs.slidesPerViewPC = pcVal;
289 }
290 const tabletVal = toSpg(slidesPerViewTablet);
291 if (tabletVal !== undefined) {
292 attrs.slidesPerViewTablet = tabletVal;
293 }
294 const mobileVal = toSpg(slidesPerViewMobile);
295 if (mobileVal !== undefined) {
296 attrs.slidesPerViewMobile = mobileVal;
297 }
298 }
299 setAttributes(attrs);
300 }}
301 />
302 </BaseControl>
303 <BaseControl id={`vk_slider-slidesPerGroup`}>
304 <ToggleControl
305 label={__('Centering the active slide', 'vk-blocks')}
306 className={'mb-1'}
307 checked={centeredSlides}
308 onChange={(checked) =>
309 setAttributes({ centeredSlides: checked })
310 }
311 help={__(
312 'If you specify the center, you can display items that are cut off on the left and right.',
313 'vk-blocks'
314 )}
315 />
316 </BaseControl>
317 </>
318 ) : null;
319
320 // 複数枚表示設定が無効な場合のアラート
321 const getDisabledReason = () => {
322 if (zoomAnimation) {
323 return __('Background Image Zoom Animation', 'vk-blocks');
324 } else if (effect === 'fade') {
325 return __('Fade', 'vk-blocks') + ' ' + __('Effect', 'vk-blocks');
326 }
327 return null;
328 };
329
330 const disabledReason = getDisabledReason();
331 const disabledAlert = disabledReason ? (
332 <div className="alert alert-warning font-size-11px">
333 {sprintf(
334 /* translators: %s: name of the feature that is enabled (e.g. "Fade Effect" or "Background Image Zoom Animation") */
335 __(
336 '%s is enabled, so multi-item settings cannot be configured.',
337 'vk-blocks'
338 ),
339 disabledReason
340 )}
341 </div>
342 ) : null;
343
344 multiItemSetting = (
345 <PanelBody
346 title={__('Multi-item Display Setting', 'vk-blocks')}
347 initialOpen={false}
348 >
349 {disabledAlert}
350 {!zoomAnimation && multiItemUI}
351 </PanelBody>
352 );
353 return multiItemSetting;
354 };
355