@feelflow/ffid-sdk 2.12.1 → 2.14.0

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/README.md CHANGED
@@ -228,6 +228,44 @@ const PremiumFeature = withSubscription(MyComponent, {
228
228
  })
229
229
  ```
230
230
 
231
+ ### getProfile() / updateProfile()
232
+
233
+ ログイン中ユーザー自身のプロフィールを取得・更新するメソッド(`createFFIDClient` から呼び出し)。
234
+
235
+ - エンドポイント: `GET /api/v1/users/ext/me` / `PUT /api/v1/users/ext/me`
236
+ - 対応 authMode: `token`(Bearer)のみが SDK 経由で成立する
237
+ - **cookie モードは非対応** — ext エンドポイントはクロスオリジン用途のため、Bearer token または `X-Service-Api-Key` のどちらかが必須。FFID 自身の UI(同一オリジン)は従来通り `/api/v1/users/me` を使う
238
+ - **service-key モードも SDK 経由では非対応** — API Key 認証時はバックエンドが `?userId=<uuid>` クエリを要求するが、`getProfile()` / `updateProfile()` は自分自身(ambient user)を前提とするため、`userId` を受け取らない。サーバー間で任意ユーザーのプロフィールを操作したい場合は `fetchWithAuth` で直接エンドポイントを叩いてください
239
+ - 外部サービス(hub 等)のフロントエンドから token モードで呼ぶのが想定される主要パターン
240
+
241
+ ```tsx
242
+ import { createFFIDClient } from '@feelflow/ffid-sdk'
243
+
244
+ const client = createFFIDClient({
245
+ serviceCode: 'hub',
246
+ authMode: 'token',
247
+ apiBaseUrl: 'https://id.feelflow.net',
248
+ })
249
+
250
+ // 取得
251
+ const { data: profile, error } = await client.getProfile()
252
+ if (error) {
253
+ console.error('プロフィール取得失敗:', error.message)
254
+ } else {
255
+ console.log(profile.email, profile.displayName, profile.timezone)
256
+ }
257
+
258
+ // 更新(部分更新 — 渡したフィールドだけ差し替え)
259
+ const { data: updated, error: updateError } = await client.updateProfile({
260
+ displayName: '山田 太郎',
261
+ timezone: 'Asia/Tokyo',
262
+ locale: 'ja',
263
+ preferences: { theme: 'dark' },
264
+ })
265
+ ```
266
+
267
+ `updateProfile` に空オブジェクト `{}` を渡すと `VALIDATION_ERROR` が返ります(無意味なラウンドトリップを防止)。
268
+
231
269
  ## 型定義
232
270
 
233
271
  ```typescript
@@ -758,8 +758,34 @@ function createMembersMethods(deps) {
758
758
  return { listMembers, updateMemberRole, removeMember };
759
759
  }
760
760
 
761
+ // src/client/profile-methods.ts
762
+ var EXT_PROFILE_ENDPOINT = "/api/v1/users/ext/me";
763
+ function createProfileMethods(deps) {
764
+ const { fetchWithAuth, createError } = deps;
765
+ async function getProfile() {
766
+ return fetchWithAuth(EXT_PROFILE_ENDPOINT);
767
+ }
768
+ async function updateProfile(data) {
769
+ if (data === null || typeof data !== "object" || Array.isArray(data)) {
770
+ return {
771
+ error: createError("VALIDATION_ERROR", "data \u306F\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059")
772
+ };
773
+ }
774
+ if (Object.keys(data).length === 0) {
775
+ return {
776
+ error: createError("VALIDATION_ERROR", "\u66F4\u65B0\u3059\u308B\u30D5\u30A3\u30FC\u30EB\u30C9\u30921\u3064\u4EE5\u4E0A\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044")
777
+ };
778
+ }
779
+ return fetchWithAuth(EXT_PROFILE_ENDPOINT, {
780
+ method: "PUT",
781
+ body: JSON.stringify(data)
782
+ });
783
+ }
784
+ return { getProfile, updateProfile };
785
+ }
786
+
761
787
  // src/client/version-check.ts
762
- var SDK_VERSION = "2.12.1";
788
+ var SDK_VERSION = "2.14.0";
763
789
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
764
790
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
765
791
  function sdkHeaders() {
@@ -2143,6 +2169,10 @@ function createFFIDClient(config) {
2143
2169
  createError,
2144
2170
  serviceCode: config.serviceCode
2145
2171
  });
