# 概要
WordPressのカスタムブロックを作成するためのプラグインで活用するパッケージです。複数のプラグインで共通に使用する機能をパッケージにまとめました。
v3.0.0 より完全な TypeScript 対応となり、開発時の型補完と安全性が大幅に向上しました。

# 使用方法
```typescript
import { 関数名又はコンポーネント名 } from "itmar-block-packages"
```
名前付きインポートでお願いします。

## 必要条件
このパッケージは WordPress ブロック開発のビルド環境（`@wordpress/scripts`）での利用を前提としています。  
TypeScript で利用する場合、以下のバージョン以上を推奨します。

@wordpress/scripts: ^27.6.0 以上

typescript: ^5.0.0 以上

## 更新履歴

= 3.2.1 =
ArrowDirection,IconStyleのタイプをエクスポートした

= 3.2.0 =
styleDataApplyを新設し、フロントエンドでのスタイル付与をstyled-componetsを使用しないようにした。

= 3.1.5 =
useStyleIframeをuseEffectで読み込むように改修した。

= 3.1.2 =
styleComponentApplyでstyle要素が重複して登録されるのを避けるようにした。

= 3.1.1 =
ログ表示の微修正

= 3.1.0 =
useStyleIframeとstyleComponentApplyを新設

= 3.0.4 =
ShadowStyleで発生していた無限ループを解消
ShadowStateをインターフェースとしてエクスポート
FieldChoiceControlの不具合を修正

= 3.0.3 =
ブロック間の通信をおこなうインターフェースを付加

= 3.0.1 =

完全 TypeScript 化: 全ソースコードを TypeScript で再構築し、型定義ファイル（.d.ts）を同梱。

ビルド構成の最適化: Rollup により ESM (build/esm) と CJS (build/cjs) を出力。

パッケージ構造の整理: peerDependencies を整理し、WordPress コアライブラリとの重複バンドルを防止。

= 2.1.2 =  
- sendRegistrationRequest内でフォールバックされていた"/wp-admin/admin-ajax.php" を削除

= 2.1.1 =  
- フロントエンドデータ共有ライブラリとしてpickupStoreを追加

= 2.0.4 =  
- JapaneseHolidaysのgetPeriodQueryのインポート漏れを修正

= 2.0.3 =  
- IconSelectControlのcreateElementのインポート漏れを修正

= 2.0.0 =
- ビルド方式を Rollup に変更（ESM 出力を優先し、未使用コードがバンドルされにくい構成に改善）
- build 出力を ESM/CJS に分離（tree-shaking の効率と将来互換性を向上）
- package.json の exports を整備（利用側の bundler が最適な形式を選べるよう改善）
- 破壊的変更: 配布物の構成を build/index.js から build/esm・build/cjs に変更（インポート方法は従来通り）

= 1.11.1 =  
- generateMonthCalendarで祝日判定に誤りがあったところを修正

= 1.11.0 =  
- PostSelectControlを新設

= 1.10.1 =  
- PageSelectControlで固定ページの選択肢が１０個しか表示されないという不具合を解消

= 1.10.0 =  
- useRebuildChangeFieldを新設。
- FieldChoiceControlについてacfフィールドの付加情報をフィールド選択項目として表示されていたものを表示しないように修正。また、gallaryについては画像を個別に選択するのではなく全体を選択するように修正
- FieldChoiceControlについて、指定された投稿タイプに紐づかないフィールドが選択項目に含まれる場合、それを除外する機能を備えた。

= 1.9.0 =  
- shopfiApi.jsを新設。

= 1.8.0 =  
- formatCreate.jsを新設。Gutenberg ブロックにおける数値・日付・自由書式の表示形式を選択・制御するための UI コンポーネントおよびフォーマット関数を含みます。
  
= 1.7.1 =  
- serializeBlockTree,createBlockTreeをblockStore.jsに加えた。
- BlockPlace.jsでdesign-groupがフレックス要素の場合は主軸の大きさの設定がflex-grow,flex-shrink,flex-basisとなるよう修正した加えた。

= 1.7.0 =  
- バリデーションチェック用の関数を集めるためのvalidationCheck.jsを新設し、URLの形式をチェックするisValidUrlWithUrlApiを加えた。

= 1.6.3 =  
- IconSelectControlに設定できるアイコンをFontAwesomeに加え、画像、アバターを選択できるようにした

= 1.6.0 =  
- fetchZipToAddressを新設  

= 1.5.0 =  
- useTargetBlocksを新設  

= 1.4.3 =  
- UpdateAllPostsBlockAttributesコンポーネントのRestAPIによる更新の不具合を修正

= 1.4.2 =  
- UpdateAllPostsBlockAttributesコンポーネントにonProcessStartのコールバック関数の処理を付加
- parse, serializeのimport漏れを修正
- 最初の100投稿までの処理しか対応できなかったものをページング処理で上限なしに改良

= 1.4.1 =  
- UpdateAllPostsBlockAttributesコンポーネントの宣言の誤りを修正

= 1.4.0 =  
- 指定した投稿タイプの投稿に含まれる特定のブロックの属性を書き換えるコンポーネントであるUpdateAllPostsBlockAttributesコンポーネントを追加

= 1.3.21 =  
- FieldChoiceControlで先頭の投稿にアイキャッチ画像が設定されていないとき、フィールド選択のトグルボタンが表示されないという不具合を修正

= 1.3.20 =  
- PageSelectControlでhomeUrlをエディタのホームURLに固定しないようにした。  

= 1.3.19 =  
- FieldChoiceControlの選択可能フィールドにlinkを加えて、個別投稿ページへのリンク設定を可能にした。
- BlockPlaceのフレックスボックスの配置に交差軸の配置を加えた。
- TermChoiceControlでタームの表示をするか否かの選択を設定できるようにした。

= 1.3.18 =  
- WordPress RestAPIのエンドポイントを文字列で受けて、その結果を返すrestFetchDataを新設
- TermChoiceControlでonChangeコールバックで返す引数にterm.nameを加えた。
- BlockPlaceコンポーネントのフレックススタイルに折り返しを設定できるように機能追加
- BlockPlaceコンポーネント内のブロック幅とブロック高の設定をBlockWidthとBlockHeightの各コンポーネントを利用するように変更
- BlockWidthに幅と最大幅を別々に設定できるように機能追加
- BlockPlaceコンポーネント内の横方向ブロック配置をフレックス、グリッドスタイルでも設定できるように修正  

= 1.3.17 =  
- restFieldesをインポートするため、エクスポート項目に加えた。

= 1.3.16 =  
- インスペクターの表示の国際化されていない部分を国際化した。

= 1.3.15 =  
- BlockPlaceのプロプスに視差効果のフラグを与え、そのフラグがtrueの時は中央揃えのセットができないように制御するようにした

= 1.3.14 =  
- position_prmの中央揃えがセットされていない場合にnullが出力されるという不具合を修正

= 1.3.13 =  
- BlockWidthのラベル表示が誤っていたのを修正

= 1.3.12 =  
- BlockPlaceの配置タイプが絶対位置の場合に縦横の中央揃えが設定できる機能を追加
- 中央揃えができるようにしたために、position_prmにそれに対応するCSSプロパティを返す機能を追加

= 1.3.11 =  
- BlockPlace、BlockWidth、BlockHeightのfreeサイズにpx以外の単位を設定できるように修正
- freeサイズにpx以外の単位を設定できるようにしたことから、max_width_prm、width_prm、height_prmがそれに対応できるように修正

