itmar-block-packages 1.3.7 → 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.
@@ -1,4 +1,5 @@
1
1
  import { useRef, useEffect, useState } from "@wordpress/element";
2
+ import { useSelect, useDispatch } from "@wordpress/data";
2
3
  import isEqual from "lodash/isEqual";
3
4
 
4
5
  //useRefで参照したDOM要素の大きさを取得するカスタムフック
@@ -141,3 +142,110 @@ export function useFontawesomeIframe() {
141
142
  }
142
143
  }, []);
143
144
  }
145
+
146
+ //ネストしたブロックを平坦化
147
+ const getFlattenBlocks = (blocks) => {
148
+ return blocks.reduce((acc, block) => {
149
+ acc.push(block);
150
+ if (block.innerBlocks && block.innerBlocks.length > 0) {
151
+ acc.push(...getFlattenBlocks(block.innerBlocks));
152
+ }
153
+ return acc;
154
+ }, []);
155
+ };
156
+
157
+ //指定されたブロック名とクラス名を含むブロックの属性が更新されたときその更新内容をかえすフック
158
+ export function useBlockAttributeChanges(
159
+ clientId,
160
+ blockName,
161
+ className,
162
+ modFlg = false,
163
+ excludeAttributes = {}
164
+ ) {
165
+ const [latestAttributes, setLatestAttributes] = useState(null);
166
+ //const [idleFlg, setIdleFlg] = useState(null);
167
+ const prevBlocksRef = useRef({});
168
+
169
+ //属性変更関数を取得
170
+ const { updateBlockAttributes } = useDispatch("core/block-editor");
171
+ //インナーブロックを平坦化する関数
172
+ const flattenedBlocks = useSelect(
173
+ (select) => {
174
+ const { getBlock } = select("core/block-editor");
175
+ const rootBlock = getBlock(clientId);
176
+ return rootBlock ? getFlattenBlocks([rootBlock]) : [];
177
+ },
178
+ [clientId]
179
+ );
180
+
181
+ const targetBlocks = flattenedBlocks.filter(
182
+ (block) =>
183
+ block.name === blockName &&
184
+ block.attributes.className?.includes(className)
185
+ );
186
+
187
+ useEffect(() => {
188
+ //平坦化されたブロックを調査
189
+ for (const block of targetBlocks) {
190
+ const prevAttributes =
191
+ prevBlocksRef.current[block.clientId]?.attributes || {};
192
+ //既に先に記録された属性があることをチェック
193
+ if (Object.keys(prevAttributes).length > 0) {
194
+ // 除外する属性を取り除いた属性オブジェクトを作成
195
+ const filteredCurrentAttributes = Object.keys(block.attributes).reduce(
196
+ (acc, key) => {
197
+ if (!excludeAttributes.hasOwnProperty(key)) {
198
+ acc[key] = block.attributes[key];
199
+ }
200
+ return acc;
201
+ },
202
+ {}
203
+ );
204
+
205
+ const filteredPrevAttributes = Object.keys(prevAttributes).reduce(
206
+ (acc, key) => {
207
+ if (!excludeAttributes.hasOwnProperty(key)) {
208
+ acc[key] = prevAttributes[key];
209
+ }
210
+ return acc;
211
+ },
212
+ {}
213
+ );
214
+
215
+ //属性の変化を比較
216
+ if (
217
+ JSON.stringify(filteredCurrentAttributes) !==
218
+ JSON.stringify(filteredPrevAttributes)
219
+ ) {
220
+ //確認ダイアログが出ている状態か否かで状態変数を変化させる
221
+ // if (block.attributes.isIdle) {
222
+ // setIdleFlg(true);
223
+ // } else {
224
+ // setIdleFlg(false);
225
+ // }
226
+ //呼び出し元に返すための更新後の属性オブジェクトを格納
227
+ setLatestAttributes(JSON.stringify(filteredCurrentAttributes));
228
+ }
229
+ }
230
+ // 現在のブロック状態を保存(除外属性も含めて保存)
231
+ prevBlocksRef.current[block.clientId] = { ...block };
232
+ }
233
+ }, [targetBlocks, blockName, className]);
234
+
235
+ //innerFlattenedBlocks内の同一種のブロックに対して属性をセットする;
236
+ useEffect(() => {
237
+ //確認ダイアログが処理されたことを確認してからこちらの処理を進める
238
+ if (latestAttributes && modFlg) {
239
+ // const latestAttrObj = JSON.parse(latestAttributes);
240
+ // const setObj = {
241
+ // ...latestAttrObj,
242
+ // className: `auto_attr_change ${latestAttrObj.className}`,
243
+ // };
244
+ targetBlocks.forEach((block) => {
245
+ updateBlockAttributes(block.clientId, JSON.parse(latestAttributes));
246
+ });
247
+ }
248
+ }, [latestAttributes]);
249
+
250
+ return JSON.parse(latestAttributes);
251
+ }
package/src/index.js CHANGED
@@ -6,6 +6,7 @@ export {
6
6
  useIsMobile,
7
7
  useDeepCompareEffect,
8
8
  useFontawesomeIframe,
9
+ useBlockAttributeChanges,
9
10
  } from "./customFooks";