2172
+ const { getProfile, updateProfile } = createProfileMethods({
2173
+ fetchWithAuth,
2174
+ createError
2175
+ });
2146
2176
  const {
2147
2177
  requestPasswordReset,
2148
2178
  verifyPasswordResetToken,
@@ -2214,6 +2244,8 @@ function createFFIDClient(config) {
2214
2244
  listMembers,
2215
2245
  updateMemberRole,
2216
2246
  removeMember,
2247
+ getProfile,
2248
+ updateProfile,
2217
2249
  createCheckoutSession,
2218
2250
  createPortalSession,
2219
2251
  listPlans,
@@ -3598,8 +3630,34 @@ var FFID_INQUIRY_CATEGORIES = [
3598
3630
  "press",
3599
3631
  "other"
3600
3632
  ];
3633
+ var FFID_INQUIRY_CATEGORIES_SITE_2026 = [
3634
+ // サービス
3635
+ "consulting",
3636
+ "saas",
3637
+ "development",
3638
+ // プロダクト
3639
+ "agent-hub",
3640
+ "ai-feel-chatbot",
3641
+ "knowledge-db",
3642
+ "biz-simulator",
3643
+ "discussion-board",
3644
+ "realtime-ai",
3645
+ // その他
3646
+ "partnership",
3647
+ "media",
3648
+ "recruiting",
3649
+ "other"
3650
+ ];
3651
+ var isFFIDInquiryCategorySite2026 = (value) => FFID_INQUIRY_CATEGORIES_SITE_2026.includes(value);
3601
3652
  var CATEGORY_PLACEHOLDER_LABEL_JA = "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044";
3602
3653
  var CATEGORY_REQUIRED_ERROR_JA = "\u304A\u554F\u3044\u5408\u308F\u305B\u7A2E\u5225\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002";
3654
+ var TERMS_REQUIRED_ERROR_JA = "\u5229\u7528\u898F\u7D04\u3078\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002";
3655
+ var PRIVACY_REQUIRED_ERROR_JA = "\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30DD\u30EA\u30B7\u30FC\u3078\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002";
3656
+ var TURNSTILE_PENDING_ERROR_JA = "\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30C1\u30A7\u30C3\u30AF\u306E\u5B8C\u4E86\u5F8C\u306B\u9001\u4FE1\u3057\u3066\u304F\u3060\u3055\u3044\u3002";
3657
+ function hasSatisfiedTurnstile(turnstileSlot, turnstileToken) {
3658
+ if (turnstileSlot == null) return true;
3659
+ return (turnstileToken ?? "").trim().length > 0;
3660
+ }
3603
3661
  var SUBMIT_BUTTON_OPACITY_PENDING = 0.6;
3604
3662
  var labelStyle = {
3605
3663
  display: "block",
@@ -3669,6 +3727,23 @@ function defaultCategories() {
3669
3727
  label: DEFAULT_CATEGORY_LABELS_JA[value]
3670
3728
  }));
3671
3729
  }