= 1.3.10 =  
- useDuplicateBlockRemoveの不具合を修正。
- ブロックの幅、高さを設定するためのコンポーネントとしてBlockWidth、BlockHeightを追加

= 1.3.9 =  
- カスタムフックとしてuseDuplicateBlockRemoveを追加。このフックはインナーブロックが挿入されたとき、指定されたブロック名が存在れば、挿入されたブロックを削除する。

= 1.3.8 =  
- WordPressのデータをRest APIを通して取得する関数等のFieldChoiceControlの機能として、choiceFieldsに登録されるフィールド名がmetaによるカスタムフィールドかacfによるカスタムフィールドかを峻別できるようにフィールド名にmeta_又はacf_という接頭辞を付加するようにした。
- カスタムフックとしてuseBlockAttributeChangesを追加。このフックはitmar/design-group内のブロックで、指定のブロック名とクラス名のブロックの属性に変化があったとき、その変化の内容を通知する機能をもつ。同一のブロック名とクラス名をもつブロックに対して、変化した属性を自動的に設定する機能もある。

= 1.3.4 =  
- BlockPlaceコンポーネントの高さにフリーサイズを追加し、デスクトップとモバイルでそれぞれ設定を可能うにした。それに伴ってcssPropertesのheight_prmのシグニチャーを変更。

= 1.3.2 =  
- BlockPlaceコンポーネントのインナーブロックの方向で縦方向又は横方向を選択したとき反転の設定ができるようにした。

= 1.3.1 =  
- edit.scssおよびstyle.scssの共通スタイルについては機能しないことが判明したので削除した。

= 1.3.0 =  
- WordPressのデータをRest APIを通して取得する関数等に、次の関数とReactコンポーネントを追加した
 - restTaxonomies
 - TermChoiceControl
- edit.scssおよびstyle.scssを配置し、これをトランスパイルして、複数のプラグインから共通のスタイルとして使用できるようにした


# 各コンポーネント・関数の機能
## カスタムフック
### useIsIframeMobile
WordPressのエディタ（ブロックエディタ、サイトエディタ）の大きさを監視し、幅が767ピクセル以下であればtrueを返します。
```
const is_mobile=useIsIframeMobile();
```

### useElementBackgroundColor
ブロックの背景色を返します。ユーザー設定で指定されていれば、その色を返し、指定されていないか、カスタムプロパティ（--wpで始まるプロパティ）であれば、getComputedStyleで実際にレンダリングされた色を取得します。
#### 引数
- `blockRef`  
ブロックへの参照。useRefで取得
- `style`  
ブロックに設定されているスタイル。useBlockPropsで取得
```
//ブロックの参照
const blockRef = useRef(null);
//blockPropsの参照
const blockProps = useBlockProps({
	ref: blockRef, // ここで参照を blockProps に渡しています
});

//背景色の取得
const baseColor = useElementBackgroundColor(blockRef, blockProps.style);
```

### useElementWidth

### useIsMobile
ViewPortの大きさの大きさを監視し、幅が767ピクセル以下であればtrueを返します。
```
const is_mobile=useIsMobile();
```
### useDeepCompareEffect
たくさんの要素をもつオブジェクトや配列の内容の変化で発火するuseEffect
#### 引数
- `callback` func  
発火させたい関数
- `dependencies` array  
依存変数にしたい配列
```
useDeepCompareEffect(() => {
・・・
},
[attributes])

```
### useFontawesomeIframe
iframeにfontawesomeを読み込むカスタムフック

### useBlockAttributeChanges
特定のブロックの属性が変更されたとき、その変更内容を返すカスタムフック。引数に指定されたブロック名のブロックで指定されたクラス名をもつブロックの属性の変更内容を返す。第3引数のフラグにtrueを指定すると同じブロック名で同じクラス名をもつブロックの属性を変更されたブロックの属性で自動的に更新する。ただし、変更内容については、指定された属性名の属性を変更及び比較の対象からはずすことができる。  

#### 引数
- `clientId` string  
変更されたことを監視する範囲となるitmar/design-groupブロックのclientId
- `blockName` string  
変更の監視対象となるブロック名
- `className` string  
変更の監視対象となるブロックが有するクラス名
- `modFlg` boolean  
同種ブロックを更新するかどうかのフラグ。デフォルトはfalse
- `excludeAttributes` object  
自動更新の対象から除外する属性をオブジェクトで指定する。オブジェクトは属性名をキーとし、値を適宜のデフォルト値とする。ここで指定された属性は更新チェックの対象からも除外される。使わないときは指定しない。
```
//clientIdで指定されたブロックの属性変更の内容を返す
const changedAttributes = useBlockAttributeChanges(
	clientId,
	"itmar/design-checkbox",
	"itmar_filter_checkbox",	
);

//clientIdで指定されたブロックの属性変更の内容でitmar/design-checkboxという名前のブロックで
//itmar_filter_checkboxというクラス名をもつブロックの属性を自動更新する。
//ただし、labelContentという属性とinputValueという属性については更新対象から除外する
useBlockAttributeChanges(
	clientId,
	"itmar/design-checkbox",
	"itmar_filter_checkbox",
	true,
	{ labelContent: "", inputValue: false },
);

```

### useDuplicateBlockRemove
インナーブロックが挿入されたとき、指定されたブロック名が存在れば、挿入したブロックを削除する。ユーザーに重複したブロックを挿入させたくないときや特定のブロックが存在するとき、ブロックを挿入させないようにするときに活用する。  

#### 引数
- `clientId` string  
インナーブロックの監視する対象となるブロックのclientId
- `blockNames` array  
存在をチェックするブロック名。文字列を配列で指定する。

```
useDuplicateBlockRemove(clientId, ["itmar/pickup-posts"]);

```

## styled-componet用のcssプロパティ生成関数
styled-componetのcssヘルパー関数内で使用するcssのパラメーターやプロパティを返します。
### radius_prm
border-radiusに設定するプロパティを文字列で返します。
#### 引数
- `radius` object  
topLeft,topRight,bottomRight,bottomLeftをキーとしてもつオブジェクト
  

### space_prm
marginやpaddingに設定するプロパティを文字列で返します。
#### 引数
- `space` object  
top,right,bottom,leftをキーとしてもつオブジェクト

### position_prm
絶対位置のポジションに関するCSSを返します。
#### 引数
- `pos` object,boolean  
次の形式のオブジェクト又はboolean
```
"posValue": {
	"vertBase": "top",
	"horBase": "left",
	"vertValue": "3em",
	"horValue": "3em",
	"isVertCenter": false,
	"isHorCenter": false
},
```

- `type` string
staic, relative,absolute,fixed,stickyのいづれか

#### 戻り値
- typeがabsolute,fixed,stickyのときposの値に応じてtop,buttom,left,rightのcssプロパティを返す。  pos内の中央揃えのフラグがオンならtransformのcssプロパティも返す。
- posがtrueのとき`top:50%;left: 50%;transform: translate(-50%, -50%);`を返す。
  

### max_width_prm
最大幅を設定するためのCSSを返します。
#### 引数
- `width` string  
wideSize,contentSize,free,fullの文字列
- `free_val` string  
px値
#### 戻り値
- wideSizeのとき`width: 100%; max-width: var(--wp--style--global--wide-size);`  
- contentSizeのとき`width: 100%; max-width: var(--wp--style--global--content-size);`  
- freeのとき`width: 100%; max-width: ${free_val};`  
- fullのとき`width: 100%; max-width: 100%;`  
- その他の文字列`width: fit-content;`  
  

