@automattic/jetpack-ai-client 0.14.6 → 0.16.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.
Files changed (128) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/build/ask-question/sync.d.ts +2 -8
  3. package/build/ask-question/sync.js +20 -19
  4. package/build/hooks/use-image-generator/index.js +1 -1
  5. package/build/hooks/use-save-to-media-library/index.d.ts +12 -0
  6. package/build/hooks/use-save-to-media-library/index.js +74 -0
  7. package/build/index.d.ts +2 -0
  8. package/build/index.js +5 -0
  9. package/build/libs/index.d.ts +1 -1
  10. package/build/libs/index.js +1 -1
  11. package/build/libs/markdown/index.d.ts +2 -2
  12. package/build/libs/markdown/index.js +2 -2
  13. package/build/libs/markdown/markdown-to-html.d.ts +8 -1
  14. package/build/libs/markdown/markdown-to-html.js +10 -1
  15. package/build/logo-generator/assets/icons/ai.d.ts +6 -0
  16. package/build/logo-generator/assets/icons/ai.js +8 -0
  17. package/build/logo-generator/assets/icons/check.d.ts +6 -0
  18. package/build/logo-generator/assets/icons/check.js +8 -0
  19. package/build/logo-generator/assets/icons/logo.d.ts +6 -0
  20. package/build/logo-generator/assets/icons/logo.js +8 -0
  21. package/build/logo-generator/assets/icons/media.d.ts +6 -0
  22. package/build/logo-generator/assets/icons/media.js +8 -0
  23. package/build/logo-generator/components/feature-fetch-failure-screen.d.ts +8 -0
  24. package/build/logo-generator/components/feature-fetch-failure-screen.js +10 -0
  25. package/build/logo-generator/components/first-load-screen.d.ts +5 -0
  26. package/build/logo-generator/components/first-load-screen.js +16 -0
  27. package/build/logo-generator/components/generator-modal.d.ts +7 -0
  28. package/build/logo-generator/components/generator-modal.js +177 -0
  29. package/build/logo-generator/components/history-carousel.d.ts +6 -0
  30. package/build/logo-generator/components/history-carousel.js +36 -0
  31. package/build/logo-generator/components/image-loader.d.ts +7 -0
  32. package/build/logo-generator/components/image-loader.js +12 -0
  33. package/build/logo-generator/components/logo-presenter.d.ts +4 -0
  34. package/build/logo-generator/components/logo-presenter.js +100 -0
  35. package/build/logo-generator/components/prompt.d.ts +5 -0
  36. package/build/logo-generator/components/prompt.js +96 -0
  37. package/build/logo-generator/components/upgrade-nudge.d.ts +2 -0
  38. package/build/logo-generator/components/upgrade-nudge.js +30 -0
  39. package/build/logo-generator/components/upgrade-screen.d.ts +9 -0
  40. package/build/logo-generator/components/upgrade-screen.js +24 -0
  41. package/build/logo-generator/components/visit-site-banner.d.ts +9 -0
  42. package/build/logo-generator/components/visit-site-banner.js +16 -0
  43. package/build/logo-generator/constants.d.ts +16 -0
  44. package/build/logo-generator/constants.js +19 -0
  45. package/build/logo-generator/hooks/use-checkout.d.ts +4 -0
  46. package/build/logo-generator/hooks/use-checkout.js +26 -0
  47. package/build/logo-generator/hooks/use-logo-generator.d.ts +46 -0
  48. package/build/logo-generator/hooks/use-logo-generator.js +286 -0
  49. package/build/logo-generator/hooks/use-request-errors.d.ts +16 -0
  50. package/build/logo-generator/hooks/use-request-errors.js +46 -0
  51. package/build/logo-generator/index.d.ts +1 -0
  52. package/build/logo-generator/index.js +1 -0
  53. package/build/logo-generator/lib/logo-storage.d.ts +58 -0
  54. package/build/logo-generator/lib/logo-storage.js +123 -0
  55. package/build/logo-generator/lib/media-exists.d.ts +12 -0
  56. package/build/logo-generator/lib/media-exists.js +33 -0
  57. package/build/logo-generator/lib/set-site-logo.d.ts +13 -0
  58. package/build/logo-generator/lib/set-site-logo.js +26 -0
  59. package/build/logo-generator/lib/wpcom-limited-request.d.ts +7 -0
  60. package/build/logo-generator/lib/wpcom-limited-request.js +25 -0
  61. package/build/logo-generator/store/actions.d.ts +105 -0
  62. package/build/logo-generator/store/actions.js +193 -0
  63. package/build/logo-generator/store/constants.d.ts +44 -0
  64. package/build/logo-generator/store/constants.js +44 -0
  65. package/build/logo-generator/store/index.d.ts +1 -0
  66. package/build/logo-generator/store/index.js +19 -0
  67. package/build/logo-generator/store/initial-state.d.ts +3 -0
  68. package/build/logo-generator/store/initial-state.js +40 -0
  69. package/build/logo-generator/store/reducer.d.ts +347 -0
  70. package/build/logo-generator/store/reducer.js +293 -0
  71. package/build/logo-generator/store/selectors.d.ts +119 -0
  72. package/build/logo-generator/store/selectors.js +173 -0
  73. package/build/logo-generator/store/types.d.ts +164 -0
  74. package/build/logo-generator/store/types.js +1 -0
  75. package/build/logo-generator/types.d.ts +84 -0
  76. package/build/logo-generator/types.js +1 -0
  77. package/build/types.d.ts +6 -0
  78. package/package.json +5 -3
  79. package/src/ask-question/sync.ts +22 -27
  80. package/src/hooks/use-image-generator/index.ts +1 -1
  81. package/src/hooks/use-save-to-media-library/index.ts +95 -0
  82. package/src/index.ts +6 -0
  83. package/src/libs/index.ts +1 -0
  84. package/src/libs/markdown/index.ts +2 -2
  85. package/src/libs/markdown/markdown-to-html.ts +20 -3
  86. package/src/logo-generator/assets/icons/ai.tsx +21 -0
  87. package/src/logo-generator/assets/icons/check.tsx +23 -0
  88. package/src/logo-generator/assets/icons/icons.scss +5 -0
  89. package/src/logo-generator/assets/icons/logo.tsx +23 -0
  90. package/src/logo-generator/assets/icons/media.tsx +24 -0
  91. package/src/logo-generator/assets/images/jetpack-logo.svg +4 -0
  92. package/src/logo-generator/assets/images/loader.gif +0 -0
  93. package/src/logo-generator/assets/index.d.ts +3 -0
  94. package/src/logo-generator/components/feature-fetch-failure-screen.tsx +35 -0
  95. package/src/logo-generator/components/first-load-screen.scss +12 -0
  96. package/src/logo-generator/components/first-load-screen.tsx +32 -0
  97. package/src/logo-generator/components/generator-modal.scss +92 -0
  98. package/src/logo-generator/components/generator-modal.tsx +280 -0
  99. package/src/logo-generator/components/history-carousel.scss +36 -0
  100. package/src/logo-generator/components/history-carousel.tsx +57 -0
  101. package/src/logo-generator/components/image-loader.tsx +22 -0
  102. package/src/logo-generator/components/logo-presenter.scss +116 -0
  103. package/src/logo-generator/components/logo-presenter.tsx +219 -0
  104. package/src/logo-generator/components/prompt.scss +102 -0
  105. package/src/logo-generator/components/prompt.tsx +211 -0
  106. package/src/logo-generator/components/upgrade-nudge.scss +43 -0
  107. package/src/logo-generator/components/upgrade-nudge.tsx +58 -0
  108. package/src/logo-generator/components/upgrade-screen.tsx +67 -0
  109. package/src/logo-generator/components/visit-site-banner.scss +29 -0
  110. package/src/logo-generator/components/visit-site-banner.tsx +54 -0
  111. package/src/logo-generator/constants.ts +22 -0
  112. package/src/logo-generator/hooks/use-checkout.ts +37 -0
  113. package/src/logo-generator/hooks/use-logo-generator.ts +389 -0
  114. package/src/logo-generator/hooks/use-request-errors.ts +70 -0
  115. package/src/logo-generator/index.ts +1 -0
  116. package/src/logo-generator/lib/logo-storage.ts +166 -0
  117. package/src/logo-generator/lib/media-exists.ts +42 -0
  118. package/src/logo-generator/lib/set-site-logo.ts +32 -0
  119. package/src/logo-generator/lib/wpcom-limited-request.ts +30 -0
  120. package/src/logo-generator/store/actions.ts +251 -0
  121. package/src/logo-generator/store/constants.ts +49 -0
  122. package/src/logo-generator/store/index.ts +25 -0
  123. package/src/logo-generator/store/initial-state.ts +43 -0
  124. package/src/logo-generator/store/reducer.ts +387 -0
  125. package/src/logo-generator/store/selectors.ts +201 -0
  126. package/src/logo-generator/store/types.ts +207 -0
  127. package/src/logo-generator/types.ts +99 -0
  128. package/src/types.ts +8 -0
