| @@ -164,9 +164,9 @@ | ||
| 164 | 164 | actionArea, |
| 165 | 165 | children |
| 166 | 166 | }) { |
| 167 | 167 | const headingId = (0, import_element.useId)(); |
| 168 | - return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.__experimentalItem, { className, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_components.__experimentalVStack, { spacing: 4, role: "group", "aria-labelledby": headingId, children: [ | |
| 168 | + return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.__experimentalItem, { className, role: "listitem", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_components.__experimentalVStack, { spacing: 4, role: "group", "aria-labelledby": headingId, children: [ | |
| 169 | 169 | /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_components.__experimentalHStack, { alignment: "center", spacing: 4, wrap: true, children: [ |
| 170 | 170 | logo, |
| 171 | 171 | /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.FlexBlock, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_components.__experimentalVStack, { spacing: 0, children: [ |
| 172 | 172 | /* @__PURE__ */ (0, import_jsx_runtime.jsx)( |
| @@ -171,9 +171,9 @@ | ||
| 171 | 171 | /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.FlexBlock, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_components.__experimentalVStack, { spacing: 0, children: [ |
| 172 | 172 | /* @__PURE__ */ (0, import_jsx_runtime.jsx)( |
| 173 | 173 | import_components.__experimentalText, |
| 174 | 174 | { |
| 175 | - weight: 600, | |
| 175 | + weight: "var(--wpds-typography-font-weight-emphasis, 600)", | |
| 176 | 176 | size: 15, |
| 177 | 177 | id: headingId, |
| 178 | 178 | as: "h2", |
| 179 | 179 | children: name |
| @@ -185,8 +185,97 @@ | ||
| 185 | 185 | ] }), |
| 186 | 186 | children |
| 187 | 187 | ] }) }); |
| 188 | 188 | } |
| 189 | +function getHelpLinkLabel(helpUrl, helpLabel) { | |
| 190 | + if (helpLabel) { | |
| 191 | + return helpLabel; | |
| 192 | + } | |
| 193 | + if (!helpUrl) { | |
| 194 | + return void 0; | |
| 195 | + } | |
| 196 | + try { | |
| 197 | + return new URL(helpUrl).hostname; | |
| 198 | + } catch { | |
| 199 | + return helpUrl; | |
| 200 | + } | |
| 201 | +} | |
| 202 | +function createConnectorHelpLink(helpUrl, helpLabel, message) { | |
| 203 | + if (!helpUrl) { | |
| 204 | + return void 0; | |
| 205 | + } | |
| 206 | + return (0, import_element.createInterpolateElement)( | |
| 207 | + (0, import_i18n.sprintf)(message, "<a></a>"), | |
| 208 | + { | |
| 209 | + a: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.ExternalLink, { href: helpUrl, children: getHelpLinkLabel(helpUrl, helpLabel) }) | |
| 210 | + } | |
| 211 | + ); | |
| 212 | +} | |
| 213 | +function useConnectorSettingsSave(onSave, fallbackErrorMessage) { | |
| 214 | + const [isSaving, setIsSaving] = (0, import_element.useState)(false); | |
| 215 | + const [saveError, setSaveError] = (0, import_element.useState)(null); | |
| 216 | + const handleSave = async (value) => { | |
| 217 | + setSaveError(null); | |
| 218 | + setIsSaving(true); | |
| 219 | + try { | |
| 220 | + await onSave?.(value); | |
| 221 | + } catch (error) { | |
| 222 | + setSaveError( | |
| 223 | + error instanceof Error ? error.message : fallbackErrorMessage | |
| 224 | + ); | |
| 225 | + } finally { | |
| 226 | + setIsSaving(false); | |
| 227 | + } | |
| 228 | + }; | |
| 229 | + return { | |
| 230 | + isSaving, | |
| 231 | + saveError, | |
| 232 | + setSaveError, | |
| 233 | + handleSave | |
| 234 | + }; | |
| 235 | +} | |
| 236 | +function ConnectorSettingsFrame({ | |
| 237 | + readOnly, | |
| 238 | + children | |
| 239 | +}) { | |
| 240 | + return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( | |
| 241 | + import_components.__experimentalVStack, | |
| 242 | + { | |
| 243 | + spacing: 4, | |
| 244 | + className: "connector-settings", | |
| 245 | + style: readOnly ? { | |
| 246 | + "--wp-components-color-background": "#f0f0f0" | |
| 247 | + } : void 0, | |
| 248 | + children | |
| 249 | + } | |
| 250 | + ); | |
| 251 | +} | |
| 252 | +function ConnectorSettingsFooter({ | |
| 253 | + readOnly, | |
| 254 | + onRemove, | |
| 255 | + canSave, | |
| 256 | + isSaving, | |
| 257 | + onSave | |
| 258 | +}) { | |
| 259 | + if (readOnly) { | |
| 260 | + if (!onRemove) { | |
| 261 | + return null; | |
| 262 | + } | |
| 263 | + return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.__experimentalHStack, { justify: "flex-start", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.Button, { variant: "link", isDestructive: true, onClick: onRemove, children: (0, import_i18n.__)("Remove and replace") }) }); | |
| 264 | + } | |
| 265 | + return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.__experimentalHStack, { justify: "flex-start", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( | |
| 266 | + import_components.Button, | |
| 267 | + { | |
| 268 | + __next40pxDefaultSize: true, | |
| 269 | + variant: "primary", | |
| 270 | + disabled: !canSave || isSaving, | |
| 271 | + accessibleWhenDisabled: true, | |
| 272 | + isBusy: isSaving, | |
| 273 | + onClick: onSave, | |
| 274 | + children: (0, import_i18n.__)("Save") | |
| 275 | + } | |
| 276 | + ) }); | |
| 277 | +} | |
| 189 | 278 | function DefaultConnectorSettings({ |
| 190 | 279 | onSave, |
| 191 | 280 | onRemove, |
| 192 | 281 | initialValue = "", |
| @@ -195,21 +284,20 @@ | ||
| 195 | 284 | readOnly = false, |
| 196 | 285 | keySource |
| 197 | 286 | }) { |
| 198 | 287 | const [apiKey, setApiKey] = (0, import_element.useState)(initialValue); |
| 199 | - const [isSaving, setIsSaving] = (0, import_element.useState)(false); | |
| 200 | - const [saveError, setSaveError] = (0, import_element.useState)(null); | |
| 201 | - const helpLinkLabel = helpLabel || helpUrl?.replace(/^https?:\/\//, ""); | |
| 202 | - const helpLink = helpUrl ? (0, import_element.createInterpolateElement)( | |
| 203 | - (0, import_i18n.sprintf)( | |
| 204 | - /* translators: %s: Link to provider settings. */ | |
| 205 | - (0, import_i18n.__)("Get your API key at %s"), | |
| 206 | - "<a></a>" | |
| 207 | - ), | |
| 208 | - { | |
| 209 | - a: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.ExternalLink, { href: helpUrl, children: helpLinkLabel }) | |
| 210 | - } | |
| 211 | - ) : void 0; | |
| 288 | + const { isSaving, saveError, setSaveError, handleSave } = useConnectorSettingsSave( | |
| 289 | + onSave, | |
| 290 | + (0, import_i18n.__)( | |
| 291 | + "It was not possible to connect to the provider using this key." | |
| 292 | + ) | |
| 293 | + ); | |
| 294 | + const helpLink = createConnectorHelpLink( | |
| 295 | + helpUrl, | |
| 296 | + helpLabel, | |
| 297 | + /* translators: %s: Link to provider settings. */ | |
| 298 | + (0, import_i18n.__)("Get your API key at %s") | |
| 299 | + ); | |
| 212 | 300 | const isExternallyConfigured = keySource === "env" || keySource === "constant"; |
| 213 | 301 | const getHelp = () => { |
| 214 | 302 | if (isExternallyConfigured) { |
| 215 | 303 | if (keySource === "env") { |
| @@ -221,19 +309,15 @@ | ||
| 221 | 309 | return (0, import_i18n.__)("This API key is configured as a constant."); |
| 222 | 310 | } |
| 223 | 311 | } |
| 224 | 312 | if (readOnly) { |
| 225 | - return helpUrl ? (0, import_element.createInterpolateElement)( | |
| 226 | - (0, import_i18n.sprintf)( | |
| 227 | - /* translators: %s: Link to provider settings. */ | |
| 228 | - (0, import_i18n.__)( | |
| 229 | - "Your API key is stored securely. You can manage it at %s" | |
| 230 | - ), | |
| 231 | - "<a></a>" | |
| 232 | - ), | |
| 233 | - { | |
| 234 | - a: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.ExternalLink, { href: helpUrl, children: helpLinkLabel }) | |
| 235 | - } | |
| 313 | + return helpUrl ? createConnectorHelpLink( | |
| 314 | + helpUrl, | |
| 315 | + helpLabel, | |
| 316 | + /* translators: %s: Link to provider settings. */ | |
| 317 | + (0, import_i18n.__)( | |
| 318 | + "Your API key is stored securely. You can manage it at %s" | |
| 319 | + ) | |
| 236 | 320 | ) : (0, import_i18n.__)("Your API key is stored securely."); |
| 237 | 321 | } |
| 238 | 322 | if (saveError) { |
| 239 | 323 | return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { role: "alert", className: "connector-settings__error", children: saveError }); |
| @@ -239,72 +323,125 @@ | ||
| 239 | 323 | return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { role: "alert", className: "connector-settings__error", children: saveError }); |
| 240 | 324 | } |
| 241 | 325 | return helpLink; |
| 242 | 326 | }; |
| 243 | - const handleSave = async () => { | |
| 244 | - setSaveError(null); | |
| 245 | - setIsSaving(true); | |
| 246 | - try { | |
| 247 | - await onSave?.(apiKey); | |
| 248 | - } catch (error) { | |
| 249 | - setSaveError( | |
| 250 | - error instanceof Error ? error.message : (0, import_i18n.__)( | |
| 251 | - "It was not possible to connect to the provider using this key." | |
| 252 | - ) | |
| 253 | - ); | |
| 254 | - } finally { | |
| 255 | - setIsSaving(false); | |
| 256 | - } | |
| 257 | - }; | |
| 258 | - return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( | |
| 259 | - import_components.__experimentalVStack, | |
| 260 | - { | |
| 261 | - spacing: 4, | |
| 262 | - className: "connector-settings", | |
| 263 | - style: readOnly ? { | |
| 264 | - "--wp-components-color-background": "#f0f0f0" | |
| 265 | - } : void 0, | |
| 266 | - children: [ | |
| 267 | - /* @__PURE__ */ (0, import_jsx_runtime.jsx)( | |
| 268 | - import_components.TextControl, | |
| 269 | - { | |
| 270 | - label: (0, import_i18n.__)("API Key"), | |
| 271 | - value: apiKey, | |
| 272 | - onChange: (value) => { | |
| 273 | - if (!readOnly) { | |
| 274 | - setSaveError(null); | |
| 275 | - setApiKey(value); | |
| 276 | - } | |
| 277 | - }, | |
| 278 | - placeholder: (0, import_i18n.__)("Enter your API key"), | |
| 279 | - disabled: readOnly || isSaving, | |
| 280 | - autoComplete: "off", | |
| 281 | - help: getHelp() | |
| 327 | + return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ConnectorSettingsFrame, { readOnly, children: [ | |
| 328 | + /* @__PURE__ */ (0, import_jsx_runtime.jsx)( | |
| 329 | + import_components.TextControl, | |
| 330 | + { | |
| 331 | + label: (0, import_i18n.__)("API Key"), | |
| 332 | + value: apiKey, | |
| 333 | + onChange: (value) => { | |
| 334 | + if (!readOnly) { | |
| 335 | + setSaveError(null); | |
| 336 | + setApiKey(value); | |
| 282 | 337 | } |
| 283 | - ), | |
| 284 | - readOnly ? onRemove && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.__experimentalHStack, { justify: "flex-start", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( | |
| 285 | - import_components.Button, | |
| 286 | - { | |
| 287 | - variant: "link", | |
| 288 | - isDestructive: true, | |
| 289 | - onClick: onRemove, | |
| 290 | - children: (0, import_i18n.__)("Remove and replace") | |
| 338 | + }, | |
| 339 | + placeholder: (0, import_i18n.__)("Enter your API key"), | |
| 340 | + disabled: readOnly || isSaving, | |
| 341 | + autoComplete: "off", | |
| 342 | + help: getHelp() | |
| 343 | + } | |
| 344 | + ), | |
| 345 | + /* @__PURE__ */ (0, import_jsx_runtime.jsx)( | |
| 346 | + ConnectorSettingsFooter, | |
| 347 | + { | |
| 348 | + readOnly, | |
| 349 | + onRemove, | |
| 350 | + canSave: !!apiKey, | |
| 351 | + isSaving, | |
| 352 | + onSave: () => handleSave(apiKey) | |
| 353 | + } | |
| 354 | + ) | |
| 355 | + ] }); | |
| 356 | +} | |
| 357 | +function ApplicationPasswordConnectorSettings({ | |
| 358 | + onSave, | |
| 359 | + onRemove, | |
| 360 | + initialUsername = "", | |
| 361 | + helpUrl, | |
| 362 | + helpLabel, | |
| 363 | + readOnly = false, | |
| 364 | + keySource | |
| 365 | +}) { | |
| 366 | + const [username, setUsername] = (0, import_element.useState)(initialUsername); | |
| 367 | + const [applicationPassword, setApplicationPassword] = (0, import_element.useState)(""); | |
| 368 | + const { isSaving, saveError, setSaveError, handleSave } = useConnectorSettingsSave( | |
| 369 | + onSave, | |
| 370 | + (0, import_i18n.__)("It was not possible to save these credentials.") | |
| 371 | + ); | |
| 372 | + const help = createConnectorHelpLink( | |
| 373 | + helpUrl, | |
| 374 | + helpLabel, | |
| 375 | + /* translators: %s: Link to the remote site's application passwords screen. */ | |
| 376 | + (0, import_i18n.__)("Create an application password at %s") | |
| 377 | + ); | |
| 378 | + let applicationPasswordHelp = help; | |
| 379 | + if (keySource === "env") { | |
| 380 | + applicationPasswordHelp = (0, import_i18n.__)( | |
| 381 | + "These credentials are configured using an environment variable." | |
| 382 | + ); | |
| 383 | + } else if (keySource === "constant") { | |
| 384 | + applicationPasswordHelp = (0, import_i18n.__)( | |
| 385 | + "These credentials are configured as a constant." | |
| 386 | + ); | |
| 387 | + } else if (readOnly) { | |
| 388 | + applicationPasswordHelp = (0, import_i18n.__)( | |
| 389 | + "Your application password is stored securely." | |
| 390 | + ); | |
| 391 | + } | |
| 392 | + if (saveError) { | |
| 393 | + applicationPasswordHelp = /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { role: "alert", className: "connector-settings__error", children: saveError }); | |
| 394 | + } | |
| 395 | + return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ConnectorSettingsFrame, { readOnly, children: [ | |
| 396 | + /* @__PURE__ */ (0, import_jsx_runtime.jsx)( | |
| 397 | + import_components.TextControl, | |
| 398 | + { | |
| 399 | + label: (0, import_i18n.__)("Username"), | |
| 400 | + value: username, | |
| 401 | + onChange: (value) => { | |
| 402 | + if (!readOnly) { | |
| 403 | + setSaveError(null); | |
| 404 | + setUsername(value); | |
| 291 | 405 | } |
| 292 | - ) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.__experimentalHStack, { justify: "flex-start", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( | |
| 293 | - import_components.Button, | |
| 294 | - { | |
| 295 | - __next40pxDefaultSize: true, | |
| 296 | - variant: "primary", | |
| 297 | - disabled: !apiKey || isSaving, | |
| 298 | - accessibleWhenDisabled: true, | |
| 299 | - isBusy: isSaving, | |
| 300 | - onClick: handleSave, | |
| 301 | - children: (0, import_i18n.__)("Save") | |
| 406 | + }, | |
| 407 | + placeholder: (0, import_i18n.__)("Enter your username"), | |
| 408 | + disabled: readOnly || isSaving, | |
| 409 | + autoComplete: "username" | |
| 410 | + } | |
| 411 | + ), | |
| 412 | + /* @__PURE__ */ (0, import_jsx_runtime.jsx)( | |
| 413 | + import_components.TextControl, | |
| 414 | + { | |
| 415 | + label: (0, import_i18n.__)("Application password"), | |
| 416 | + value: readOnly ? "••••••••••••••••" : applicationPassword, | |
| 417 | + onChange: (value) => { | |
| 418 | + if (!readOnly) { | |
| 419 | + setSaveError(null); | |
| 420 | + setApplicationPassword(value); | |
| 302 | 421 | } |
| 303 | - ) }) | |
| 304 | - ] | |
| 305 | - } | |
| 306 | - ); | |
| 422 | + }, | |
| 423 | + type: "password", | |
| 424 | + placeholder: (0, import_i18n.__)("Enter your application password"), | |
| 425 | + disabled: readOnly || isSaving, | |
| 426 | + autoComplete: "new-password", | |
| 427 | + help: applicationPasswordHelp | |
| 428 | + } | |
| 429 | + ), | |
| 430 | + /* @__PURE__ */ (0, import_jsx_runtime.jsx)( | |
| 431 | + ConnectorSettingsFooter, | |
| 432 | + { | |
| 433 | + readOnly, | |
| 434 | + onRemove, | |
| 435 | + canSave: !!username.trim() && !!applicationPassword, | |
| 436 | + isSaving, | |
| 437 | + onSave: () => handleSave({ | |
| 438 | + username: username.trim(), | |
| 439 | + applicationPassword | |
| 440 | + }) | |
| 441 | + } | |
| 442 | + ) | |
| 443 | + ] }); | |
| 307 | 444 | } |
| 308 | 445 | |
| 309 | 446 | // packages/connectors/build-module/private-apis.mjs |
| 310 | 447 | var privateApis = {}; |
| @@ -309,8 +446,9 @@ | ||
| 309 | 446 | // packages/connectors/build-module/private-apis.mjs |
| 310 | 447 | var privateApis = {}; |
| 311 | 448 | lock(privateApis, { store, STORE_NAME }); |
| 312 | 449 | export { |
| 450 | + ApplicationPasswordConnectorSettings as __experimentalApplicationPasswordConnectorSettings, | |
| 313 | 451 | ConnectorItem as __experimentalConnectorItem, |
| 314 | 452 | DefaultConnectorSettings as __experimentalDefaultConnectorSettings, |
| 315 | 453 | registerConnector as __experimentalRegisterConnector, |
| 316 | 454 | unregisterConnector as __experimentalUnregisterConnector, |