### width_prm
widthのCSSを返します。
#### 引数
- `width` string  
wideSize,contentSize,freeの文字列
- `free_val` string  
px値
#### 戻り値
- wideSizeのとき`width: var(--wp--style--global--wide-size);`
- contentSizeのとき`width: var(--wp--style--global--content-size);`
- freeのとき`width: ${free_val};`
- その他の文字列`width: fit-content;`
  

### height_prm
heightのCSSを返します。
#### 引数
- `height` string
fit, full, freeの文字列
- `free_val` string  
px値  
#### 戻り値
- fitのとき`height: fit-content;`
- freeのとき`height: ${free_val};`
- その他の文字列`height: 100%;`
  

### align_prm
marginによる横方向の配置のためのCSSを返します。
また、camelFlgを設定することで、インナースタイル用のオブジェクトを返します。
#### 引数
- `align` string
- `camelFLg` boolean  
center,rightの文字列
#### 戻り値
camelFLgがfalse又は設定されていないとき
- centerのとき`margin-left: auto; margin-right: auto;`
- rightのとき`margin-left: auto; margin-right: 0`
- その他の文字列`margin-right: auto; margin-left: 0`
camelFLgがtrueのとき
- centerのとき` { marginLeft: "auto", marginRight: "auto" }`
- rightのとき` { marginLeft: "auto" }`
- その他の文字列`{}`
  

### convertToScss
キャメルケースで与えられたstyleオブジェクトをscssの文字列に変換します。
#### 引数
- `styleObject` object  
ブロックに設定されたスタイルオブジェクト

```
const str_scss = convertToScss(styleObject)
```
  

### borderProperty
WordPressのBorderBoxControlコンポーネントが返すオブジェクトをキャメルケースのCSSに変換して返します。
#### 引数
- `borderObj` object  
WordPressのBorderBoxControlコンポーネントが返すオブジェクト

```
const css_obj = borderProperty(borderObj)
```
  

### radiusProperty
WordPressのBorderRadiusControlコンポーネントが返すオブジェクトをキャメルケースのCSSに変換して返します。
#### 引数
- `radiusObj` object  
WordPressのBorderRadiusControlコンポーネントが返すオブジェクト

```
const css_obj = radiusProperty(radiusObj)
```
   

### marginProperty
marginのcssを返します。
#### 引数
- `marginObj` object  
top,right,bottom,leftをキーとしてもつオブジェクト。オブジェクトの値は単位（px,em,%等）付きにしてください。
  

### paddingProperty
paddingのcssを返します。
#### 引数
- `paddingObj` object  
top,right,bottom,leftをキーとしてもつオブジェクト。オブジェクトの値は単位（px,em,%等）付きにしてください。
  

## ボックスシャドーを設定するコントロール
### ShadowStyle
WordPressのブロックエディタのサイドバーにbox-shadowを設定するためのコントロールを表示させるReactコンポーネント。
```
<ShadowStyle
	shadowStyle={{ ...shadow_element }}
	onChange={(newStyle, newState) => {
		setAttributes({ shadow_result: newStyle.style });
		setAttributes({ shadow_element: newState });
	}}
/>
```

<img src="./img/shadow.png" alt="ShadowStyleのスクリーンショット" width="500" height="500">
  
  
### ShadowElm
設定されたbox-shadowをスタイルオブジェクトとして返します。
#### 引数
- `shadowState` object  
ShadowStyleコンポーネントで生成され、ブロックの属性としてセットされるオブジェクト
  

## 疑似要素を設定するコントロール
### PseudoElm
WordPressのブロックエディタのサイドバーに疑似要素を設定するためのコントロールを表示させるReactコンポーネント。現時点のバージョンでは上下左右の矢印表示の設定のみが可能です。
```
<PseudoElm
	element="Arrow"
	direction={pseudoInfo.option}
	onChange={(direction) => {
		setAttributes({
			pseudoInfo: { ...pseudoInfo, option: direction },
		});
	}}
/>
```
<img src="./img/pseudo.png" alt="PseudoElmのスクリーンショット" width="200" height="100">

### Arrow
矢印を表示させる疑似要素を生成してscssの文字列で返します。
```
const arrow = Arrow(direction);

```
#### 引数
- `direction` object  
キーをdirection、値をupper,left,right,underのいずれかとするオブジェクト
  


## メディアライブラリから画像を選択するコントロール
### SingleImageSelect
メディアライブラリ選択画面を開き、ブロックの属性にmediaとmedia.idをセットします。
```
<SingleImageSelect
	attributes={attributes}
	onSelectChange={(media) => {
		setAttributes({ media: media, mediaID: media.id });
	}}
/>
```
### MultiImageSelect
メディアライブラリ選択画面を開き、複数の画像を選択して、ブロックの属性にmediaとmedia.idをセットします。
```
<MultiImageSelect
	attributes={attributes}
	label=__("Selected Images", "text-domain")
	onSelectChange={(media) => {
		// media から map で id プロパティの配列を生成
		const media_ID = media.map((image) => image.id);
		setAttributes({
			mobile_val: { ...mobile_val, mediaID: media_ID, media: media },
		});
		
	}}
	onAllDelete={() => {
		setAttributes({
			mobile_val: { ...mobile_val, mediaID: [], media: [] },
		});
	}}
/>
```
  
  
## ブロックのドラッガブルを設定するコントロール
### DraggableBox
ブロックを移動させる移動量を設定するコントロールをサイドバーに表示させます。
```
<DraggableBox
	attributes={position}
	onPositionChange={(position) =>
		setAttributes({ position: position })
	}
/>
```
  

### useDraggingMove
参照したブロックを可能とするためのカスタムフックを設定します。
```
useDraggingMove(
  isMovable,
  blockRef,
  position,
  onPositionChange
)
```
#### 引数
- `isMovable` boolean
移動を可とするかどうかのフラグ
- `blockRef` useRef  
移動させるブロックへの参照
- `position` object  
移動量を決定するためのx,yのキーをもつオブジェクト
- `onPositionChange` function
移動量が変化したときに属性値を記録するためのコールバック関数
  

## ブロックをlazy Loadさせるためのラッパーモジュール
## BlockEditWrapper
registerBlockTypeの第２引数内にあるeditオブジェクトに、以下の使用例で生成したBlockEditを渡してやることで、ブロックの読み込みをレンダリングの時まで遅らせます。

```
const LazyEditComponent = React.lazy(() => import("./edit"));
const BlockEdit = (props) => {
	return <BlockEditWrapper lazyComponent={LazyEditComponent} {...props} />;
};
```
## ブロックにアニメーション効果をあたえるためのコントロール
### AnimationBlock
WordPressのブロックエディタのサイドバーにアニメーションを設定するためのコントロールを表示させるReactコンポーネント。現時点のバージョンではflipDown,fadeUp,fadeLeft,fadeRightのアニメーション設定が可能です
```
<AnimationBlock
	attributes={attributes}
	onChange={(newValue) => setAttributes(newValue)}
/>
```
<img src="./img/animation.png" alt="AnimationBlockのスクリーンショット" width="100" height="200">

### anime_comp
設定されたアニメーションのパラメータをオブジェクトとして渡すことで、SCSSの文字列に変換して返します。
#### 引数
- `anime_prm` object  
AnimationBlockコンポーネントで生成され、ブロックの属性としてセットされるオブジェクト
  