3730
+ function warnOnGroupLabelConflicts(options) {
3731
+ if (process.env.NODE_ENV === "production") return;
3732
+ const firstExplicitLabel = /* @__PURE__ */ new Map();
3733
+ const warnedGroups = /* @__PURE__ */ new Set();
3734
+ for (const opt of options) {
3735
+ if (!opt.group || opt.groupLabel === void 0) continue;
3736
+ const firstLabel = firstExplicitLabel.get(opt.group);
3737
+ if (firstLabel === void 0) {
3738
+ firstExplicitLabel.set(opt.group, opt.groupLabel);
3739
+ } else if (firstLabel !== opt.groupLabel && !warnedGroups.has(opt.group)) {
3740
+ warnedGroups.add(opt.group);
3741
+ console.warn(
3742
+ `[FFIDInquiryForm] group "${opt.group}" has conflicting groupLabels: "${firstLabel}" (first-wins) vs "${opt.groupLabel}" (ignored). Pass the same groupLabel for every item in the group, or omit it on all but the first.`
3743
+ );
3744
+ }
3745
+ }
3746
+ }
3672
3747
  function renderCategoryOptions(options) {
3673
3748
  const hasAnyGroup = options.some((o) => !!o.group);
3674
3749
  if (!hasAnyGroup) {
@@ -3721,6 +3796,9 @@ function FFIDInquiryForm({
3721
3796
  () => categories && categories.length > 0 ? categories : defaultCategories(),
3722
3797
  [categories]
3723
3798
  );
3799
+ useEffect(() => {
3800
+ warnOnGroupLabelConflicts(categoryOptions);
3801
+ }, [categoryOptions]);
3724
3802
  const initialOrgId = useMemo(() => {
3725
3803
  if (!isAuth) return null;
3726
3804
  if (preselectedOrganizationId !== void 0) return preselectedOrganizationId;
@@ -3754,6 +3832,8 @@ function FFIDInquiryForm({
3754
3832
  const [agreedLegal, setAgreedLegal] = useState(false);
3755
3833
  const [agreedTerms, setAgreedTerms] = useState(false);
3756
3834
  const [agreedPrivacy, setAgreedPrivacy] = useState(false);
3835
+ const [agreedTermsError, setAgreedTermsError] = useState(false);
3836
+ const [agreedPrivacyError, setAgreedPrivacyError] = useState(false);
3757
3837
  const [submitting, setSubmitting] = useState(false);
3758
3838
  const [formError, setFormError] = useState(null);
3759
3839
  const [successMessage, setSuccessMessage] = useState(null);
@@ -3771,7 +3851,7 @@ function FFIDInquiryForm({
3771
3851
  onChangeRef.current = onChange;
3772
3852
  }, [onChange]);
3773
3853
  useEffect(() => {
3774
- if (category === "") return;
3854
+ if (category === "" || successMessage) return;
3775
3855
  onChangeRef.current?.({
3776
3856
  name: name.trim(),
3777
3857
  email: email.trim(),
@@ -3800,25 +3880,19 @@ function FFIDInquiryForm({
3800
3880
  termsVersion,
3801
3881
  privacyVersion,
3802
3882
  turnstileToken,
3803
- locale
3883
+ locale,
3884
+ successMessage
3804
3885
  ]);
3805
3886
  const s = (style) => styleOrUndefined(style, unstyled);
3806
3887
  async function handleSubmit(e) {
3807
3888
  e.preventDefault();
3808
3889
  setFormError(null);
3809
3890
  if (separateLegalCheckboxes) {
3810
- if (!agreedTerms && !agreedPrivacy) {
3811
- setFormError("\u5229\u7528\u898F\u7D04\u3068\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30DD\u30EA\u30B7\u30FC\u3078\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002");
3812
- return;
3813
- }
3814
- if (!agreedTerms) {
3815
- setFormError("\u5229\u7528\u898F\u7D04\u3078\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002");
3816
- return;
3817
- }
3818
- if (!agreedPrivacy) {
3819
- setFormError("\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30DD\u30EA\u30B7\u30FC\u3078\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002");
3820
- return;
3821
- }
3891
+ const termsInvalid = !agreedTerms;
3892
+ const privacyInvalid = !agreedPrivacy;
3893
+ setAgreedTermsError(termsInvalid);
3894
+ setAgreedPrivacyError(privacyInvalid);
3895
+ if (termsInvalid || privacyInvalid) return;
3822
3896
  } else if (!agreedLegal) {
3823
3897
  setFormError("\u5229\u7528\u898F\u7D04\u3068\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30DD\u30EA\u30B7\u30FC\u3078\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002");
3824
3898
  return;
@@ -3835,6 +3909,10 @@ function FFIDInquiryForm({
3835
3909
  setFormError("\u304A\u540D\u524D\u3068\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
3836
3910
  return;
3837
3911
  }
3912
+ if (!isAuth && !hasSatisfiedTurnstile(turnstileSlot, turnstileToken)) {
3913
+ setFormError(TURNSTILE_PENDING_ERROR_JA);
3914
+ return;
3915
+ }
3838
3916
  setSubmitting(true);
3839
3917
  try {
3840
3918
  const result = await onSubmit({
@@ -3912,7 +3990,7 @@ function FFIDInquiryForm({
3912
3990
  onSubmit: handleSubmit,
3913
3991
  className: cx(className, classNames?.form),
3914
3992
  noValidate: true,
3915
- "data-hydrated": hydrated ? "true" : void 0,
3993
+ "data-hydrated": hydrated ? "true" : "false",
3916
3994
  children: [
3917
3995
  showOrgBlock && /* @__PURE__ */ jsxs("div", { style: s(fieldsetStyle), className: cx(classNames?.field, classNames?.orgSelectWrapper), children: [
3918
3996
  /* @__PURE__ */ jsx("label", { style: s(labelStyle), className: classNames?.label, htmlFor: "ffid-inquiry-org", children: "\u554F\u3044\u5408\u308F\u305B\u308B\u7ACB\u5834" }),
@@ -4079,7 +4157,11 @@ function FFIDInquiryForm({
4079
4157
  type: "checkbox",
4080
4158
  className: classNames?.legalCheckbox,
4081
4159
  checked: agreedTerms,
4082
- onChange: (e) => setAgreedTerms(e.target.checked),
4160
+ onChange: (e) => {
4161
+ const checked = e.target.checked;
4162
+ setAgreedTerms(checked);
4163
+ if (checked) setAgreedTermsError(false);
4164
+ },
4083
4165
  required: true
4084
4166
  }
4085
4167
  ),
@@ -4088,6 +4170,7 @@ function FFIDInquiryForm({
4088
4170
  " \u306B\u540C\u610F\u3057\u307E\u3059\u3002"
4089
4171
  ] })
4090
4172
  ] }),
4173
+ agreedTermsError && /* @__PURE__ */ jsx("p", { role: "alert", style: s(errorTextStyle), className: classNames?.errorText, children: TERMS_REQUIRED_ERROR_JA }),
4091
4174
  /* @__PURE__ */ jsxs("label", { style: s(legalRowLast), className: classNames?.legalRow, children: [
4092
4175
  /* @__PURE__ */ jsx(
4093
4176
  "input",
@@ -4095,7 +4178,11 @@ function FFIDInquiryForm({
4095
4178
  type: "checkbox",
4096
4179
  className: classNames?.legalCheckbox,
4097
4180
  checked: agreedPrivacy,
4098
- onChange: (e) => setAgreedPrivacy(e.target.checked),
4181
+ onChange: (e) => {
4182
+ const checked = e.target.checked;
4183
+ setAgreedPrivacy(checked);
4184
+ if (checked) setAgreedPrivacyError(false);
4185
+ },
4099
4186
  required: true
4100
4187
  }
4101
4188
  ),
@@ -4103,7 +4190,8 @@ function FFIDInquiryForm({
4103
4190
  renderPrivacyLink(),
4104
4191
  " \u306B\u540C\u610F\u3057\u307E\u3059\u3002"
4105
4192
  ] })
4106
- ] })
4193
+ ] }),
4194
+ agreedPrivacyError && /* @__PURE__ */ jsx("p", { role: "alert", style: s(errorTextStyle), className: classNames?.errorText, children: PRIVACY_REQUIRED_ERROR_JA })
4107
4195
  ] }) : /* @__PURE__ */ jsx("div", { style: s(fieldsetStyle), className: classNames?.legalBlock, children: /* @__PURE__ */ jsxs("label", { style: s(legalRowLast), className: classNames?.legalRow, children: [
4108
4196
  /* @__PURE__ */ jsx(
4109
4197
  "input",
@@ -4151,4 +4239,4 @@ function FFIDInquiryForm({
4151
4239
  );
4152
4240
  }
4153
4241
 
4154
- export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSDKError, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_INQUIRY_CATEGORIES, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useFFIDContext, useSubscription, withSubscription };
4242
+ export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSDKError, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_INQUIRY_CATEGORIES, FFID_INQUIRY_CATEGORIES_SITE_2026, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, isFFIDInquiryCategorySite2026, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useFFIDContext, useSubscription, withSubscription };
@@ -760,8 +760,34 @@ function createMembersMethods(deps) {
760
760
  return { listMembers, updateMemberRole, removeMember };
761
761
  }
762
762
 
763
+ // src/client/profile-methods.ts
764
+ var EXT_PROFILE_ENDPOINT = "/api/v1/users/ext/me";
765
+ function createProfileMethods(deps) {
766
+ const { fetchWithAuth, createError } = deps;
767
+ async function getProfile() {
768
+ return fetchWithAuth(EXT_PROFILE_ENDPOINT);
769
+ }
770
+ async function updateProfile(data) {
771
+ if (data === null || typeof data !== "object" || Array.isArray(data)) {
772
+ return {
773
+ error: createError("VALIDATION_ERROR", "data \u306F\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059")
774
+ };
775
+ }
776
+ if (Object.keys(data).length === 0) {
777
+ return {
778
+ error: createError("VALIDATION_ERROR", "\u66F4\u65B0\u3059\u308B\u30D5\u30A3\u30FC\u30EB\u30C9\u30921\u3064\u4EE5\u4E0A\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044")
779
+ };
780
+ }
781
+ return fetchWithAuth(EXT_PROFILE_ENDPOINT, {
782
+ method: "PUT",
783
+ body: JSON.stringify(data)
784
+ });
785
+ }
786
+ return { getProfile, updateProfile };
787
+ }
788
+
763
789
  // src/client/version-check.ts
764
- var SDK_VERSION = "2.12.1";
790
+ var SDK_VERSION = "2.14.0";
765
791
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
766
792
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
767
793
  function sdkHeaders() {
@@ -2145,6 +2171,10 @@ function createFFIDClient(config) {
2145
2171
  createError,
2146
2172
  serviceCode: config.serviceCode
2147
2173
  });
2174
+ const { getProfile, updateProfile } = createProfileMethods({
2175
+ fetchWithAuth,
2176
+ createError
2177
+ });
2148
2178
  const {
2149
2179
  requestPasswordReset,
2150
2180
  verifyPasswordResetToken,
@@ -2216,6 +2246,8 @@ function createFFIDClient(config) {
2216
2246
  listMembers,
2217
2247
  updateMemberRole,
2218
2248
  removeMember,
2249
+ getProfile,
2250
+ updateProfile,
2219
2251
  createCheckoutSession,
2220
2252
  createPortalSession,
2221
2253
  listPlans,
@@ -3600,8 +3632,34 @@ var FFID_INQUIRY_CATEGORIES = [
3600
3632
  "press",
3601
3633
  "other"
3602
3634
  ];
3635
+ var FFID_INQUIRY_CATEGORIES_SITE_2026 = [
3636
+ // サービス
3637
+ "consulting",
3638
+ "saas",
3639
+ "development",
3640
+ // プロダクト
3641
+ "agent-hub",
3642
+ "ai-feel-chatbot",
3643
+ "knowledge-db",
3644
+ "biz-simulator",
3645
+ "discussion-board",
3646
+ "realtime-ai",
3647
+ // その他
3648
+ "partnership",
3649
+ "media",
3650
+ "recruiting",
3651
+ "other"
3652
+ ];
3653
+ var isFFIDInquiryCategorySite2026 = (value) => FFID_INQUIRY_CATEGORIES_SITE_2026.includes(value);
3603
3654
  var CATEGORY_PLACEHOLDER_LABEL_JA = "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044";
3604
3655
  var CATEGORY_REQUIRED_ERROR_JA = "\u304A\u554F\u3044\u5408\u308F\u305B\u7A2E\u5225\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002";
3656
+ var TERMS_REQUIRED_ERROR_JA = "\u5229\u7528\u898F\u7D04\u3078\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002";
3657
+ var PRIVACY_REQUIRED_ERROR_JA = "\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30DD\u30EA\u30B7\u30FC\u3078\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002";
3658
+ var TURNSTILE_PENDING_ERROR_JA = "\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30C1\u30A7\u30C3\u30AF\u306E\u5B8C\u4E86\u5F8C\u306B\u9001\u4FE1\u3057\u3066\u304F\u3060\u3055\u3044\u3002";
3659
+ function hasSatisfiedTurnstile(turnstileSlot, turnstileToken) {
3660
+ if (turnstileSlot == null) return true;
3661
+ return (turnstileToken ?? "").trim().length > 0;
3662
+ }
3605
3663
  var SUBMIT_BUTTON_OPACITY_PENDING = 0.6;
3606
3664
  var labelStyle = {
3607
3665
  display: "block",
@@ -3671,6 +3729,23 @@ function defaultCategories() {
3671
3729
  label: DEFAULT_CATEGORY_LABELS_JA[value]
3672
3730
  }));
3673
3731
  }
3732
+ function warnOnGroupLabelConflicts(options) {
3733
+ if (process.env.NODE_ENV === "production") return;
3734
+ const firstExplicitLabel = /* @__PURE__ */ new Map();
3735
+ const warnedGroups = /* @__PURE__ */ new Set();
3736
+ for (const opt of options) {
3737
+ if (!opt.group || opt.groupLabel === void 0) continue;
3738
+ const firstLabel = firstExplicitLabel.get(opt.group);
3739
+ if (firstLabel === void 0) {
3740
+ firstExplicitLabel.set(opt.group, opt.groupLabel);
3741
+ } else if (firstLabel !== opt.groupLabel && !warnedGroups.has(opt.group)) {
3742
+ warnedGroups.add(opt.group);
3743
+ console.warn(
3744
+ `[FFIDInquiryForm] group "${opt.group}" has conflicting groupLabels: "${firstLabel}" (first-wins) vs "${opt.groupLabel}" (ignored). Pass the same groupLabel for every item in the group, or omit it on all but the first.`
3745
+ );
3746
+ }
3747
+ }
3748
+ }
3674
3749
  function renderCategoryOptions(options) {
3675
3750
  const hasAnyGroup = options.some((o) => !!o.group);
3676
3751
  if (!hasAnyGroup) {
@@ -3723,6 +3798,9 @@ function FFIDInquiryForm({
3723
3798
  () => categories && categories.length > 0 ? categories : defaultCategories(),
3724
3799
  [categories]
3725
3800
  );
3801
+ react.useEffect(() => {
3802
+ warnOnGroupLabelConflicts(categoryOptions);
3803
+ }, [categoryOptions]);
3726
3804
  const initialOrgId = react.useMemo(() => {
3727
3805
  if (!isAuth) return null;
3728
3806
  if (preselectedOrganizationId !== void 0) return preselectedOrganizationId;
@@ -3756,6 +3834,8 @@ function FFIDInquiryForm({
3756
3834
  const [agreedLegal, setAgreedLegal] = react.useState(false);
3757
3835
  const [agreedTerms, setAgreedTerms] = react.useState(false);
3758
3836
  const [agreedPrivacy, setAgreedPrivacy] = react.useState(false);
3837
+ const [agreedTermsError, setAgreedTermsError] = react.useState(false);
3838
+ const [agreedPrivacyError, setAgreedPrivacyError] = react.useState(false);
3759
3839
  const [submitting, setSubmitting] = react.useState(false);
3760
3840
  const [formError, setFormError] = react.useState(null);
3761
3841
  const [successMessage, setSuccessMessage] = react.useState(null);
@@ -3773,7 +3853,7 @@ function FFIDInquiryForm({
3773
3853
  onChangeRef.current = onChange;
3774
3854
  }, [onChange]);
3775
3855
  react.useEffect(() => {
3776
- if (category === "") return;
3856
+ if (category === "" || successMessage) return;
3777
3857
  onChangeRef.current?.({
3778
3858
  name: name.trim(),
3779
3859
  email: email.trim(),
@@ -3802,25 +3882,19 @@ function FFIDInquiryForm({
3802
3882
  termsVersion,
3803
3883
  privacyVersion,
3804
3884
  turnstileToken,
3805
- locale
3885
+ locale,
3886
+ successMessage
3806
3887
  ]);
3807
3888
  const s = (style) => styleOrUndefined(style, unstyled);
3808
3889
  async function handleSubmit(e) {
3809
3890
  e.preventDefault();
3810
3891
  setFormError(null);
3811
3892
  if (separateLegalCheckboxes) {
3812
- if (!agreedTerms && !agreedPrivacy) {
3813
- setFormError("\u5229\u7528\u898F\u7D04\u3068\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30DD\u30EA\u30B7\u30FC\u3078\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002");
3814
- return;
3815
- }
3816
- if (!agreedTerms) {
3817
- setFormError("\u5229\u7528\u898F\u7D04\u3078\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002");
3818
- return;
3819
- }
3820
- if (!agreedPrivacy) {
3821
- setFormError("\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30DD\u30EA\u30B7\u30FC\u3078\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002");
3822
- return;
3823
- }
3893
+ const termsInvalid = !agreedTerms;
3894
+ const privacyInvalid = !agreedPrivacy;
3895
+ setAgreedTermsError(termsInvalid);
3896
+ setAgreedPrivacyError(privacyInvalid);
3897
+ if (termsInvalid || privacyInvalid) return;
3824
3898
  } else if (!agreedLegal) {
3825
3899
  setFormError("\u5229\u7528\u898F\u7D04\u3068\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30DD\u30EA\u30B7\u30FC\u3078\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002");
3826
3900
  return;
@@ -3837,6 +3911,10 @@ function FFIDInquiryForm({
3837
3911
  setFormError("\u304A\u540D\u524D\u3068\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
3838
3912
  return;
3839
3913
  }
3914
+ if (!isAuth && !hasSatisfiedTurnstile(turnstileSlot, turnstileToken)) {
3915
+ setFormError(TURNSTILE_PENDING_ERROR_JA);
3916
+ return;
3917
+ }
3840
3918
  setSubmitting(true);
3841
3919
  try {
3842
3920
  const result = await onSubmit({
@@ -3914,7 +3992,7 @@ function FFIDInquiryForm({
3914
3992
  onSubmit: handleSubmit,
3915
3993
  className: cx(className, classNames?.form),
3916
3994
  noValidate: true,
3917
- "data-hydrated": hydrated ? "true" : void 0,
3995
+ "data-hydrated": hydrated ? "true" : "false",
3918
3996
  children: [
3919
3997
  showOrgBlock && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: s(fieldsetStyle), className: cx(classNames?.field, classNames?.orgSelectWrapper), children: [
3920
3998
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: s(labelStyle), className: classNames?.label, htmlFor: "ffid-inquiry-org", children: "\u554F\u3044\u5408\u308F\u305B\u308B\u7ACB\u5834" }),
@@ -4081,7 +4159,11 @@ function FFIDInquiryForm({
4081
4159
  type: "checkbox",
4082
4160
  className: classNames?.legalCheckbox,
4083
4161
  checked: agreedTerms,
4084
- onChange: (e) => setAgreedTerms(e.target.checked),
4162
+ onChange: (e) => {
4163
+ const checked = e.target.checked;
4164
+ setAgreedTerms(checked);
4165
+ if (checked) setAgreedTermsError(false);
4166
+ },
4085
4167
  required: true
4086
4168
  }
4087
4169
  ),
@@ -4090,6 +4172,7 @@ function FFIDInquiryForm({
4090
4172
  " \u306B\u540C\u610F\u3057\u307E\u3059\u3002"
4091
4173
  ] })
4092
4174
  ] }),
4175
+ agreedTermsError && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", style: s(errorTextStyle), className: classNames?.errorText, children: TERMS_REQUIRED_ERROR_JA }),
4093
4176
  /* @__PURE__ */ jsxRuntime.jsxs("label", { style: s(legalRowLast), className: classNames?.legalRow, children: [
4094
4177
  /* @__PURE__ */ jsxRuntime.jsx(
4095
4178
  "input",
@@ -4097,7 +4180,11 @@ function FFIDInquiryForm({
4097
4180
  type: "checkbox",
4098
4181
  className: classNames?.legalCheckbox,
4099
4182
  checked: agreedPrivacy,
4100
- onChange: (e) => setAgreedPrivacy(e.target.checked),
4183
+ onChange: (e) => {
4184
+ const checked = e.target.checked;
4185
+ setAgreedPrivacy(checked);
4186
+ if (checked) setAgreedPrivacyError(false);
4187
+ },
4101
4188
  required: true
4102
4189
  }
4103
4190
  ),
@@ -4105,7 +4192,8 @@ function FFIDInquiryForm({
4105
4192
  renderPrivacyLink(),
4106
4193
  " \u306B\u540C\u610F\u3057\u307E\u3059\u3002"
4107
4194
  ] })
4108
- ] })
4195
+ ] }),
4196
+ agreedPrivacyError && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", style: s(errorTextStyle), className: classNames?.errorText, children: PRIVACY_REQUIRED_ERROR_JA })
4109
4197
  ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: s(fieldsetStyle), className: classNames?.legalBlock, children: /* @__PURE__ */ jsxRuntime.jsxs("label", { style: s(legalRowLast), className: classNames?.legalRow, children: [
4110
4198
  /* @__PURE__ */ jsxRuntime.jsx(
4111
4199
  "input",
@@ -4165,11 +4253,13 @@ exports.FFIDSubscriptionBadge = FFIDSubscriptionBadge;
4165
4253
  exports.FFIDUserMenu = FFIDUserMenu;
4166
4254
  exports.FFID_ANNOUNCEMENTS_ERROR_CODES = FFID_ANNOUNCEMENTS_ERROR_CODES;
4167
4255
  exports.FFID_INQUIRY_CATEGORIES = FFID_INQUIRY_CATEGORIES;
4256
+ exports.FFID_INQUIRY_CATEGORIES_SITE_2026 = FFID_INQUIRY_CATEGORIES_SITE_2026;
4168
4257
  exports.createFFIDAnnouncementsClient = createFFIDAnnouncementsClient;
4169
4258
  exports.createFFIDClient = createFFIDClient;
4170
4259
  exports.createTokenStore = createTokenStore;
4171
4260
  exports.generateCodeChallenge = generateCodeChallenge;
4172
4261
  exports.generateCodeVerifier = generateCodeVerifier;
4262
+ exports.isFFIDInquiryCategorySite2026 = isFFIDInquiryCategorySite2026;
4173
4263
  exports.normalizeRedirectUri = normalizeRedirectUri;
4174
4264
  exports.retrieveCodeVerifier = retrieveCodeVerifier;
4175
4265
  exports.storeCodeVerifier = storeCodeVerifier;
@@ -1,34 +1,34 @@
1
1
  'use strict';
2
2
 
3
- var chunkDJPOGNAO_cjs = require('../chunk-DJPOGNAO.cjs');
3
+ var chunkKMGY6PQY_cjs = require('../chunk-KMGY6PQY.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
8
8
  enumerable: true,
9
- get: function () { return chunkDJPOGNAO_cjs.FFIDAnnouncementBadge; }
9
+ get: function () { return chunkKMGY6PQY_cjs.FFIDAnnouncementBadge; }
10
10
  });
11
11
  Object.defineProperty(exports, "FFIDAnnouncementList", {
12
12
  enumerable: true,
13
- get: function () { return chunkDJPOGNAO_cjs.FFIDAnnouncementList; }
13
+ get: function () { return chunkKMGY6PQY_cjs.FFIDAnnouncementList; }
14
14
  });
15
15
  Object.defineProperty(exports, "FFIDInquiryForm", {
16
16
  enumerable: true,
17
- get: function () { return chunkDJPOGNAO_cjs.FFIDInquiryForm; }
17
+ get: function () { return chunkKMGY6PQY_cjs.FFIDInquiryForm; }
18
18
  });
19
19
  Object.defineProperty(exports, "FFIDLoginButton", {
20
20
  enumerable: true,
21
- get: function () { return chunkDJPOGNAO_cjs.FFIDLoginButton; }
21
+ get: function () { return chunkKMGY6PQY_cjs.FFIDLoginButton; }
22
22
  });
23
23
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
24
24
  enumerable: true,
25
- get: function () { return chunkDJPOGNAO_cjs.FFIDOrganizationSwitcher; }
25
+ get: function () { return chunkKMGY6PQY_cjs.FFIDOrganizationSwitcher; }
26
26
  });
27
27
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
28
28
  enumerable: true,
29
- get: function () { return chunkDJPOGNAO_cjs.FFIDSubscriptionBadge; }
29
+ get: function () { return chunkKMGY6PQY_cjs.FFIDSubscriptionBadge; }
30
30
  });
31
31
  Object.defineProperty(exports, "FFIDUserMenu", {
32
32
  enumerable: true,
33
- get: function () { return chunkDJPOGNAO_cjs.FFIDUserMenu; }
33
+ get: function () { return chunkKMGY6PQY_cjs.FFIDUserMenu; }
34
34
  });
@@ -1,3 +1,3 @@
1
- export { H as FFIDAnnouncementBadge, ad as FFIDAnnouncementBadgeClassNames, ae as FFIDAnnouncementBadgeProps, I as FFIDAnnouncementList, af as FFIDAnnouncementListClassNames, ag as FFIDAnnouncementListProps, Q as FFIDInquiryForm, R as FFIDInquiryFormCategoryItem, S as FFIDInquiryFormClassNames, T as FFIDInquiryFormOrganization, U as FFIDInquiryFormPlaceholderContext, V as FFIDInquiryFormPrefill, W as FFIDInquiryFormProps, X as FFIDInquiryFormSubmitData, Y as FFIDInquiryFormSubmitResult, _ as FFIDLoginButton, ah as FFIDLoginButtonProps, a4 as FFIDOrganizationSwitcher, ai as FFIDOrganizationSwitcherClassNames, aj as FFIDOrganizationSwitcherProps, a6 as FFIDSubscriptionBadge, ak as FFIDSubscriptionBadgeClassNames, al as FFIDSubscriptionBadgeProps, a8 as FFIDUserMenu, am as FFIDUserMenuClassNames, an as FFIDUserMenuProps } from '../index-BuT9VaRt.cjs';
1
+ export { J as FFIDAnnouncementBadge, ai as FFIDAnnouncementBadgeClassNames, aj as FFIDAnnouncementBadgeProps, K as FFIDAnnouncementList, ak as FFIDAnnouncementListClassNames, al as FFIDAnnouncementListProps, T as FFIDInquiryForm, U as FFIDInquiryFormCategoryItem, V as FFIDInquiryFormClassNames, W as FFIDInquiryFormOrganization, X as FFIDInquiryFormPlaceholderContext, Y as FFIDInquiryFormPrefill, Z as FFIDInquiryFormProps, _ as FFIDInquiryFormSubmitData, $ as FFIDInquiryFormSubmitResult, a1 as FFIDLoginButton, am as FFIDLoginButtonProps, a7 as FFIDOrganizationSwitcher, an as FFIDOrganizationSwitcherClassNames, ao as FFIDOrganizationSwitcherProps, a9 as FFIDSubscriptionBadge, ap as FFIDSubscriptionBadgeClassNames, aq as FFIDSubscriptionBadgeProps, ab as FFIDUserMenu, ar as FFIDUserMenuClassNames, as as FFIDUserMenuProps } from '../index-DT3wF1vZ.cjs';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1,3 +1,3 @@
1
- export { H as FFIDAnnouncementBadge, ad as FFIDAnnouncementBadgeClassNames, ae as FFIDAnnouncementBadgeProps, I as FFIDAnnouncementList, af as FFIDAnnouncementListClassNames, ag as FFIDAnnouncementListProps, Q as FFIDInquiryForm, R as FFIDInquiryFormCategoryItem, S as FFIDInquiryFormClassNames, T as FFIDInquiryFormOrganization, U as FFIDInquiryFormPlaceholderContext, V as FFIDInquiryFormPrefill, W as FFIDInquiryFormProps, X as FFIDInquiryFormSubmitData, Y as FFIDInquiryFormSubmitResult, _ as FFIDLoginButton, ah as FFIDLoginButtonProps, a4 as FFIDOrganizationSwitcher, ai as FFIDOrganizationSwitcherClassNames, aj as FFIDOrganizationSwitcherProps, a6 as FFIDSubscriptionBadge, ak as FFIDSubscriptionBadgeClassNames, al as FFIDSubscriptionBadgeProps, a8 as FFIDUserMenu, am as FFIDUserMenuClassNames, an as FFIDUserMenuProps } from '../index-BuT9VaRt.js';
1
+ export { J as FFIDAnnouncementBadge, ai as FFIDAnnouncementBadgeClassNames, aj as FFIDAnnouncementBadgeProps, K as FFIDAnnouncementList, ak as FFIDAnnouncementListClassNames, al as FFIDAnnouncementListProps, T as FFIDInquiryForm, U as FFIDInquiryFormCategoryItem, V as FFIDInquiryFormClassNames, W as FFIDInquiryFormOrganization, X as FFIDInquiryFormPlaceholderContext, Y as FFIDInquiryFormPrefill, Z as FFIDInquiryFormProps, _ as FFIDInquiryFormSubmitData, $ as FFIDInquiryFormSubmitResult, a1 as FFIDLoginButton, am as FFIDLoginButtonProps, a7 as FFIDOrganizationSwitcher, an as FFIDOrganizationSwitcherClassNames, ao as FFIDOrganizationSwitcherProps, a9 as FFIDSubscriptionBadge, ap as FFIDSubscriptionBadgeClassNames, aq as FFIDSubscriptionBadgeProps, ab as FFIDUserMenu, ar as FFIDUserMenuClassNames, as as FFIDUserMenuProps } from '../index-DT3wF1vZ.js';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1 +1 @@
1
- export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-MDBV4WY3.js';
1
+ export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-424GEJSP.js';