10
11
 
11
12
  //WordPressデータを取得するためのRestAPI
@@ -69,3 +70,19 @@ export { default as BlockEditWrapper } from "./BlockEditWrapper";
69
70
 
70
71
  //色コードの変換関数
71
72
  export { hslToRgb16, rgb16ToHsl, HexToRGB } from "./hslToRgb";
73
+
74
+ //日付関連の関数、コントロール
75
+ export {
76
+ generateDateArray,
77
+ generateMonthCalendar,
78
+ PeriodCtrl,
79
+ getPeriodQuery,
80
+ getTodayYearMonth,
81
+ getTodayYear,
82
+ getTodayMonth,
83
+ generateGridAreas,
84
+ JapaneseHolidays,
85
+ } from "./DateElm";
86
+
87
+ //インナーブロック関連の関数
88
+ export { flattenBlocks } from "./blockStore";
@@ -1,4 +1,5 @@
1
1
  import { useState, useEffect } from "@wordpress/element";
2
+ import { __ } from "@wordpress/i18n";
2
3
  import {
3
4
  ComboboxControl,
4
5
  CheckboxControl,
@@ -52,7 +53,14 @@ const SelectControl = (props) => {
52
53
 
53
54
  //選択コントロールのレンダリング関数
54
55
  const ChoiceControl = (props) => {
55
- const { selectedSlug, choiceItems, type, fetchFunction } = props;
56
+ const {
57
+ selectedSlug,
58
+ choiceItems,
59
+ type,
60
+ blockMap,
61
+ textDomain,
62
+ fetchFunction,
63
+ } = props;
56
64
  const [choices, setChoices] = useState([]);
57
65
  useEffect(() => {
58
66
  if (!selectedSlug) return; //ポストタイプのスラッグが選択されていないときは処理終了
@@ -82,11 +90,15 @@ const ChoiceControl = (props) => {
82
90
  };
83
91
 
84
92
  //階層化されたカスタムフィールドのフィールド名を表示する関数
93
+ let groupLabel = "";
85
94
  const dispCustumFields = (obj, prefix = "", onChange) => {
86
95
  return Object.entries(obj).map(([key, value]) => {
87
- const fieldName = prefix ? `${prefix}.${key}` : key;
88
- const fieldLabel = key;
96
+ const fieldName = prefix ? `${prefix}.${key}` : key; //prefixはグループ名
97
+
98
+ const fieldLabel = key.replace(/^(meta_|acf_)/, "");
99
+
89
100
  if (typeof value === "object" && value !== null) {
101
+ groupLabel = `${fieldLabel}.`;
90
102
  return (
91
103
  <div className="group_area">
92
104
  <div className="group_label">{fieldLabel}</div>
@@ -96,20 +108,43 @@ const ChoiceControl = (props) => {
96
108
  </div>
97
109
  );
98
110
  } else {
99
- if (key === "_acf_changed") return; //_acf_changedは対象外
111
+ if (key === "meta__acf_changed" || key === "meta_footnotes") return; //_acf_changedは対象外
112
+
113
+ //フィールドを表示するブロックの選択肢
114
+ const options = [
115
+ { value: "itmar/design-title", label: "itmar/design-title" },
116
+ { value: "core/paragraph", label: "core/paragraph" },
117
+ { value: "core/image", label: "core/image" },
118
+ ];
100
119
  return (
101
- <ToggleControl
102
- key={fieldName}
103
- className="field_choice"
104
- label={fieldLabel}
105
- checked={choiceItems.some(
106
- (choiceField) => choiceField === fieldName
107
- )}
108
- onChange={(checked) => {
109
- const newChoiceFields = handleChoiceChange(checked, fieldName);
110
- props.onChange(newChoiceFields);
111
- }}
112
- />
120
+ <div className="itmar_custom_field_set">
121
+ <ToggleControl
122
+ key={fieldName}
123
+ className="field_choice"
124
+ label={fieldLabel}
125
+ checked={choiceItems.some(
126
+ (choiceField) => choiceField === fieldName
127
+ )}
128
+ onChange={(checked) => {
129
+ const newChoiceFields = handleChoiceChange(checked, fieldName);
130
+ props.onChange(newChoiceFields);
131
+ }}
132
+ />
133
+ <ComboboxControl
134
+ options={options}
135
+ value={
136
+ blockMap[`${prefix ? groupLabel : ""}${fieldLabel}`] ||
137
+ "itmar/design-title"
138
+ }
139
+ onChange={(newValue) => {
140
+ const fieldKey = prefix
141
+ ? `${groupLabel}${fieldLabel}`
142
+ : `${fieldLabel}`;
143
+ const newBlockMap = { ...blockMap, [fieldKey]: newValue };
144
+ props.onBlockMapChange(newBlockMap);
145
+ }}
146
+ />
147
+ </div>
113
148
  );
114
149
  }
115
150
  });
@@ -157,7 +192,7 @@ const ChoiceControl = (props) => {
157
192
  {choice.title && (
158
193
  <ToggleControl
159
194
  className="field_choice"
160
- label="タイトル"
195
+ label={__("Title", textDomain)}
161
196
  checked={choiceItems.some(
162
197
  (choiceField) => choiceField === "title"
163
198
  )}
@@ -217,10 +252,28 @@ const ChoiceControl = (props) => {
217
252
  )}
218
253
  {(choice.meta || choice.acf.length > 0) && (
219
254
  <>
220
- <div className="custom_field_label">カスタムフィールド</div>
255
+ <div className="custom_field_label">
256
+ {__("Custom Field", textDomain)}
257
+ </div>
221
258
  <div className="custom_field_area">
222
- {choice.meta && dispCustumFields(choice.meta)}
223
- {choice.acf && dispCustumFields(choice.acf)}
259
+ <div className="custom_field_area">
260
+ {dispCustumFields({
261
+ ...Object.entries(choice.meta).reduce(
262
+ (acc, [key, value]) => ({
263
+ ...acc,
264
+ [`meta_${key}`]: value,
265
+ }),
266
+ {}
267
+ ),
268
+ ...Object.entries(choice.acf).reduce(
269
+ (acc, [key, value]) => ({
270
+ ...acc,
271
+ [`acf_${key}`]: value,
272
+ }),
273
+ {}
274
+ ),
275
+ })}
276
+ </div>
224
277
  </div>
225
278
  </>
226
279
  )}