## Typographyを設定するコントロール
### TypographyControls
WordPressのブロックエディタのサイドバーにTypographyを設定するためのコントロールを表示させるReactコンポーネント。
```
<TypographyControls
	title={__("Typography", "text-domain")}
	fontStyle=	
	{
		default_fontSize: "16px",
		mobile_fontSize: "12px",
		fontFamily: "Arial, sans-serif",
		fontWeight: "500",
		isItalic: false,
	}
	initialOpen={false}
	isMobile={isMobile}
	onChange={(newStyle) => {
		setAttributes({ font_style_input: newStyle });
	}}
/>
```
<img src="./img/typography.png" alt="Typographyのスクリーンショット" width="100" height="200">

## WordPressのデータをRest APIを通して取得する関数等
### fetchPagesOptions
固定ページの情報を取得して配列で返します。
#### 引数
- `homeUrl` string  
サイトのホームURL  

#### 戻り値
次のようなキーを持つオブジェクトの配列を返します。  
`value` 固定ページのid。ただし、サイトのホームについては-1をかえす。  
`slug` 固定ページのスラッグ  
`link` 固定ページのURL
`label` 固定ページの名称  

### fetchArchiveOptions
カスタム投稿タイプ（ビルトインを含む）の情報を取得して配列で返します。
#### 引数
- `homeUrl` string  
サイトのホームURL  

#### 戻り値
次のようなキーを持つオブジェクトの配列を返します。  
`value` 0から始まる通し番号  
`slug` ポストタイプのスラッグ  
`link` アーカイブページのURL
`label` ポストタイプの名称 

### restFetchData
RestAPIのエンドポイントを文字列で受けて、その結果を返す
#### 引数
- `path` string  
エンドポイント

#### 戻り値
エンドポイントに対応したレスポンスがPromiseで返る 

### restTaxonomies
投稿タイプに登録されているタクソノミー（カテゴリ、タグを含む）の情報およびそのタームの情報をを取得して配列で返します。
#### 引数
- `post_type` string  
投稿タイプのスラッグ  

#### 戻り値
次のようなキーを持つオブジェクトの配列を返します。  
`slug` タクソノミーのスラッグ 
`name` タクソノミーの名称  
`rest_base` タクソノミーのREST_APIの名称
`terms` ターム情報オブジェクトの配列 

### restFields
投稿タイプに登録されているタクソノミー（カテゴリ、タグを含む）の情報およびそのタームの情報をを取得して配列で返します。
#### 引数
- `rest_base` string  
投稿タイプのRestAPI用スラッグ  

#### 戻り値
"title","date","excerpt","featured_media","meta","acf"の各フィールドの値を投稿タイプの最新データ1件分を返す。この結果で投稿タイプがどのフィールドをサポートしているか、また、どのようなカスタムフィールドが設定されているかの情報を取得することができる。 

### PageSelectControl
固定ページを選択できるコンボボックス表示し、固定ページの情報を返します。
#### プロプス  
- `selectedSlug` string  
選択済みの固定ページのスラッグ 
- `label` string
コンボボックスのラベル  
- `homeUrl` string  
サイトのホームURL
- `onChange` func
コンボボックスの内容が変化したとき発生するコールバック関数。引数には`fetchPagesOptions`の戻り値が入る。 

```
<PageSelectControl
	selectedSlug={selectedSlug}
	label={__("Select Post Type", "post-blocks")}
	homeUrl={post_blocks.home_url}
	onChange={(postInfo) => {
		setAttributes({ selectedSlug: postInfo.slug });
	}}
/>
```

### ArchiveSelectControl
投稿タイプ名を選択できるコンボボックス表示し、投稿タイプの情報を返します。
#### プロプス  
- `selectedSlug` string  
選択済みの投稿タイプのスラッグ 
- `label` string
コンボボックスのラベル  
- `homeUrl` string  
サイトのホームURL
- `onChange` func
コンボボックスの内容が変化したとき発生するコールバック関数。引数には`fetchArchiveOptions`の戻り値が入る。 

```
<ArchiveSelectControl
	selectedSlug={selectedSlug}
	label={__("Select Post Type", "post-blocks")}
	homeUrl={post_blocks.home_url}
	onChange={(postInfo) => {
		setAttributes({ selectedSlug: postInfo.slug });
	}}
/>
```

### PostSelectControl
投稿（カスタム投稿タイプを含む）のタイトルを選択できるコンボボックスを表示し、選択した投稿の情報を返します。

#### プロプス
- `selectedSlug` string  
選択済みの投稿スラッグ

- `label` string  
コンボボックスのラベル

- `homeUrl` string  
サイトのホームURL

- `restBase` string  
取得対象の REST Base（例：`posts` / `pages` / `itmar_resource` など）  
※ `/wp/v2/{restBase}` を呼び出して投稿一覧を取得します。

- `status` string (optional)  
取得する投稿ステータス（デフォルト：`publish`）  
例：`any` を指定すると下書き等も含めて取得できます。

- `perPage` number (optional)  
1ページあたりの取得件数（最大100 / デフォルト：100）

- `orderby` string (optional)  
並び順のキー（デフォルト：`title`）

- `order` string (optional)  
並び順（デフォルト：`asc`）

- `search` string (optional)  
検索キーワード（指定した場合、RESTの `search` パラメータで絞り込みます）

- `onChange` func  
コンボボックスの内容が変化したとき発生するコールバック関数。  
引数には `fetchPostOptions` の戻り値（options配列の要素）が入ります。

#### 返却される情報（onChange の引数例）
- `value` number（投稿ID）
- `label` string（投稿タイトル）
- `slug` string（投稿スラッグ）
- `link` string（投稿のパーマリンク）
- `rest_base` string（使用した restBase）
- `post_id` number（投稿ID）

#### 使用例
```
<PostSelectControl
	label={__("Resource Name", "itmaroon-booking-block")}
	homeUrl={itmar_option.home_url}
	restBase={selectedRest || "itmar_resource"}
	selectedSlug={selectedPostSlug || ""}
	onChange={(info) => {
		if (info) {
			setAttributes({
				resourceId: info.post_id,
				resourceSlug: info.slug,
				resourceRest: info.rest_base,
			});
		}
	}}
/>
```

### TermChoiceControl
投稿タイプに紐づけられている全てのタクソノミー（カテゴリ、タグを含む。）に登録されたタームを選択できるチェックボックス表示し、コールバック関数に選択されたタームの情報を返します。
#### プロプス  
- `selectedSlug` string  
選択済みの投稿タイプのスラッグ 
- `choiceTerms` array  
選択済みのタームの情報。配列の要素は次の形式のオブジェクトであること。  
{ taxonomy: タクソノミーのスラッグ, term: タームのスラッグ } 
- `dispTaxonomies` array  
選択済みのタクソノミの情報。配列の要素はタクソノミーのスラッグ     
- `type` string 
選択するデータのタイプ。将来の拡張のためにセットしている。現時点では"taxonomy"とセットすること。
- `label` string  

- `onChange` func
チェックボックスの内容が変化したとき発生するコールバック関数。引数には{ taxonomy: タクソノミーのスラッグ, term:{ id: term.id, slug: term.slug, name: term.name } }という形式のオブジェクトを要素とする配列が入る。
- `onSetDispTax` func
トグルコントロールの内容が変化したとき発生するコールバック関数。引数にはタクソノミーのスラッグを要素とする配列が入る。 

