itmar-block-packages 1.3.6 → 1.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "itmar-block-packages",
3
- "version": "1.3.6",
3
+ "version": "1.3.8",
4
4
  "description": "We have put together a package of common React components used for WordPress custom blocks.",
5
5
  "main": "build/index.js",
6
6
  "scripts": {
package/src/BlockPlace.js CHANGED
@@ -89,7 +89,10 @@ export default function BlockPlace(props) {
89
89
  computedStyle.display === "flex" ||
90
90
  computedStyle.display === "inline-flex"
91
91
  ) {
92
- if (computedStyle.flexDirection === "row") {
92
+ if (
93
+ computedStyle.flexDirection === "row" ||
94
+ computedStyle.flexDirection === "row-reverse"
95
+ ) {
93
96
  setDirection("row");
94
97
  } else {
95
98
  setDirection("column");
@@ -316,10 +319,22 @@ export default function BlockPlace(props) {
316
319
  {(itemProps) => (
317
320
  <Button
318
321
  {...itemProps}
319
- isPressed={sel_pos.outer_vertical === "self-start"}
320
- onClick={() => props.onVerticalChange("self-start")}
322
+ isPressed={
323
+ direction === "row"
324
+ ? sel_pos.outer_vertical === "self-start"
325
+ : sel_pos.outer_align === "left"
326
+ }
327
+ onClick={
328
+ direction === "row"
329
+ ? () => props.onVerticalChange("self-start")
330
+ : () => props.onAlignChange("left")
331
+ }
321
332
  icon={direction === "row" ? upper : justifyLeft}
322
- label={__("upper alignment", "block-collections")}
333
+ label={
334
+ direction === "row"
335
+ ? __("upper alignment", "block-collections")
336
+ : __("left alignment", "block-collections")
337
+ }
323
338
  />
324
339
  )}
325
340
  </ToolbarItem>
@@ -327,8 +342,16 @@ export default function BlockPlace(props) {
327
342
  {(itemProps) => (
328
343
  <Button
329
344
  {...itemProps}
330
- isPressed={sel_pos.outer_vertical === "center"}
331
- onClick={() => props.onVerticalChange("center")}
345
+ isPressed={
346
+ direction === "row"
347
+ ? sel_pos.outer_vertical === "center"
348
+ : sel_pos.outer_align === "center"
349
+ }
350
+ onClick={
351
+ direction === "row"
352
+ ? () => props.onVerticalChange("center")
353
+ : () => props.onAlignChange("center")
354
+ }
332
355
  icon={direction === "row" ? middle : justifyCenter}
333
356
  label={__("center alignment", "block-collections")}
334
357
  />
@@ -338,10 +361,22 @@ export default function BlockPlace(props) {
338
361
  {(itemProps) => (
339
362
  <Button
340
363
  {...itemProps}
341
- isPressed={sel_pos.outer_vertical === "self-end"}
342
- onClick={() => props.onVerticalChange("self-end")}
364
+ isPressed={
365
+ direction === "row"
366
+ ? sel_pos.outer_vertical === "self-end"
367
+ : sel_pos.outer_align === "right"
368
+ }
369
+ onClick={
370
+ direction === "row"
371
+ ? () => props.onVerticalChange("self-end")
372
+ : () => props.onAlignChange("right")
373
+ }
343
374
  icon={direction === "row" ? lower : justifyRight}
344
- label={__("lower alignment", "block-collections")}
375
+ label={
376
+ direction === "row"
377
+ ? __("lower alignment", "block-collections")
378
+ : __("right alignment", "block-collections")
379
+ }
345
380
  />
346
381
  )}
347
382
  </ToolbarItem>
@@ -455,21 +490,20 @@ export default function BlockPlace(props) {
455
490
  />
456
491
  )}
457
492
  </ToolbarItem>
458
-
459
- {sel_pos.height_val === "free" && (
460
- <RangeControl
461
- value={sel_pos.free_height}
462
- label={__("Height", "block-collections")}
463
- max={1800}
464
- min={300}
465
- step={10}
466
- onChange={(newValue) => {
467
- props.onFreeHeightChange(newValue);
468
- }}
469
- withInputField={true}
470
- />
471
- )}
472
493
  </ToolbarGroup>
494
+ {sel_pos.height_val === "free" && (
495
+ <RangeControl
496
+ value={sel_pos.free_height}
497
+ label={__("Height", "block-collections")}
498
+ max={1800}
499
+ min={300}
500
+ step={10}
501
+ onChange={(newValue) => {
502
+ props.onFreeHeightChange(newValue);
503
+ }}
504
+ withInputField={true}
505
+ />
506
+ )}
473
507
 
474
508
  {sel_pos.direction === "grid" && (
475
509
  <>
package/src/DateElm.js ADDED
@@ -0,0 +1,354 @@
1
+ import { __ } from "@wordpress/i18n";
2
+ import { nanoid } from "nanoid";
3
+ import {
4
+ PanelBody,
5
+ PanelRow,
6
+ __experimentalNumberControl as NumberControl,
7
+ } from "@wordpress/components";
8
+
9
+ import { useRef, useEffect, useState } from "@wordpress/element";
10
+
11
+ //Google Calender APIから祝日データを取得するためのID
12
+ const CALENDAR_ID = "japanese__ja@holiday.calendar.google.com";
13
+
14
+ //期間の設定から選択できる月の情報オブジェクトを配列にする関数
15
+ export const generateDateArray = (dateObj, isMonth) => {
16
+ const { startYear, startMonth, endYear, endMonth } = dateObj;
17
+ const result = [];
18
+
19
+ for (let year = startYear; year <= endYear; year++) {
20
+ if (isMonth) {
21
+ const monthStart = year === startYear ? startMonth : 1;
22
+ const monthEnd = year === endYear ? endMonth : 12;
23
+
24
+ for (let month = monthStart; month <= monthEnd; month++) {
25
+ const unitObj = {
26
+ id: nanoid(5),
27
+ value: `${year}/${month.toString().padStart(2, "0")}`,
28
+ label: `${year}/${month.toString().padStart(2, "0")}`,
29
+ classname: "filter_date",
30
+ };
31
+ result.push(unitObj);
32
+ }
33
+ } else {
34
+ const unitObj = {
35
+ id: nanoid(5),
36
+ value: `${year}`,
37
+ label: `${year}`,
38
+ classname: "filter_date",
39
+ };
40
+ result.push(unitObj);
41
+ }
42
+ }
43
+
44
+ return result;
45
+ };
46
+
47
+ //与えられた月から日付と曜日を要素とする配列を生成する
48
+ export const generateMonthCalendar = (dateString, holidays = null) => {
49
+ const [year, month] = dateString.split("/").map(Number);
50
+ const date = new Date(year, month - 1, 1);
51
+ const lastDay = new Date(year, month, 0).getDate();
52
+
53
+ const calendar = [];
54
+
55
+ for (let day = 1; day <= lastDay; day++) {
56
+ date.setDate(day);
57
+ //祝日の情報
58
+ const holidayItem = holidays?.find((item) => {
59
+ // 日付文字列から最後の2桁を抽出
60
+ const lastTwoDigits = parseInt(item.date.slice(-2), 10);
61
+ // 抽出した2桁を比較
62
+ return lastTwoDigits === day;
63
+ });
64
+ //日付情報オブジェクト
65
+ const dayObj = holidayItem
66
+ ? {
67
+ date: day,
68
+ weekday: date.getDay(),
69
+ holiday: holidayItem.name,
70
+ }
71
+ : {
72
+ date: day,
73
+ weekday: date.getDay(),
74
+ };
75
+ calendar.push(dayObj);
76
+ }
77
+
78
+ return calendar;
79
+ };
80
+
81
+ //期間設定のインスペクターコントロール
82
+ export const PeriodCtrl = ({
83
+ startYear,
84
+ endYear,
85
+ dateSpan,
86
+ isMonth,
87
+ onChange,
88
+ }) => {
89
+ return (
90
+ <PanelBody
91
+ title={__("Period Setting", "block-collections")}
92
+ initialOpen={true}
93
+ className="form_setteing_ctrl"
94
+ >
95
+ <label>{__("Start of period", "block-collections")}</label>
96
+ <PanelRow className="itmar_date_span">
97
+ <NumberControl
98
+ label={__("Year", "block-collections")}
99
+ labelPosition="side"
100
+ max={endYear}
101
+ min={startYear}
102
+ onChange={(newValue) => {
103
+ const newSpanObj = {
104
+ dateSpan: {
105
+ ...dateSpan,
106
+ startYear: Number(newValue),
107
+ },
108
+ };
109
+ onChange(newSpanObj);
110
+ }}
111
+ value={dateSpan.startYear}
112
+ />
113
+ {isMonth && (
114
+ <NumberControl
115
+ label={__("Month", "block-collections")}
116
+ labelPosition="side"
117
+ max={12}
118
+ min={1}
119
+ onChange={(newValue) => {
120
+ const newSpanObj = {
121
+ dateSpan: {
122
+ ...dateSpan,
123
+ startMonth: Number(newValue),
124
+ },
125
+ };
126
+ onChange(newSpanObj);
127
+ }}
128
+ value={dateSpan.startMonth}
129
+ />
130
+ )}
131
+ </PanelRow>
132
+ <label>{__("End of period", "block-collections")}</label>
133
+ <PanelRow className="itmar_date_span">
134
+ <NumberControl
135
+ label={__("Year", "block-collections")}
136
+ labelPosition="side"
137
+ max={endYear}
138
+ min={startYear}
139
+ onChange={(newValue) => {
140
+ const newSpanObj = {
141
+ dateSpan: {
142
+ ...dateSpan,
143
+ endYear: Number(newValue),
144
+ },
145
+ };
146
+ onChange(newSpanObj);
147
+ }}
148
+ value={dateSpan.endYear}
149
+ />
150
+ <NumberControl
151
+ label={__("Month", "block-collections")}
152
+ labelPosition="side"
153
+ max={12}
154
+ min={1}
155
+ onChange={(newValue) => {
156
+ const newSpanObj = {
157
+ dateSpan: {
158
+ ...dateSpan,
159
+ endMonth: Number(newValue),
160
+ },
161
+ };
162
+ onChange(newSpanObj);
163
+ }}
164
+ value={dateSpan.endMonth}
165
+ />
166
+ </PanelRow>
167
+ </PanelBody>
168
+ );
169
+ };
170
+
171
+ //日付から期間のクエリー用の配列を生成
172
+ export const getPeriodQuery = (dateString) => {
173
+ if (!dateString) {
174
+ return null; //与えられた文字列が空ならnullをかえす
175
+ }
176
+ const parts = dateString.split("/");
177
+ const year = parseInt(parts[0], 10);
178
+ const month = parts.length > 1 ? parseInt(parts[1], 10) : null;
179
+ const day = parts.length > 2 ? parseInt(parts[2], 10) : null;
180
+
181
+ let startDate, endDate;
182
+
183
+ if (day) {
184
+ // 特定の日
185
+ startDate = new Date(year, month - 1, day, 0, 0, 0, -1);
186
+ endDate = new Date(year, month - 1, day, 23, 59, 59, 1000);
187
+ } else if (month) {
188
+ // 特定の月
189
+ startDate = new Date(year, month - 1, 1, 0, 0, 0, -1);
190
+ endDate = new Date(year, month, 1, 0, 0, 0, 0);
191
+ } else {
192
+ // 特定の年
193
+ startDate = new Date(year, 0, 1, 0, 0, 0, -1);
194
+ endDate = new Date(year + 1, 0, 1, 0, 0, 0, 0);
195
+ }
196
+
197
+ return {
198
+ after: startDate.toISOString(),
199
+ before: endDate.toISOString(),
200
+ };
201
+ };
202
+
203
+ //本日の日付から'YYYY/MM'形式の日付文字列を生成する
204
+ export const getTodayYearMonth = () => {
205
+ const today = new Date();
206
+ const year = today.getFullYear();
207
+ const month = String(today.getMonth() + 1).padStart(2, "0");
208
+ return `${year}/${month}`;
209
+ };
210
+ //本日の日付から年を返す
211
+ export const getTodayYear = () => {
212
+ const today = new Date();
213
+ return today.getFullYear();
214
+ };
215
+ //本日の日付から月を返す
216
+ export const getTodayMonth = () => {
217
+ const today = new Date();
218
+ return today.getMonth() + 1;
219
+ };
220
+
221
+ /* ------------------------------
222
+ カレンダー用グリッドAreasの生成関数
223
+ ------------------------------ */
224
+ const week = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
225
+ export const generateGridAreas = (firstDayOfMonth, totalDays, isMonday) => {
226
+ let areas = [];
227
+ let currentDay = 1;
228
+ //月曜日を先頭に持ってくる場合の係数
229
+ const mondayFirstDay = firstDayOfMonth - 1 < 0 ? 6 : firstDayOfMonth - 1;
230
+ //先頭曜日の選択
231
+ const modifyFirstDay = isMonday ? mondayFirstDay : firstDayOfMonth;
232
+
233
+ //曜日ラベル
234
+ let weekLabels = [];
235
+ let week_index;
236
+ for (let i = 0; i < 7; i++) {
237
+ week_index = isMonday ? i + 1 : i; //月曜日を先頭に持ってくる場合の補正
238
+ if (week_index > 6) week_index = 0;
239
+ weekLabels.push(week[week_index]);
240
+ }
241
+ areas.push(weekLabels.join(" "));
242
+
243
+ for (let i = 0; i < 6; i++) {
244
+ // 6週分のループ
245
+ let week = [];
246
+ for (let j = 0; j < 7; j++) {
247
+ // 1週間の7日分のループ
248
+ if ((i === 0 && j < modifyFirstDay) || currentDay > totalDays) {
249
+ week.push(`empty${i}`);
250
+ } else {
251
+ week.push(`day${currentDay}`);
252
+ currentDay++;
253
+ }
254
+ }
255
+ if (i == 5) {
256
+ //最後の週
257
+ week[5] = "day_clear";
258
+ week[6] = "day_clear";
259
+ }
260
+ areas.push(week.join(" "));
261
+ }
262
+ return areas.map((week) => `"${week}"`).join("\n");
263
+ };
264
+
265
+ export const JapaneseHolidays = async (apiKey, targetMonth) => {
266
+ //Google API Client Libraryをプロジェクトに追加する(非同期で読み込み)
267
+ const loadGoogleAPI = () => {
268
+ return new Promise((resolve, reject) => {
269
+ //window.gapi の存在を直接チェック
270
+ if (window.gapi) {
271
+ resolve();
272
+ return;
273
+ }
274
+
275
+ const script = document.createElement("script");
276
+ script.src = "https://apis.google.com/js/api.js";
277
+ script.async = true;
278
+ script.defer = true;
279
+ //スクリプトがロードされたときのイベントハンドラ
280
+ script.onload = () => {
281
+ // gapiがロードされるまでチェックを繰り返す
282
+ const checkGapi = () => {
283
+ if (window.gapi) {
284
+ resolve();
285
+ } else {
286
+ setTimeout(checkGapi, 20); // Check again after 20ms
287
+ }
288
+ };
289
+ checkGapi();
290
+ };
291
+
292
+ script.onerror = () =>
293
+ reject(new Error("Failed to load Google API script"));
294
+
295
+ // Check if the script is already in the document
296
+ if (
297
+ !document.querySelector(
298
+ 'script[src="https://apis.google.com/js/api.js"]'
299
+ )
300
+ ) {
301
+ document.body.appendChild(script);
302
+ }
303
+ });
304
+ };
305
+ //APIキーを使用してクライアントを初期化する
306
+ const initClient = async () => {
307
+ if (!window.gapi) {
308
+ throw new Error("Google API not loaded");
309
+ }
310
+
311
+ // Check if gapi.client is already available
312
+ if (!window.gapi.client) {
313
+ // If not, load the client module
314
+ await new Promise((resolve) => window.gapi.load("client", resolve));
315
+ }
316
+
317
+ if (window.gapi.client.calendar) {
318
+ return;
319
+ }
320
+ await window.gapi.client.init({
321
+ apiKey: apiKey,
322
+ discoveryDocs: [
323
+ "https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest",
324
+ ],
325
+ });
326
+ };
327
+ //祝日データの取得
328
+ const fetchHolidays = async () => {
329
+ const periodObj = getPeriodQuery(targetMonth);
330
+
331
+ const response = await window.gapi.client.calendar.events.list({
332
+ calendarId: CALENDAR_ID,
333
+ timeMin: periodObj.after,
334
+ timeMax: periodObj.before,
335
+ singleEvents: true,
336
+ orderBy: "startTime",
337
+ });
338
+
339
+ const events = response.result.items;
340
+ return events.map((event) => ({
341
+ date: event.start.date,
342
+ name: event.summary,
343
+ }));
344
+ };
345
+
346
+ try {
347
+ await loadGoogleAPI();
348
+ await initClient();
349
+ return await fetchHolidays();
350
+ } catch (error) {
351
+ console.error("エラーが発生しました:", error);
352
+ throw error;
353
+ }
354
+ };
@@ -1,5 +1,4 @@
1
-
2
- import { __ } from '@wordpress/i18n';
1
+ import { __ } from "@wordpress/i18n";
3
2
 
4
3
  import {
5
4
  TextControl,
@@ -7,59 +6,61 @@ import {
7
6
  RadioControl,
8
7
  ComboboxControl,
9
8
  __experimentalUnitControl as UnitControl,
10
- } from '@wordpress/components';
11
-
12
- import {
13
- PanelColorSettings
14
- } from '@wordpress/block-editor';
9
+ } from "@wordpress/components";
15
10
 
11
+ import { PanelColorSettings } from "@wordpress/block-editor";
16
12
 
17
13
  const helpLink = createElement(
18
- 'a',
19
- { href: 'https://fontawesome.com/search', target: '_blank' },
20
- 'FontAwesome'
14
+ "a",
15
+ { href: "https://fontawesome.com/search", target: "_blank" },
16
+ "FontAwesome"
21
17
  );
22
18
 
23
19
  const helpTextCode = createElement(
24
- 'span',
20
+ "span",
25
21
  {},
26
22
  helpLink,
27
- __('Select the icon from and enter Unicode (the upper right four digits of the selection dialog). ', 'block-collections')
23
+ __(
24
+ "Select the icon from and enter Unicode (the upper right four digits of the selection dialog). ",
25
+ "block-collections"
26
+ )
28
27
  );
29
28
 
30
29
  const helpTextFamily = createElement(
31
- 'span',
30
+ "span",
32
31
  {},
33
32
  helpLink,
34
- __('Please select the first class name shown in the HTML code field of the selection dialog. ', 'block-collections')
33
+ __(
34
+ "Please select the first class name shown in the HTML code field of the selection dialog. ",
35
+ "block-collections"
36
+ )
35
37
  );
36
38
 
37
-
38
39
  const units = [
39
- { value: 'px', label: 'px' },
40
- { value: 'em', label: 'em' },
41
- { value: 'rem', label: 'rem' },
40
+ { value: "px", label: "px" },
41
+ { value: "em", label: "em" },
42
+ { value: "rem", label: "rem" },
42
43
  ];
43
44
 
44
45
  const family_option = [
45
- { value: 'Font Awesome 6 Free', label: 'SOLID' },
46
- { value: 'Font Awesome 6 Brands', label: 'BRANDS' },
47
- ]
46
+ { value: "Font Awesome 6 Free", label: "SOLID" },
47
+ { value: "Font Awesome 6 Brands", label: "BRANDS" },
48
+ ];
48
49
 
49
- export default ({ iconStyle, onChange }) => {
50
+ export default ({ iconStyle, setPosition, onChange }) => {
50
51
  const {
51
52
  icon_name,
52
53
  icon_pos,
53
54
  icon_size,
54
55
  icon_color,
55
56
  icon_space,
56
- icon_family
57
+ icon_family,
57
58
  } = iconStyle;
58
59
 
59
60
  return (
60
61
  <>
61
62
  <TextControl
62
- label={__("icon name", 'block-collections')}
63
+ label={__("icon name", "block-collections")}
63
64
  help={helpTextCode}
64
65
  labelPosition="top"
65
66
  value={icon_name}
@@ -71,41 +72,43 @@ export default ({ iconStyle, onChange }) => {
71
72
  />
72
73
 
73
74
  <ComboboxControl
74
- label={__('Icon Family', 'block-collections')}
75
+ label={__("Icon Family", "block-collections")}
75
76
  help={helpTextFamily}
76
77
  options={family_option}
77
- value={icon_family ? icon_family : 'Font Awesome 6 Free'}
78
+ value={icon_family ? icon_family : "Font Awesome 6 Free"}
78
79
  onChange={(newValue) => {
79
80
  const newStyle = { ...iconStyle, icon_family: newValue };
80
81
  onChange(newStyle);
81
82
  }}
82
83
  />
83
84
 
84
- <PanelRow className='sizing_row'>
85
+ <PanelRow className="sizing_row">
85
86
  <UnitControl
86
87
  dragDirection="e"
87
88
  onChange={(newValue) => {
88
89
  const newStyle = { ...iconStyle, icon_size: newValue };
89
90
  onChange(newStyle);
90
91
  }}
91
- label={__("Size", 'block-collections')}
92
+ label={__("Size", "block-collections")}
92
93
  value={icon_size}
93
94
  units={units}
94
95
  />
95
- <UnitControl
96
- dragDirection="e"
97
- onChange={(newValue) => {
98
- const newStyle = { ...iconStyle, icon_space: newValue };
99
- onChange(newStyle);
100
- }}
101
- label={__('spacing to end', 'block-collections')}
102
- value={icon_space}
103
- units={units}
104
- />
96
+ {setPosition && (
97
+ <UnitControl
98
+ dragDirection="e"
99
+ onChange={(newValue) => {
100
+ const newStyle = { ...iconStyle, icon_space: newValue };
101
+ onChange(newStyle);
102
+ }}
103
+ label={__("spacing to end", "block-collections")}
104
+ value={icon_space}
105
+ units={units}
106
+ />
107
+ )}
105
108
  </PanelRow>
106
109
 
107
110
  <PanelColorSettings
108
- title={__('Color settings', 'itmar_location')}
111
+ title={__("Color settings", "itmar_location")}
109
112
  initialOpen={false}
110
113
  colorSettings={[
111
114
  {
@@ -114,26 +117,30 @@ export default ({ iconStyle, onChange }) => {
114
117
  const newStyle = { ...iconStyle, icon_color: newValue };
115
118
  onChange(newStyle);
116
119
  },
117
- label: __('Icon color', 'itmar_location')
120
+ label: __("Icon color", "itmar_location"),
118
121
  },
119
-
120
122
  ]}
121
123
  />
122
- <label className="components-base-control__label">{__("Arrangement", 'block-collections')}</label>
123
- <PanelRow className='itmar_position_row'>
124
- <RadioControl
125
- selected={icon_pos}
126
- options={[
127
- { label: __("left", 'block-collections'), value: "left" },
128
- { label: __("right", 'block-collections'), value: "right" },
129
- ]}
130
- onChange={(newValue) => {
131
- const newStyle = { ...iconStyle, icon_pos: newValue };
132
- onChange(newStyle);
133
- }}
134
- />
135
- </PanelRow>
124
+ {setPosition && (
125
+ <>
126
+ <label className="components-base-control__label">
127
+ {__("Arrangement", "block-collections")}
128
+ </label>
129
+ <PanelRow className="itmar_position_row">
130
+ <RadioControl
131
+ selected={icon_pos}
132
+ options={[
133
+ { label: __("left", "block-collections"), value: "left" },
134
+ { label: __("right", "block-collections"), value: "right" },
135
+ ]}
136
+ onChange={(newValue) => {
137
+ const newStyle = { ...iconStyle, icon_pos: newValue };
138
+ onChange(newStyle);
139
+ }}
140
+ />
141
+ </PanelRow>
142
+ </>
143
+ )}
136
144
  </>
137
-
138
145
  );
139
- }
146
+ };
@@ -0,0 +1,10 @@
1
+ //ネストしたブロックを平坦化
2
+ export const flattenBlocks = (blocks) => {
3
+ return blocks.reduce((acc, block) => {
4
+ acc.push(block);
5
+ if (block.innerBlocks && block.innerBlocks.length > 0) {
6
+ acc.push(...flattenBlocks(block.innerBlocks));
7
+ }
8
+ return acc;
9
+ }, []);
10
+ };