@@ -0,0 +1,36 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * External dependencies
4
+ */
5
+ import { useAnalytics } from '@automattic/jetpack-shared-extension-utils';
6
+ import { Button } from '@wordpress/components';
7
+ import clsx from 'clsx';
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import { EVENT_NAVIGATE } from '../constants.js';
12
+ import useLogoGenerator from '../hooks/use-logo-generator.js';
13
+ import './history-carousel.scss';
14
+ export const HistoryCarousel = () => {
15
+ const { tracks } = useAnalytics();
16
+ const { recordEvent: recordTracksEvent } = tracks;
17
+ const { logos, selectedLogo, setSelectedLogoIndex, context } = useLogoGenerator();
18
+ const handleClick = (index) => {
19
+ recordTracksEvent(EVENT_NAVIGATE, {
20
+ context,
21
+ logos_count: logos.length,
22
+ selected_logo: index + 1,
23
+ });
24
+ setSelectedLogoIndex(index);
25
+ };
26
+ const thumbnailFrom = (url) => {
27
+ const thumbnailURL = new URL(url);
28
+ if (!thumbnailURL.searchParams.has('resize')) {
29
+ thumbnailURL.searchParams.append('resize', '48,48');
30
+ }
31
+ return thumbnailURL.toString();
32
+ };
33
+ return (_jsx("div", { className: "jetpack-ai-logo-generator__carousel", children: logos.map((logo, index) => (_jsx(Button, { className: clsx('jetpack-ai-logo-generator__carousel-logo', {
34
+ 'is-selected': logo.url === selectedLogo.url,
35
+ }), onClick: () => handleClick(index), children: _jsx("img", { src: thumbnailFrom(logo.url), alt: logo.description }) }, logo.url))) }));
36
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Types
3
+ */
4
+ import type React from 'react';
5
+ export declare const ImageLoader: React.FC<{
6
+ className?: string;
7
+ }>;
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * External dependencies
4
+ */
5
+ import clsx from 'clsx';
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import loader from '../assets/images/loader.gif';
10
+ export const ImageLoader = ({ className = null }) => {
11
+ return (_jsx("img", { src: loader, alt: "Loading", className: clsx('jetpack-ai-logo-generator-modal__loader', className) }));
12
+ };
@@ -0,0 +1,4 @@
1
+ import './logo-presenter.scss';
2
+ import type { LogoPresenterProps } from '../types.js';
3
+ import type React from 'react';
4
+ export declare const LogoPresenter: React.FC<LogoPresenterProps>;
@@ -0,0 +1,100 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * External dependencies
4
+ */
5
+ import { useAnalytics } from '@automattic/jetpack-shared-extension-utils';
6
+ import { Button, Icon } from '@wordpress/components';
7
+ import { useDispatch } from '@wordpress/data';
8
+ import { __ } from '@wordpress/i18n';
9
+ import debugFactory from 'debug';
10
+ /**
11
+ * Internal dependencies
12
+ */
13
+ import CheckIcon from '../assets/icons/check.js';
14
+ import LogoIcon from '../assets/icons/logo.js';
15
+ import MediaIcon from '../assets/icons/media.js';
16
+ import { EVENT_SAVE, EVENT_USE } from '../constants.js';
17
+ import useLogoGenerator from '../hooks/use-logo-generator.js';
18
+ import useRequestErrors from '../hooks/use-request-errors.js';
19
+ import { updateLogo } from '../lib/logo-storage.js';
20
+ import { STORE_NAME } from '../store/index.js';
21
+ import { ImageLoader } from './image-loader.js';
22
+ import './logo-presenter.scss';
23
+ const debug = debugFactory('jetpack-ai-calypso:logo-presenter');
24
+ const SaveInLibraryButton = ({ siteId }) => {
25
+ const { tracks } = useAnalytics();
26
+ const { recordEvent: recordTracksEvent } = tracks;
27
+ const { saveLogo, selectedLogo, isSavingLogoToLibrary: saving, logos, selectedLogoIndex, context, } = useLogoGenerator();
28
+ const saved = !!selectedLogo?.mediaId;
29
+ const { loadLogoHistory } = useDispatch(STORE_NAME);
30
+ const handleClick = async () => {
31
+ if (!saved && !saving) {
32
+ recordTracksEvent(EVENT_SAVE, {
33
+ context,
34
+ logos_count: logos.length,
35
+ selected_logo: selectedLogoIndex ? selectedLogoIndex + 1 : 0,
36
+ });
37
+ try {
38
+ const savedLogo = await saveLogo(selectedLogo);
39
+ // Update localStorage
40
+ updateLogo({
41
+ siteId,
42
+ url: selectedLogo.url,
43
+ newUrl: savedLogo.mediaURL,
44
+ mediaId: savedLogo.mediaId,
45
+ });
46
+ // Update state
47
+ loadLogoHistory(siteId);
48
+ }
49
+ catch (error) {
50
+ debug('Error saving logo', error);
51
+ }
52
+ }
53
+ };
54
+ const savingLabel = __('Saving…', 'jetpack-ai-client');
55
+ const savedLabel = __('Saved', 'jetpack-ai-client');
56
+ return !saving && !saved ? (_jsxs(Button, { className: "jetpack-ai-logo-generator-modal-presenter__action", onClick: handleClick, children: [_jsx(Icon, { icon: _jsx(MediaIcon, {}) }), _jsx("span", { className: "action-text", children: __('Save in Library', 'jetpack-ai-client') })] })) : (_jsxs("button", { className: "jetpack-ai-logo-generator-modal-presenter__action", children: [_jsx(Icon, { icon: saving ? _jsx(MediaIcon, {}) : _jsx(CheckIcon, {}) }), _jsx("span", { className: "action-text", children: saving ? savingLabel : savedLabel })] }));
57
+ };
58
+ const UseOnSiteButton = ({ onApplyLogo, }) => {
59
+ const { tracks } = useAnalytics();
60
+ const { recordEvent: recordTracksEvent } = tracks;
61
+ const { isSavingLogoToLibrary, selectedLogo, logos, selectedLogoIndex, context } = useLogoGenerator();
62
+ const handleClick = async () => {
63
+ if (!isSavingLogoToLibrary) {
64
+ recordTracksEvent(EVENT_USE, {
65
+ context,
66
+ logos_count: logos.length,
67
+ selected_logo: selectedLogoIndex != null ? selectedLogoIndex + 1 : 0,
68
+ });
69
+ onApplyLogo?.(selectedLogo?.mediaId);
70
+ }
71
+ };
72
+ return (_jsxs(Button, { className: "jetpack-ai-logo-generator-modal-presenter__action", onClick: handleClick, disabled: isSavingLogoToLibrary || !selectedLogo?.mediaId, children: [_jsx(Icon, { icon: _jsx(LogoIcon, {}) }), _jsx("span", { className: "action-text", children: __('Use on block', 'jetpack-ai-client') })] }));
73
+ };
74
+ const LogoLoading = () => {
75
+ return (_jsxs(_Fragment, { children: [_jsx(ImageLoader, { className: "jetpack-ai-logo-generator-modal-presenter__logo" }), _jsx("span", { className: "jetpack-ai-logo-generator-modal-presenter__loading-text", children: __('Generating new logo…', 'jetpack-ai-client') })] }));
76
+ };
77
+ const LogoReady = ({ siteId, logo, onApplyLogo }) => {
78
+ return (_jsxs(_Fragment, { children: [_jsx("img", { src: logo.url, alt: logo.description, className: "jetpack-ai-logo-generator-modal-presenter__logo" }), _jsxs("div", { className: "jetpack-ai-logo-generator-modal-presenter__action-wrapper", children: [_jsx("span", { className: "jetpack-ai-logo-generator-modal-presenter__description", children: logo.description }), _jsxs("div", { className: "jetpack-ai-logo-generator-modal-presenter__actions", children: [_jsx(SaveInLibraryButton, { siteId: siteId }), _jsx(UseOnSiteButton, { onApplyLogo: onApplyLogo })] })] })] }));
79
+ };
80
+ const LogoUpdated = ({ logo }) => {
81
+ return (_jsxs(_Fragment, { children: [_jsx("img", { src: logo.url, alt: logo.description, className: "jetpack-ai-logo-generator-modal-presenter__logo" }), _jsxs("div", { className: "jetpack-ai-logo-generator-modal-presenter__success-wrapper", children: [_jsx(Icon, { icon: _jsx(CheckIcon, {}) }), _jsx("span", { children: __('Your new logo was set to the block!', 'jetpack-ai-client') })] })] }));
82
+ };
83
+ export const LogoPresenter = ({ logo = null, loading = false, onApplyLogo, logoAccepted = false, siteId, }) => {
84
+ const { isRequestingImage } = useLogoGenerator();
85
+ const { saveToLibraryError, logoUpdateError } = useRequestErrors();
86
+ if (!logo) {
87
+ return null;
88
+ }
89
+ let logoContent;
90
+ if (loading || isRequestingImage) {
91
+ logoContent = _jsx(LogoLoading, {});
92
+ }
93
+ else if (logoAccepted) {
94
+ logoContent = _jsx(LogoUpdated, { logo: logo });
95
+ }
96
+ else {
97
+ logoContent = (_jsx(LogoReady, { siteId: String(siteId), logo: logo, onApplyLogo: onApplyLogo }));
98
+ }
99
+ return (_jsxs("div", { className: "jetpack-ai-logo-generator-modal-presenter__wrapper", children: [_jsxs("div", { className: "jetpack-ai-logo-generator-modal-presenter", children: [_jsx("div", { className: "jetpack-ai-logo-generator-modal-presenter__content", children: logoContent }), !logoAccepted && (_jsx("div", { className: "jetpack-ai-logo-generator-modal-presenter__rectangle" }))] }), saveToLibraryError && (_jsx("div", { className: "jetpack-ai-logo-generator__prompt-error", children: __('Error saving the logo to your library. Please try again.', 'jetpack-ai-client') })), logoUpdateError && (_jsx("div", { className: "jetpack-ai-logo-generator__prompt-error", children: __('Error applying the logo to your site. Please try again.', 'jetpack-ai-client') }))] }));
100
+ };
@@ -0,0 +1,5 @@
1
+ /// <reference types="react" resolution-mode="require"/>
2
+ import './prompt.scss';
3
+ export declare const Prompt: React.FC<{
4
+ initialPrompt?: string;
5
+ }>;
@@ -0,0 +1,96 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * External dependencies
4
+ */
5
+ import { useAnalytics } from '@automattic/jetpack-shared-extension-utils';
6
+ import { Button, Tooltip } from '@wordpress/components';
7
+ import { __, sprintf } from '@wordpress/i18n';
8
+ import { Icon, info } from '@wordpress/icons';
9
+ import debugFactory from 'debug';
10
+ import { useCallback, useEffect, useState, useRef } from 'react';
11
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import AiIcon from '../assets/icons/ai.js';
15
+ import { EVENT_GENERATE, MINIMUM_PROMPT_LENGTH, EVENT_UPGRADE, EVENT_PLACEMENT_INPUT_FOOTER, } from '../constants.js';
16
+ import { useCheckout } from '../hooks/use-checkout.js';
17
+ import useLogoGenerator from '../hooks/use-logo-generator.js';
18
+ import useRequestErrors from '../hooks/use-request-errors.js';
19
+ import { UpgradeNudge } from './upgrade-nudge.js';
20
+ import './prompt.scss';
21
+ const debug = debugFactory('jetpack-ai-calypso:prompt-box');
22
+ export const Prompt = ({ initialPrompt = '' }) => {
23
+ const { tracks } = useAnalytics();
24
+ const { recordEvent: recordTracksEvent } = tracks;
25
+ const [prompt, setPrompt] = useState(initialPrompt);
26
+ const [requestsRemaining, setRequestsRemaining] = useState(0);
27
+ const { enhancePromptFetchError, logoFetchError } = useRequestErrors();
28
+ const { nextTierCheckoutURL: checkoutUrl, hasNextTier } = useCheckout();
29
+ const hasPrompt = prompt?.length >= MINIMUM_PROMPT_LENGTH;
30
+ const { generateLogo, enhancePrompt, setIsEnhancingPrompt, isBusy, isEnhancingPrompt, site, getAiAssistantFeature, requireUpgrade, context, } = useLogoGenerator();
31
+ const enhancingLabel = __('Enhancing…', 'jetpack-ai-client');
32
+ const enhanceLabel = __('Enhance prompt', 'jetpack-ai-client');
33
+ const enhanceButtonLabel = isEnhancingPrompt ? enhancingLabel : enhanceLabel;
34
+ const inputRef = useRef(null);
35
+ const onEnhance = useCallback(async () => {
36
+ debug('Enhancing prompt', prompt);
37
+ setIsEnhancingPrompt(true);
38
+ recordTracksEvent(EVENT_GENERATE, { context, tool: 'enhance-prompt' });
39
+ try {
40
+ const enhancedPrompt = await enhancePrompt({ prompt });
41
+ setPrompt(enhancedPrompt);
42
+ setIsEnhancingPrompt(false);
43
+ }
44
+ catch (error) {
45
+ debug('Error enhancing prompt', error);
46
+ setIsEnhancingPrompt(false);
47
+ }
48
+ }, [context, enhancePrompt, prompt, setIsEnhancingPrompt]);
49
+ const featureData = getAiAssistantFeature(String(site?.id || ''));
50
+ const currentLimit = featureData?.currentTier?.value || 0;
51
+ const currentUsage = featureData?.usagePeriod?.requestsCount || 0;
52
+ const isUnlimited = currentLimit === 1;
53
+ useEffect(() => {
54
+ if (currentLimit - currentUsage <= 0) {
55
+ setRequestsRemaining(0);
56
+ }
57
+ else {
58
+ setRequestsRemaining(currentLimit - currentUsage);
59
+ }
60
+ }, [currentLimit, currentUsage]);
61
+ useEffect(() => {
62
+ // Update prompt text node after enhancement
63
+ if (inputRef.current && inputRef.current.textContent !== prompt) {
64
+ inputRef.current.textContent = prompt;
65
+ }
66
+ }, [prompt]);
67
+ const onGenerate = useCallback(async () => {
68
+ recordTracksEvent(EVENT_GENERATE, { context, tool: 'image' });
69
+ generateLogo({ prompt });
70
+ }, [context, generateLogo, prompt]);
71
+ const onPromptInput = (event) => {
72
+ setPrompt(event.target.textContent || '');
73
+ };
74
+ const onPromptPaste = (event) => {
75
+ event.preventDefault();
76
+ // Paste plain text only
77
+ const text = event.clipboardData.getData('text/plain');
78
+ const selection = window.getSelection();
79
+ if (!selection || !selection.rangeCount) {
80
+ return;
81
+ }
82
+ selection.deleteFromDocument();
83
+ const range = selection.getRangeAt(0);
84
+ range.insertNode(document.createTextNode(text));
85
+ selection.collapseToEnd();
86
+ setPrompt(inputRef.current?.textContent || '');
87
+ };
88
+ const onUpgradeClick = () => {
89
+ recordTracksEvent(EVENT_UPGRADE, { context, placement: EVENT_PLACEMENT_INPUT_FOOTER });
90
+ };
91
+ return (_jsxs("div", { className: "jetpack-ai-logo-generator__prompt", children: [_jsxs("div", { className: "jetpack-ai-logo-generator__prompt-header", children: [_jsx("div", { className: "jetpack-ai-logo-generator__prompt-label", children: __('Describe your site:', 'jetpack-ai-client') }), _jsx("div", { className: "jetpack-ai-logo-generator__prompt-actions", children: _jsxs(Button, { variant: "link", disabled: isBusy || requireUpgrade || !hasPrompt, onClick: onEnhance, children: [_jsx(AiIcon, {}), _jsx("span", { children: enhanceButtonLabel })] }) })] }), _jsxs("div", { className: "jetpack-ai-logo-generator__prompt-query", children: [_jsx("div", { ref: inputRef, contentEditable: !isBusy && !requireUpgrade,
92
+ // The content editable div is expected to be updated by the enhance prompt, so warnings are suppressed
93
+ suppressContentEditableWarning: true, className: "prompt-query__input", onInput: onPromptInput, onPaste: onPromptPaste, "data-placeholder": __('Describe your site or simply ask for a logo specifying some details about it', 'jetpack-ai-client') }), _jsx(Button, { variant: "primary", className: "jetpack-ai-logo-generator__prompt-submit", onClick: onGenerate, disabled: isBusy || requireUpgrade || !hasPrompt, children: __('Generate', 'jetpack-ai-client') })] }), _jsxs("div", { className: "jetpack-ai-logo-generator__prompt-footer", children: [!isUnlimited && !requireUpgrade && (_jsxs("div", { className: "jetpack-ai-logo-generator__prompt-requests", children: [_jsx("div", { children: sprintf(
94
+ // translators: %u is the number of requests
95
+ __('%u requests remaining.', 'jetpack-ai-client'), requestsRemaining) }), hasNextTier && (_jsxs(_Fragment, { children: ["\u00A0", _jsx(Button, { variant: "link", href: checkoutUrl, target: "_blank", onClick: onUpgradeClick, children: __('Upgrade', 'jetpack-ai-client') })] })), "\u00A0", _jsx(Tooltip, { text: __('Logo generation costs 10 requests; prompt enhancement costs 1 request each', 'jetpack-ai-client'), placement: "bottom", children: _jsx(Icon, { className: "prompt-footer__icon", icon: info }) })] })), !isUnlimited && requireUpgrade && _jsx(UpgradeNudge, {}), enhancePromptFetchError && (_jsx("div", { className: "jetpack-ai-logo-generator__prompt-error", children: __('Error enhancing prompt. Please try again.', 'jetpack-ai-client') })), logoFetchError && (_jsx("div", { className: "jetpack-ai-logo-generator__prompt-error", children: __('Error generating logo. Please try again.', 'jetpack-ai-client') }))] })] }));
96
+ };
@@ -0,0 +1,2 @@
1
+ import './upgrade-nudge.scss';
2
+ export declare const UpgradeNudge: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * External dependencies
4
+ */
5
+ import { useAnalytics } from '@automattic/jetpack-shared-extension-utils';
6
+ import { Button } from '@wordpress/components';
7
+ import { createInterpolateElement } from '@wordpress/element';
8
+ import { __ } from '@wordpress/i18n';
9
+ import { Icon, warning } from '@wordpress/icons';
10
+ /**
11
+ * Internal dependencies
12
+ */
13
+ import { EVENT_PLACEMENT_UPGRADE_PROMPT, EVENT_UPGRADE } from '../constants.js';
14
+ import { useCheckout } from '../hooks/use-checkout.js';
15
+ import useLogoGenerator from '../hooks/use-logo-generator.js';
16
+ import './upgrade-nudge.scss';
17
+ export const UpgradeNudge = () => {
18
+ const { tracks } = useAnalytics();
19
+ const { recordEvent: recordTracksEvent } = tracks;
20
+ const buttonText = __('Upgrade', 'jetpack-ai-client');
21
+ const upgradeMessage = createInterpolateElement(__('Not enough requests left to generate a logo. <strong>Upgrade now to increase it.</strong>', 'jetpack-ai-client'), {
22
+ strong: _jsx("strong", {}),
23
+ });
24
+ const { nextTierCheckoutURL: checkoutUrl } = useCheckout();
25
+ const { context } = useLogoGenerator();
26
+ const handleUpgradeClick = () => {
27
+ recordTracksEvent(EVENT_UPGRADE, { context, placement: EVENT_PLACEMENT_UPGRADE_PROMPT });
28
+ };
29
+ return (_jsx("div", { className: "jetpack-upgrade-plan-banner", children: _jsxs("div", { className: "jetpack-upgrade-plan-banner__wrapper", children: [_jsxs("div", { children: [_jsx(Icon, { className: "jetpack-upgrade-plan-banner__icon", icon: warning }), _jsx("span", { className: "jetpack-upgrade-plan-banner__banner-description", children: upgradeMessage })] }), _jsx(Button, { href: checkoutUrl, target: "_blank", className: "is-primary", onClick: handleUpgradeClick, children: buttonText })] }) }));
30
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Types
3
+ */
4
+ import type React from 'react';
5
+ export declare const UpgradeScreen: React.FC<{
6
+ onCancel: () => void;
7
+ upgradeURL: string;
8
+ reason: 'feature' | 'requests';
9
+ }>;
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * External dependencies
4
+ */
5
+ import { useAnalytics } from '@automattic/jetpack-shared-extension-utils';
6
+ import { Button } from '@wordpress/components';
7
+ import { __ } from '@wordpress/i18n';
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import { EVENT_PLACEMENT_FREE_USER_SCREEN, EVENT_UPGRADE } from '../constants.js';
12
+ import useLogoGenerator from '../hooks/use-logo-generator.js';
13
+ export const UpgradeScreen = ({ onCancel, upgradeURL, reason }) => {
14
+ const { tracks } = useAnalytics();
15
+ const { recordEvent: recordTracksEvent } = tracks;
16
+ const upgradeMessageFeature = __('Upgrade your Jetpack AI for access to exclusive features, including logo generation. This upgrade will also increase the amount of requests you can use in all AI-powered features.', 'jetpack-ai-client');
17
+ const upgradeMessageRequests = __('Not enough requests left to generate a logo. Upgrade your Jetpack AI to increase the amount of requests you can use in all AI-powered features.', 'jetpack-ai-client');
18
+ const { context } = useLogoGenerator();
19
+ const handleUpgradeClick = () => {
20
+ recordTracksEvent(EVENT_UPGRADE, { context, placement: EVENT_PLACEMENT_FREE_USER_SCREEN });
21
+ onCancel();
22
+ };
23
+ return (_jsxs("div", { className: "jetpack-ai-logo-generator-modal__notice-message-wrapper", children: [_jsxs("div", { className: "jetpack-ai-logo-generator-modal__notice-message", children: [_jsx("span", { className: "jetpack-ai-logo-generator-modal__loading-message", children: reason === 'feature' ? upgradeMessageFeature : upgradeMessageRequests }), "\u00A0", _jsx(Button, { variant: "link", href: "https://jetpack.com/ai/", target: "_blank", children: __('Learn more', 'jetpack-ai-client') })] }), _jsxs("div", { className: "jetpack-ai-logo-generator-modal__notice-actions", children: [_jsx(Button, { variant: "tertiary", onClick: onCancel, children: __('Cancel', 'jetpack-ai-client') }), _jsx(Button, { variant: "primary", href: upgradeURL, target: "_blank", onClick: handleUpgradeClick, children: __('Upgrade', 'jetpack-ai-client') })] })] }));
24
+ };
@@ -0,0 +1,9 @@
1
+ import './visit-site-banner.scss';
2
+ /**
3
+ * Types
4
+ */
5
+ import type React from 'react';
6
+ export declare const VisitSiteBanner: React.FC<{
7
+ className?: string;
8
+ onVisitBlankTarget: () => void;
9
+ }>;
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * External dependencies
4
+ */
5
+ import { Button, Icon } from '@wordpress/components';
6
+ import { __ } from '@wordpress/i18n';
7
+ import { external } from '@wordpress/icons';
8
+ import clsx from 'clsx';
9
+ /**
10
+ * Internal dependencies
11
+ */
12
+ import jetpackLogo from '../assets/images/jetpack-logo.svg';
13
+ import './visit-site-banner.scss';
14
+ export const VisitSiteBanner = ({ className = null, onVisitBlankTarget }) => {
15
+ return (_jsxs("div", { className: clsx('jetpack-ai-logo-generator-modal-visit-site-banner', className), children: [_jsx("div", { className: "jetpack-ai-logo-generator-modal-visit-site-banner__jetpack-logo", children: _jsx("img", { src: jetpackLogo, alt: "Jetpack" }) }), _jsxs("div", { className: "jetpack-ai-logo-generator-modal-visit-site-banner__content", children: [_jsx("strong", { children: __('Do you want to know all the amazing things you can do with Jetpack AI?', 'jetpack-ai-client') }), _jsx("span", { children: __('Generate and tweak content, create forms, get feedback and much more.', 'jetpack-ai-client') }), _jsx("div", { children: _jsxs(Button, { variant: "link", href: "https://jetpack.com/redirect/?source=logo_generator_learn_more_about_jetpack_ai", target: "_blank", onClick: onVisitBlankTarget, children: [__('Learn more about Jetpack AI', 'jetpack-ai-client'), _jsx(Icon, { icon: external, size: 20 })] }) })] })] }));
16
+ };
@@ -0,0 +1,16 @@
1
+ export declare const JWT_TOKEN_ID = "jetpack-ai-jwt";
2
+ export declare const JWT_TOKEN_EXPIRATION_TIME: number;
3
+ export declare const EVENT_MODAL_OPEN = "jetpack_ai_logo_generator_modal_open";
4
+ export declare const EVENT_MODAL_CLOSE = "jetpack_ai_logo_generator_modal_close";
5
+ export declare const EVENT_GENERATE = "jetpack_ai_logo_generator_generate";
6
+ export declare const EVENT_SAVE = "jetpack_ai_logo_generator_save";
7
+ export declare const EVENT_USE = "jetpack_ai_logo_generator_use";
8
+ export declare const EVENT_NAVIGATE = "jetpack_ai_logo_generator_navigate";
9
+ export declare const EVENT_FEEDBACK = "jetpack_ai_logo_generator_feedback";
10
+ export declare const EVENT_UPGRADE = "jetpack_ai_upgrade_button";
11
+ export declare const EVENT_PLACEMENT_QUICK_LINKS = "quick_links";
12
+ export declare const EVENT_PLACEMENT_INPUT_FOOTER = "input_footer";
13
+ export declare const EVENT_PLACEMENT_FREE_USER_SCREEN = "free_user_screen";
14
+ export declare const EVENT_PLACEMENT_UPGRADE_PROMPT = "upgrade_prompt";
15
+ export declare const MINIMUM_PROMPT_LENGTH = 3;
16
+ export declare const DEFAULT_LOGO_COST = 10;
@@ -0,0 +1,19 @@
1
+ export const JWT_TOKEN_ID = 'jetpack-ai-jwt';
2
+ export const JWT_TOKEN_EXPIRATION_TIME = 2 * 60 * 1000; // 2 minutes
3
+ // Tracks event names
4
+ export const EVENT_MODAL_OPEN = 'jetpack_ai_logo_generator_modal_open';
5
+ export const EVENT_MODAL_CLOSE = 'jetpack_ai_logo_generator_modal_close';
6
+ export const EVENT_GENERATE = 'jetpack_ai_logo_generator_generate';
7
+ export const EVENT_SAVE = 'jetpack_ai_logo_generator_save';
8
+ export const EVENT_USE = 'jetpack_ai_logo_generator_use';
9
+ export const EVENT_NAVIGATE = 'jetpack_ai_logo_generator_navigate';
10
+ export const EVENT_FEEDBACK = 'jetpack_ai_logo_generator_feedback';
11
+ export const EVENT_UPGRADE = 'jetpack_ai_upgrade_button';
12
+ // Event placement constants
13
+ export const EVENT_PLACEMENT_QUICK_LINKS = 'quick_links';
14
+ export const EVENT_PLACEMENT_INPUT_FOOTER = 'input_footer';
15
+ export const EVENT_PLACEMENT_FREE_USER_SCREEN = 'free_user_screen';
16
+ export const EVENT_PLACEMENT_UPGRADE_PROMPT = 'upgrade_prompt';
17
+ // Feature constants
18
+ export const MINIMUM_PROMPT_LENGTH = 3;
19
+ export const DEFAULT_LOGO_COST = 10;
@@ -0,0 +1,4 @@
1
+ export declare const useCheckout: () => {
2
+ nextTierCheckoutURL: string;
3
+ hasNextTier: boolean;
4
+ };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { useSelect } from '@wordpress/data';
5
+ import debugFactory from 'debug';
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import { STORE_NAME } from '../store/index.js';
10
+ const debug = debugFactory('ai-client:logo-generator:use-checkout');
11
+ export const useCheckout = () => {
12
+ const { nextTier, siteDetails } = useSelect(select => {
13
+ const selectors = select(STORE_NAME);
14
+ return {
15
+ nextTier: selectors.getAiAssistantFeature().nextTier,
16
+ siteDetails: selectors.getSiteDetails(),
17
+ };
18
+ }, []);
19
+ const upgradeURL = new URL(`${location.origin}/checkout/${siteDetails?.domain}/${nextTier?.slug}`);
20
+ upgradeURL.searchParams.set('redirect_to', location.href);
21
+ debug('Next tier checkout URL: ', upgradeURL.toString());
22
+ return {
23
+ nextTierCheckoutURL: upgradeURL.toString(),
24
+ hasNextTier: !!nextTier,
25
+ };
26
+ };
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Types
3
+ */
4
+ import type { Logo, SaveLogo } from '../store/types.js';
5
+ declare const useLogoGenerator: () => {
6
+ logos: Logo[];
7
+ selectedLogoIndex: number;
8
+ selectedLogo: Logo;
9
+ setSelectedLogoIndex: any;
10
+ site: {
11
+ id: string;
12
+ name: string;
13
+ description: string;
14
+ };
15
+ generateFirstPrompt: () => Promise<string>;
16
+ saveLogo: SaveLogo;
17
+ applyLogo: () => Promise<void>;
18
+ generateImage: ({ prompt, }: {
19
+ prompt: string;
20
+ }) => Promise<{
21
+ data: Array<{
22
+ url: string;
23
+ }>;
24
+ }>;
25
+ enhancePrompt: ({ prompt }: {
26
+ prompt: string;
27
+ }) => Promise<string>;
28
+ storeLogo: (logo: Logo) => void;
29
+ generateLogo: ({ prompt }: {
30
+ prompt: string;
31
+ }) => Promise<void>;
32
+ setIsEnhancingPrompt: any;
33
+ setIsRequestingImage: any;
34
+ setIsSavingLogoToLibrary: any;
35
+ setIsApplyingLogo: any;
36
+ setContext: any;
37
+ isEnhancingPrompt: boolean;
38
+ isRequestingImage: boolean;
39
+ isSavingLogoToLibrary: boolean;
40
+ isApplyingLogo: boolean;
41
+ isBusy: boolean;
42
+ getAiAssistantFeature: (siteId?: string) => Partial<import("../store/types.js").AiFeatureProps>;
43
+ requireUpgrade: boolean;
44
+ context: string;
45
+ };
46
+ export default useLogoGenerator;