```
<TermChoiceControl
	selectedSlug={selectedSlug}
	choiceTerms={choiceTerms}
	dispTaxonomies={dispTaxonomies}
	type="taxonomy"
	label={__("Choice Taxsonomy", "post-blocks")}
	onChange={(newChoiceTerms) =>
		setAttributes({ choiceTerms: newChoiceTerms })
	}
	onSetDispTax={(newChoiceTerms) => {
		setAttributes({ dispTaxonomies: newChoiceTerms });
	}}
/>
```

### FieldChoiceControl
タイトル、日付、抜粋、アイキャッチ画像、リンクの各フィールドと投稿タイプに紐づけられている全てのカスタムフィールドを選択できるチェックボックス表示し、コールバック関数に選択されたフィールドの情報を返します。
また、各フィールドがどのブロックでレンダリングされるかの設定機能も含みます。
#### プロプス  
- `selectedSlug` string  
選択済みの投稿タイプのスラッグ （Restタイプ）
- `choiceItems` array  
選択済みのフィールドの情報。配列の要素はフィールドのスラッグ（文字列）。  
- `type` string 
選択するデータのタイプ。将来の拡張のためにセットしている。現時点では"field"とセットすること。
- `blockMap` object
フィールド名とブロック名を対にしたオブジェクト
```
{
	"title":"itmar/design-title",
	"date":"itmar/design-title",
	"excerpt":"core/paragraph",
	"featured_media":"core/image",
	"link":"itmar/design-button"
}
```
- `textDomain` string
使用するブロックのテキストドメイン

- `onChange` func
チェックボックスの内容が変化したとき発生するコールバック関数。引数には選択されたフィールドのフィールド名を要素とする配列が入る。 

```

- `onBlockMapChange` func
コンボボックスの内容が変化したとき発生するコールバック関数。引数には設定されたフィールド名とブロック名を対にしたオブジェクトが入る。 

```
<FieldChoiceControl
	type="field"
	selectedSlug={selectedRest}
	choiceItems={choiceFields}
	blockMap={blockMap}
	textDomain="post-blocks"
	onChange={(newChoiceFields) => {
		setAttributes({ choiceFields: newChoiceFields });
	}}
	onBlockMapChange={(newBlockMap) => {
		setAttributes({ blockMap: newBlockMap });
	}}
/>
```

## Font awesom のアイコンを選択するためのコントロール
### IconSelectControl
WordPressのブロックエディタのサイドバーにFont awesomのアイコンを選択するためのコントロールを表示させるReactコンポーネント。
```
<IconSelectControl
	iconStyle={
		icon_type: "awesome",
		icon_url: "",
		icon_name: "f030",
		icon_pos: "left",
		icon_size: "24px",
		icon_color: "var(--wp--preset--color--content)",
		icon_space: "5px",
    	icon_family: "Font Awesome 6 Free",

	}
	setPosition={true}
	onChange={(newValue) => {
		setAttributes({icon_style: newValue})
	}}
/>
```

iconStyleオブジェクトを再設定します。
setPositionプロプスをtrueにするとicon_posとicon_spaceの各オブジェクトを設定するコントロールが表示されます。

<img src="./img/iconControl.png" alt="IconSelectControlのスクリーンショット" width="100" height="200">

## DOM要素をラップしてレンダリングを変化させるReactコンポーネント
### ToggleElement
DOM要素をdiv要素でラップし、flgの値によって、その要素にopenというクラス名を付加します。呼び出し側でflgの値を変更することで、DOM要素の表示・非表示を操作するときに使用します。

```
<ToggleElement
	onToggle={handleHambergerToggle}
	className="itmar_hamberger_btn"
	openFlg={flg}
>
	<span></span>
	<span></span>
	<span></span>
</ToggleElement>
```

## グリッドスタイルの各種設定を行うためのコントロール
### GridControls
CSSでdisplay : grid が設定されたブロックに対し、gridの各種設定を行うため、モーダルウインドウを表示させるReactコンポーネント。
```
<GridControls
	attributes={props.grid_info}
	clientId={clientId}
	onChange={(newValue) => {
		props.onGridChange(newValue)
	}}
/>
```

<img src="./img/grid.png" alt="GridControlsのスクリーンショット" width="200" height="200">

## ブロックの配置に関する各種設定を行うためのコントロール
### BlockPlace
WordPressのブロックエディタのサイドバーにブロックの配置に関する設定のためのコントロールを表示させるReactコンポーネント。
```
<BlockPlace
	attributes={attributes}
	clientId={clientId}
	blockRef={blockRef}
	isMobile={isMobile}
	isSubmenu={is_submenu}
	isParallax={true}
	onDirectionChange={(position) => {
		setAttributes({direction: position });
	}}
	onReverseChange={(checked) => {
		setAttributes({reverse: checked });	
	}}
	onFlexChange={(position,axis) => {
		setAttributes({[axis]: position });
	}}
	onAlignChange={(position) => {
		setAttributes({outer_align: position });
	}}
	onVerticalChange={(position) => {
		setAttributes({outer_vertical: position });
	}}
	onWidthChange={(position) => {
		setAttributes({width_val: position });
	}}
	onHeightChange={(value) => {
		setAttributes({ height_val: value });
	}}
	onFreeWidthChange={(value) => {
		setAttributes({free_width: position });
	}}
	onFreeHeightChange={(value) => {
		setAttributes({free_height: position });
	}}
	onGridChange={(value) => {
		setAttributes({grid_info: position });
	}}
	onPositionChange={(value) => {
		setAttributes({ positionType: value });
	}}
	onPosValueChange={(value) => {
		setAttributes({posValue: position });
	}}
/>
```


<img src="./img/blockplace.png" alt="BlockPlaceのスクリーンショット" width="100" height="300">

### BlockWidth
ブロックコンポーネントの幅を設定する
#### 引数
- `attributes` object  
ブロックの属性オブジェクト
- `isMobile` boolean  
スクリーン幅が767px以下かどうかのフラグ
- `isSubmenu` boolean  
trueの場合はmax-widthを合わせて設定する
- `onWidthChange` function
widthの種別を設定するためのコールバック関数。返ってくる引数はkey,valueの２つでkeyはwidth_valまたはmax_valという文字列でwidthValはfit,full,wideSize,contentSize,freeのいずれか
- `onFreeWidthChange` function
widthの種別がfreeのとき幅を設定するためのコールバック関数。返ってくる引数はkey,valueの２つでkeyはfree_widthまたはmax_free_widthという文字列でvalueは単位付きの文字列

```
<BlockWidth
	attributes={attributes}
	isMobile={isMobile}
	isSubmenu={isFront}
	onWidthChange={(key,value) => {
		setAttributes(
			!isMobile
				? { default_val: { ...default_val, [key]: value } }
				: { mobile_val: { ...mobile_val, [key]: value } },
		);
	}}
	onFreeWidthChange={(key,value) => {
		setAttributes(
			!isMobile
				? { default_val: { ...default_val, [key]: value } }
				: { mobile_val: { ...mobile_val, [key]: value } },
		);
	}}
/>
```

### BlockHeight
ブロックコンポーネントの高さを設定する
#### 引数
- `attributes` object  
ブロックの属性オブジェクト
- `isMobile` boolean  
スクリーン幅が767px以下かどうかのフラグ
- `onHeightChange` function
heightの種別を設定するためのコールバック関数。返ってくる引数はfit,full,free
- `onFreeHeightChange` function
heightの種別がfreeのとき幅を設定するためのコールバック関数。返ってくる引数は単位付きの文字列

```
<BlockHeight
	attributes={attributes}
	isMobile={isMobile}
	onHeightChange={(value) => {
		setAttributes(
			!isMobile
				? { default_val: { ...default_val, height_val: value } }
				: { mobile_val: { ...mobile_val, height_val: value } },
		);
	}}
	onFreeHeightChange={(value) => {
		setAttributes(
			!isMobile
				? { default_val: { ...default_val, free_height: value } }
				: { mobile_val: { ...mobile_val, free_height: value } },
		);
	}}
/>
```

## 色コードを変換する関数
### hslToRgb16
Hslオブジェクトの値を与えると#000000型のRGB表記に変換するためのユーティリティ関数です。
#### 引数
- `hue` number  
Hslオブジェクトのhueの値
- `saturation` number  
Hslオブジェクトのsaturationの値
- `lightness` number  
Hslオブジェクトのlightnessの値

### rgb16ToHsl
16進数のRGB表記を受け取り、それをHslオブジェクトに変換するためのユーティリティ関数です。
#### 引数
- `strRgb16` string  
#000000形式の１６進数の文字列又はrgb(0,0,0) 形式の文字列
　　

### HexToRGB
16進数のRGB表記を受け取り、それを10進数のRGBオブジェクトに変換するためのユーティリティ関数です。
#### 引数
- `strRgb16` string  
#000000形式の１６進数の文字列又はrgb(0,0,0) 形式の文字列  

## 指定した投稿タイプの投稿に含まれる特定のブロックの属性を書き換えるコンポーネント
### UpdateAllPostsBlockAttributes
#### 引数
- `postType` string  
WordPressのRestAPIで使用するrest_baseに相当する文字列
- `blockName` string  
ブロックの名称。投稿本文に含まれるブロックの名前を指定
- `newAttributes` object  
新しいブロックの属性をオブジェクトで指定
- `onProcessStart` function  
処理が完了したときに実行するコールバック関数
- `onProcessEnd` function  
処理が完了したときに実行するコールバック関数
- `onProcessCancel` function  
処理が中断されたときに実行するコールバック関数
```
<UpdateAllPostsBlockAttributes
	postType={rest_base}
	blockName="itmar/markdown-block"
	newAttributes={{
		element_style_obj: element_style_obj,
		backgroundColor: backgroundColor,
		backgroundGradient: backgroundGradient,
		default_val: default_val,
		mobile_val: mobile_val,
		radius_value: radius_value,
		border_value: border_value,
	}}
	onProcessStart={startProgress}
	onProcessEnd={closeProgress}
	onProcessCancel={() => {
		dispatch("core/notices").createNotice(
			"error",
			__("Processing was interrupted.", "markdown-block"),
			{ type: "snackbar" },
		);
	}}
/>
```

## インナーブロックを取得・操作する関数
### `useTargetBlocks`

`useTargetBlocks` は、**Gutenberg ブロックエディタ上で同じ親ブロック内にある特定の名前・属性を持つブロックを取得する React フック**です。  
ネストされたブロックの検索にも対応しています。



#### 🧩 概要

このカスタムフックは、次のような用途に使えます：

- 同じ親ブロックの中から特定のブロックを配列で取得
- 属性値でフィルタして一致する **1件のブロック**を取得
- ネストされたブロックも含めて取得（オプション）

---

#### ✅ 使い方

##### 基本構文

```js
const result = useTargetBlocks(clientId, blockName, attributeFilter?, includeNested?);
```

| 引数 | 型 | 説明 |
|------|----|------|
| `clientId` | `string` | 呼び出し元（自分自身）の `clientId`。`useBlockEditContext()` などで取得 |
| `blockName` | `string` | 対象ブロック名（例: `'itmar/design-text-ctrl'`） |
| `attributeFilter` | `object|null` | オプション：指定した属性に一致するブロックを1件だけ取得（例: `{ inputName: 'address' }`） |
| `includeNested` | `boolean` | オプション：`true` でネストされたブロックも対象に含める（デフォルト: `false`） |

---

#### 🧪 使用例

##### 1. 全ての `itmar/design-text-ctrl` ブロックを取得（自分を除く）

```js
import { useBlockEditContext } from '@wordpress/block-editor';
import { useTargetBlocks } from '@your-scope/use-target-blocks';

const MyComponent = () => {
  const { clientId } = useBlockEditContext();

  const blocks = useTargetBlocks(clientId, 'itmar/design-text-ctrl');

  return <div>対象ブロック数: {blocks.length}</div>;
};
```

---

##### 2. `inputName: 'address'` を持つブロックを1件だけ取得

```js
const targetBlock = useTargetBlocks(clientId, 'itmar/design-text-ctrl', {
  inputName: 'address',
});

if (targetBlock) {
  console.log('Address block found:', targetBlock.clientId);
}
```

---

##### 3. ネストされたブロックも含めて検索

```js
const nestedBlock = useTargetBlocks(
  clientId,
  'itmar/design-text-ctrl',
  { inputName: 'address' },
  true // ネスト含める
);
```

---

#### 📁 内部で使用しているもの

- `@wordpress/data`
- `@wordpress/block-editor`
- `useSelect`, `getBlockRootClientId`, `getBlock`, `getBlocks`

---

#### 🔁 補助関数：`flattenBlocks`

ネストされたブロックを平坦化するためのユーティリティも内蔵：

```js
const flattenBlocks = (blocks) => {
  return blocks.reduce((acc, block) => {
    acc.push(block);
    if (block.innerBlocks?.length > 0) {
      acc.push(...flattenBlocks(block.innerBlocks));
    }
    return acc;
  }, []);
};
```

---

#### 🛡️ 注意事項

- このフックは **Gutenberg ブロックエディタ内でのみ使用可能**です。
- `useTargetBlocks()` は **React フック**です。関数やイベントハンドラ内部では直接呼び出せません。

---

### `serializeBlockTree`

指定された Gutenberg ブロックオブジェクトを、**ネスト構造を保ったままプレーンな JSON 形式に変換（保存用）**します。

#### ✅ 使い方

```js
import { serializeBlockTree } from '@your-scope/block-tree-utils';

const json = serializeBlockTree(block);
```

#### 📥 入力

- `block`: Gutenberg ブロックオブジェクト（`name`, `attributes`, `innerBlocks` を含む）

#### 📤 出力

```json
{
  "blockName": "core/group",
  "attributes": { ... },
  "innerBlocks": [
    {
      "blockName": "core/paragraph",
      "attributes": { ... },
      "innerBlocks": []
    }
  ]
}
```

---

### `createBlockTree`

`serializeBlockTree` によって得られた JSON 構造を、**`createBlock()` に渡せる Gutenberg ブロックオブジェクトに再構築**します。

#### ✅ 使い方

```js
import { createBlockTree } from '@your-scope/block-tree-utils';
import { createBlock } from '@wordpress/blocks';

const wpBlock = createBlockTree(savedJson);
```

#### 📥 入力

- `savedJson`: `serializeBlockTree` で生成されたブロックデータ

#### 📤 出力

- `createBlock(name, attributes, innerBlocks)` の形で再帰的に構成された WP ブロックオブジェクト

---

### `flattenBlocks`

Gutenberg のネストされたブロック配列を、**1階層の配列としてフラットに展開**します。  
ブロック構成内にあるすべてのブロック（ネスト含む）を一括走査する際に便利です。

#### ✅ 使い方

```js
import { flattenBlocks } from '@your-scope/block-tree-utils';

const flat = flattenBlocks(innerBlocks);
```

#### 📥 入力

- `innerBlocks`: Gutenberg のブロック配列（`innerBlocks` を含む構造）

#### 📤 出力

- 平坦化されたブロック配列（元の構造は保持しない）

---

## 🧪 使用例

```js
import {
  serializeBlockTree,
  createBlockTree,
  flattenBlocks,
} from '@your-scope/block-tree-utils';

const savedData = blocks.map(serializeBlockTree);
const restored = savedData.map(createBlockTree);
const flatList = flattenBlocks(restored);
```

---  


## 日本郵便番号から住所を取得するユーティリティ関数
### `fetchZipToAddress`
`fetchZipToAddress` は、[zipcloud](https://zipcloud.ibsnet.co.jp) API を使用して、日本の郵便番号から都道府県・市区町村・町域の住所を非同期で取得する JavaScript 関数です。  
Gutenberg ブロック開発やフロントエンドフォーム処理において、郵便番号による住所補完機能を簡単に実装できます。


#### 使用例（React / jQuery 共通）

```js
const addressObj = await fetchZipToAddress("1600022");
if (addressObj) {
  const fullAddress = addressObj.address1 + addressObj.address2 + addressObj.address3;
  console.log(fullAddress); // 例: 東京都新宿区新宿
}
```

---

#### 🔐 バリデーション仕様

- 郵便番号は「**ハイフンなしの7桁の数字**」形式のみ許可されます（例: `1234567`）。
- 無効な形式や一致しない郵便番号、通信エラー時には `null` を返します。
- エラーはすべて `alert()` によってユーザーに通知されます。

---

#### 🔁 返り値の形式（成功時）

```json
{
  "zipcode": "1600022",
  "prefcode": "13",
  "address1": "東京都",
  "address2": "新宿区",
  "address3": "新宿",
  ...
}
```

---

#### 🌐 使用API

本ライブラリは以下の外部APIを使用しています：

- **zipcloud（日本郵便公式APIラッパー）**
  - URL: [https://zipcloud.ibsnet.co.jp](https://zipcloud.ibsnet.co.jp)
  - ドキュメント: [https://zipcloud.ibsnet.co.jp/doc/api](https://zipcloud.ibsnet.co.jp/doc/api)

#### ⚠️ ご注意

- この API は外部サービス（zipcloud）に依存しており、アクセス過多による制限や仕様変更の可能性があります。
- 本ライブラリを利用する場合は、[zipcloud利用規約](https://zipcloud.ibsnet.co.jp/doc/rule) を必ずご確認・順守してください。

---

#### 🧩 WordPress / Gutenberg との統合例

```js
const handleZipSearch = async () => {
  const result = await fetchZipToAddress(zipValue);
  if (result) {
    setAttributes({ inputValue: result.address1 + result.address2 + result.address3 });
  }
};
```

## バリデーションチェックを行う関数
### `isValidUrlWithUrlApi`
`isValidUrlWithUrlApi` は、引数で与えた文字列がURLの形式であるかどうかのバリデーションチェックをします。


#### 使用例
```
if (isValidUrlWithUrlApi(headingContent)) {
	setAttributes({ selectedPageUrl: headingContent });
} 
```

## データのフォーマットを設定、表示するコンポーネント

Gutenberg ブロックにおける数値・日付・自由書式の表示形式を選択・制御するための UI コンポーネントおよびフォーマット関数です。

---

### 概要

このライブラリは、以下の2つの機能を提供します：

1. **`<FormatSelectControl />`**  
   ブロックエディターの「インスペクター設定」内で、表示形式を選択する UI コンポーネント。

2. **`displayFormated()`**  
   保存された設定に基づき、日付・数値・自由文字列の値を整形する表示用関数。

---

### `FormatSelectControl`

#### 説明

ブロック編集画面で「日付」「数値」「自由文字列」のいずれかの表示形式を選択・設定可能にする `PanelBody` コンポーネントです。

#### 引数

| 名前 | 型 | 必須 | 説明 |
|------|----|------|------|
| `titleType` | `"date"` \| `"plaine"` \| `"user"` | ✅ | フォーマット対象の種類を指定します。 |
| `userFormat` | `string` | ✅ | 現在選択中のフォーマットのキー（例: `"num_comma"`）。 |
| `freeStrFormat` | `string` | ✅ | 自由書式入力時の書式文字列（例: `"¥%s円"`）。 |
| `decimal` | `number` | ✅ | 数値の小数点以下の桁数（0〜5） |
| `onFormatChange` | `(info: FormatSettings) => void` | ✅ | 各設定項目の更新を通知するコールバック |

#### フォーマットオプション例（SelectControlで使用）

- 日付形式：`Y-m-d H:i:s`、`Y年n月j日 (l)` など
- 数値形式：カンマ区切りあり／なし、金額表示など
- 自由書式：`"%s"` を含む文字列で、実際の値が置換されます

---

### `displayFormated(content, userFormat, freeStrFormat, decimal)`

#### 説明

指定されたフォーマットに従って、値を整形して文字列として返します。

#### 引数

| 名前 | 型 | 説明 |
|------|----|------|
| `content` | `string` \| `number` | 整形対象の生の値 |
| `userFormat` | `string` | 日付または数値のフォーマットキー（例: `"num_comma"`、`"Y-m-d"`） |
| `freeStrFormat` | `string` | `"%s"` を含む自由書式文字列 |
| `decimal` | `number` | 小数点以下の桁数指定（`0` なら整数扱い） |

#### 戻り値

整形後の文字列（`string`）

---

### 使用例

#### 1. コンポーネントの設置例

```jsx
<FormatSelectControl
  titleType="plaine"
  userFormat={attributes.userFormat}
  freeStrFormat={attributes.freeStrFormat}
  decimal={attributes.decimal}
  onFormatChange={(newSettings) => setAttributes(newSettings)}
/>
```
#### 2. 表示用フォーマット関数の使用例
```
const display = displayFormated(
  1234567.89,
  attributes.userFormat,
  attributes.freeStrFormat,
  attributes.decimal
);
// → "1,234,567.89"（例: num_comma + decimal: 2 の場合）
```

### 注意事項・ルール
✅ 自由書式（freeStrFormat）について
- %s を含まない文字列は 置換せず、値をそのまま返します
- 例："¥%s" → "¥1234"、"Total: " → "1234"（%s なし）

✅ 日付フォーマットの安全性
- userFormat が dateFormats に存在しない限り format() は呼び出されません（安全）
- Gutenberg 標準の PHP形式に準拠（例：Y-m-d, F j, Y）

✅ 数値フォーマットの条件
- decimal が 1 以上のときは minimumFractionDigits / maximumFractionDigits が指定され、常に小数点以下を表示
- decimal = 0 の場合は整数として表示

## pickupStore

複数の WordPress ブロック（複数の `view.js` / `viewScript`）から **共通の状態（state）** を扱うための、軽量なグローバルストアです。  
`window.__itmar_pickup_store__` 上に `contexts: Map` を1つだけ持ち、`pickup_id`（任意の id）ごとに `ctx`（コンテキスト）を共有します。

---

### 特長

- **id ごとに状態を共有**（`contexts: Map`）
- **購読（subscribe）で state 変更通知**（初回は即時通知）
- **部分更新（shallow merge）**で state を更新し購読者へ通知
- `ctx.inflight.abort` など、通信中管理の置き場も用意

---

### インストール

```bash
npm i <your-package-name>
```

---

### 基本コンセプト

#### グローバルストアと contexts

`pickupStore` は `window.__itmar_pickup_store__` に `{ contexts: new Map() }` を保持します。  
この `contexts` により、**別ファイル・別ブロックでも同じ Map を共有**できます。

#### ctx（コンテキスト）

`ctx` は id ごとに作られる共有オブジェクトです。`state`・`dataset`・`listeners`・`cache`・`inflight` などを持ちます。

---

### API

#### `ensureCtx(id)`

**概要**: id の ctx を取得します。存在しなければ作成して返します。id が falsy の場合は `null`。

- 引数: `id: string`
- 戻り値: `ctx | null`

---

#### `registerPickup(pickupEl)`

**概要**: DOM要素の `data-pickup_id` から id を取り、その id の ctx を確保した上で `ctx.pickupEl` と `ctx.dataset` を更新します。id が無ければ `null`。

- 引数: `pickupEl: Element`
- 戻り値: `ctx | null`

---

#### `getCtx(id)`

**概要**: 既存の ctx を取得します（作成はしない）。無ければ `null`。

- 引数: `id: string`
- 戻り値: `ctx | null`

---

#### `subscribe(id, fn)`

**概要**: ctx を購読します。登録直後に `fn(ctx)` が **1回即時実行**されます（初回通知）。解除関数を返します。

- 引数:
  - `id: string`
  - `fn: (ctx) => void`
- 戻り値: `() => void`（購読解除関数）

---

#### `setState(id, partial)`

**概要**: `ctx.state` を `partial` で **浅くマージ**して更新し、購読者を全員呼びます。

- 引数:
  - `id: string`
  - `partial: object`
- 戻り値: `void`

---

### 使用例（registerPickup → subscribe → setState）

```js
import { registerPickup, subscribe, setState } from "./pickupStore";

const pickups = document.querySelectorAll(".wp-block-itmar-pickup-posts");

pickups.forEach((el) => {
  const ctx = registerPickup(el); // data-pickup_id が必要
  if (!ctx) return;

  // 初期状態を投入
  setState(ctx.id, { page: 0, total: 0 });

  // 購読（初回は即時に1回呼ばれる）
  const unsubscribe = subscribe(ctx.id, (ctxNow) => {
    console.log("state:", ctxNow.state);
  });

  // 必要なら解除
  // unsubscribe();
});
```

> `registerPickup()` は `ctx.dataset = { ...pickupEl.dataset }` のように dataset をスナップショット保存します。

---

### `useStyleIframe(StyleComp, attributes)`

#### 説明

WordPressブロックエディタの編集画面（iframe内）に対して、`styled-components` のスタイルを安全に注入するためのカスタムフック兼コンポーネントです。
`createPortal` と `StyleSheetManager` を組み合わせることで、エディタの canvas（iframe）の `head` 内に直接スタイル定義を飛ばし、エディタ上での正確なプレビューを実現します。

#### 引数

| 名前 | 型 | 説明 |
|------|----|------|
| `StyleComp` | `React.ComponentType` | スタイル定義のみを含むReactコンポーネント |
| `attributes` | `T` (Generic) | ブロックの属性オブジェクト（`StyleComp` に渡されます） |

#### 戻り値

React Portal要素（`React.ReactPortal | null`）
※エディタのiframeが見つからない場合は `null` を返します。

---

### 使用例

#### 1. スタイル定義用コンポーネントの作成
まず、`styled-components` を使って、スタイルだけを定義するコンポーネントを用意します。

```tsx
import styled from 'styled-components';

// 外部に書き出したいスタイル定義
const StyleComp = ({ attributes }) => (
    <style>
        {`
            .my-custom-block {
                color: ${attributes.color};
                font-size: ${attributes.fontSize}px;
            }
        `}
    </style>
);

#### 2. Editコンポーネントでの使用例
ブロックの `Edit` 関数内で呼び出します。戻り値をJSX内に配置するだけで、スタイルがiframeに注入されます。

```tsx
import { useStyleIframe } from 'itmar-block-packages';

export default function Edit({ attributes }) {
    // スタイルをiframeのheadに注入するポータルを取得
    const stylePortal = useStyleIframe(StyleComp, attributes);

    return (
        <>
            {/* これを配置するだけでiframeのheadにスタイルが飛びます */}
            {stylePortal}

            <div className="my-custom-block">
                エディタ上でのプレビュー表示
            </div>
        </>
    );
}

### 注意事項・ルール

✅ **iframeの自動検知**
- Gutenbergの標準的なiframe名である `"editor-canvas"` を自動で検索し、その `head` 要素をターゲットにします。

✅ **DOMを汚さない設計**
- `createPortal` を使用して `document.head` に描画するため、ブロックのコンテンツエリア（`div` 等の中）に不要なスタイルタグや空の `div` が残ることはありません。

✅ **動的なスタイル更新**
- `attributes` が更新されるたびに `useMemo` と React の再レンダリングが連動し、エディタ上のスタイルもリアルタイムに反映されます。

✅ **安全なフォールバック**
- サイトエディタや古いWordPress環境など、iframeが存在しないケースでは何も描画（`null` を返却）しないため、エラーでエディタ全体が白くなる心配がありません。

### `styleComponentApply(StyleComp, blockSelector)`

#### 説明

WordPressのフロントエンド表示時において、`styled-components` で定義されたスタイルを動的に生成し、該当するブロックに適用します。
ブロックの `save` 関数で出力された特定のセレクター（`.itmar-wrap` 等）を自動で探し出し、生成されたユニークなクラス名とスタイルタグを注入します。

#### 引数

| 名前 | 型 | 説明 |
|------|----|------|
| `StyleComp` | `React.ComponentType` | スタイル定義のみを含むReactコンポーネント |
| `blockSelector` | `string` | 対象となるブロックを特定するためのCSSセレクター |

### 使用例

#### 1. ブロックの `save.tsx` での準備
この関数は `data-attributes` 属性からデータを読み取るため、`save` 関数で属性をJSONとして出力しておく必要があります。

```tsx
export default function save({ attributes }) {
    return (
        <div 
            className="wp-block-my-custom-block" 
            data-attributes={JSON.stringify(attributes)}
        >
            <div className="itmar-wrap">
                {/* ここにスタイルが適用されます */}
                コンテンツ
            </div>
        </div>
    );
}
#### 2. フロントエンド（front.ts 等）での実行
ブロックが表示されるフロントエンドのスクリプトで、この関数を呼び出します。
```tsx
import { styleComponentApply } from 'itmar-block-packages';
import { StyleComp } from './edit'; // スタイル定義コンポーネント

// DOMの読み込み完了後に実行
window.addEventListener('load', () => {
    styleComponentApply(StyleComp, '.wp-block-my-custom-block');
});
```

### 注意事項・ルール

✅ **ハイドレーション不要のスタイル注入**
- `styled-components` の `ServerStyleSheet` をブラウザ上でエミュレートすることで、Reactのフルハイドレーションを行わずに、軽量にスタイルだけを適用します。

✅ **ユニークなクラス名の継承**
- `styled-components` が生成する `sc-xxxx` のようなユニークなクラス名を自動で抽出し、対象要素（`.itmar-wrap` またはルート要素）の `classList` に追加します。

✅ **data-attributes への依存**
- 実行には要素に `data-attributes` 属性が付与されている必要があります。属性が存在しない要素は自動的にスキップされます。

✅ **安全なスタイル注入**
- 生成されたスタイルタグは `document.head` に集約して追加されるため、DOM構造を壊すことなくページ全体のスタイルを管理できます。