@aglyn/plugins-ai 1.0.0-beta.228 → 1.0.0-beta.230
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 +3 -3
- package/package.json +17 -17
- package/src/lib/activity/ai-activity-actions.js +7 -1
- package/src/lib/activity/ai-activity-actions.js.map +1 -1
- package/src/lib/components/ai-automation-zones.d.ts +38 -0
- package/src/lib/components/ai-automation-zones.js +5 -1
- package/src/lib/components/ai-automation-zones.js.map +1 -1
- package/src/lib/components/ai-brief-dialog.component.d.ts +20 -2
- package/src/lib/components/ai-brief-dialog.component.js +87 -8
- package/src/lib/components/ai-brief-dialog.component.js.map +1 -1
- package/src/lib/components/ai-campaign-create.component.d.ts +54 -0
- package/src/lib/components/ai-campaign-create.component.js +270 -0
- package/src/lib/components/ai-campaign-create.component.js.map +1 -0
- package/src/lib/components/ai-describe-automation.component.d.ts +8 -3
- package/src/lib/components/ai-describe-automation.component.js +15 -6
- package/src/lib/components/ai-describe-automation.component.js.map +1 -1
- package/src/lib/components/ai-describe-button.component.d.ts +20 -8
- package/src/lib/components/ai-describe-button.component.js +19 -36
- package/src/lib/components/ai-describe-button.component.js.map +1 -1
- package/src/lib/components/ai-describe-email.component.d.ts +31 -0
- package/src/lib/components/ai-describe-email.component.js +22 -0
- package/src/lib/components/ai-describe-email.component.js.map +1 -0
- package/src/lib/components/ai-describe-org-automation.component.d.ts +36 -0
- package/src/lib/components/ai-describe-org-automation.component.js +238 -0
- package/src/lib/components/ai-describe-org-automation.component.js.map +1 -0
- package/src/lib/components/ai-experiment-cards.component.d.ts +9 -1
- package/src/lib/components/ai-experiment-cards.component.js +104 -18
- package/src/lib/components/ai-experiment-cards.component.js.map +1 -1
- package/src/lib/components/ai-explain-automation.component.js +1 -5
- package/src/lib/components/ai-explain-automation.component.js.map +1 -1
- package/src/lib/components/ai-funnel-zones.component.d.ts +61 -0
- package/src/lib/components/ai-funnel-zones.component.js +178 -0
- package/src/lib/components/ai-funnel-zones.component.js.map +1 -0
- package/src/lib/components/ai-insight-card.component.d.ts +42 -0
- package/src/lib/components/ai-insight-card.component.js +137 -0
- package/src/lib/components/ai-insight-card.component.js.map +1 -0
- package/src/lib/components/ai-insight-dialog.component.d.ts +6 -0
- package/src/lib/components/ai-insight-dialog.component.js +9 -3
- package/src/lib/components/ai-insight-dialog.component.js.map +1 -1
- package/src/lib/components/ai-job-plan.component.d.ts +7 -2
- package/src/lib/components/ai-job-plan.component.js +35 -5
- package/src/lib/components/ai-job-plan.component.js.map +1 -1
- package/src/lib/components/ai-job-requests.d.ts +17 -1
- package/src/lib/components/ai-job-requests.js +39 -3
- package/src/lib/components/ai-job-requests.js.map +1 -1
- package/src/lib/components/ai-jobs-list-page.component.js +12 -1
- package/src/lib/components/ai-jobs-list-page.component.js.map +1 -1
- package/src/lib/components/ai-logic-zones.d.ts +64 -0
- package/src/lib/components/ai-logic-zones.js +18 -0
- package/src/lib/components/ai-logic-zones.js.map +1 -0
- package/src/lib/components/ai-logic.component.d.ts +77 -0
- package/src/lib/components/ai-logic.component.js +553 -0
- package/src/lib/components/ai-logic.component.js.map +1 -0
- package/src/lib/components/ai-marketing-insight.component.d.ts +30 -0
- package/src/lib/components/ai-marketing-insight.component.js +80 -0
- package/src/lib/components/ai-marketing-insight.component.js.map +1 -0
- package/src/lib/components/ai-media-create.component.d.ts +55 -0
- package/src/lib/components/ai-media-create.component.js +433 -0
- package/src/lib/components/ai-media-create.component.js.map +1 -0
- package/src/lib/components/ai-overlay-cards.component.d.ts +83 -0
- package/src/lib/components/ai-overlay-cards.component.js +505 -0
- package/src/lib/components/ai-overlay-cards.component.js.map +1 -0
- package/src/lib/components/ai-product-zones.d.ts +5 -0
- package/src/lib/components/ai-product-zones.js +1 -1
- package/src/lib/components/ai-product-zones.js.map +1 -1
- package/src/lib/components/ai-products-create-button.component.d.ts +42 -0
- package/src/lib/components/ai-products-create-button.component.js +67 -0
- package/src/lib/components/ai-products-create-button.component.js.map +1 -0
- package/src/lib/components/ai-products-hub-card.component.js +100 -81
- package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
- package/src/lib/components/ai-revise-automation.component.d.ts +16 -0
- package/src/lib/components/ai-revise-automation.component.js +207 -0
- package/src/lib/components/ai-revise-automation.component.js.map +1 -0
- package/src/lib/components/ai-site-build-page.component.d.ts +1 -1
- package/src/lib/components/ai-site-build-page.component.js +177 -20
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/ai-site-start-card.component.d.ts +10 -1
- package/src/lib/components/ai-site-start-card.component.js +7 -4
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-upsell-dialog.component.d.ts +53 -0
- package/src/lib/components/ai-upsell-dialog.component.js +177 -0
- package/src/lib/components/ai-upsell-dialog.component.js.map +1 -0
- package/src/lib/components/assist-build-card.component.d.ts +42 -0
- package/src/lib/components/assist-build-card.component.js +183 -0
- package/src/lib/components/assist-build-card.component.js.map +1 -0
- package/src/lib/components/assist-edit-canvas.d.ts +2 -0
- package/src/lib/components/assist-edit-canvas.js +56 -1
- package/src/lib/components/assist-edit-canvas.js.map +1 -1
- package/src/lib/components/assist-jobs-drawer.component.d.ts +11 -0
- package/src/lib/components/assist-jobs-drawer.component.js +85 -4
- package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
- package/src/lib/components/assist-panel.component.js +51 -2
- package/src/lib/components/assist-panel.component.js.map +1 -1
- package/src/lib/components/use-ai-job-run.d.ts +3 -14
- package/src/lib/components/use-ai-job-run.js +0 -50
- package/src/lib/components/use-ai-job-run.js.map +1 -1
- package/src/lib/jobs/ai-build-capabilities.d.ts +58 -0
- package/src/lib/jobs/ai-build-capabilities.js +256 -0
- package/src/lib/jobs/ai-build-capabilities.js.map +1 -0
- package/src/lib/jobs/ai-build-unit-outcome.d.ts +52 -0
- package/src/lib/jobs/ai-build-unit-outcome.js +138 -0
- package/src/lib/jobs/ai-build-unit-outcome.js.map +1 -0
- package/src/lib/jobs/ai-job-build-step.d.ts +144 -0
- package/src/lib/jobs/ai-job-build-step.js +657 -0
- package/src/lib/jobs/ai-job-build-step.js.map +1 -0
- package/src/lib/jobs/ai-job-draft-ids.js +9 -1
- package/src/lib/jobs/ai-job-draft-ids.js.map +1 -1
- package/src/lib/jobs/ai-job-drafts.d.ts +14 -4
- package/src/lib/jobs/ai-job-drafts.js +25 -4
- package/src/lib/jobs/ai-job-drafts.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-site-pages.d.ts +70 -0
- package/src/lib/jobs/ai-job-layout-site-pages.js +216 -0
- package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -0
- package/src/lib/jobs/ai-job-layout-step.d.ts +2 -2
- package/src/lib/jobs/ai-job-layout-step.js +19 -1
- package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
- package/src/lib/jobs/ai-job-logic-step.d.ts +107 -0
- package/src/lib/jobs/ai-job-logic-step.js +395 -0
- package/src/lib/jobs/ai-job-logic-step.js.map +1 -0
- package/src/lib/jobs/ai-job-overlay-copy.d.ts +70 -0
- package/src/lib/jobs/ai-job-overlay-copy.js +178 -0
- package/src/lib/jobs/ai-job-overlay-copy.js.map +1 -0
- package/src/lib/jobs/ai-job-page-step.js +6 -6
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +26 -1
- package/src/lib/jobs/ai-job-plan-step.js +79 -11
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.d.ts +15 -1
- package/src/lib/jobs/ai-job-site-step.js +207 -58
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-job-text-step.d.ts +22 -1
- package/src/lib/jobs/ai-job-text-step.js +12 -0
- package/src/lib/jobs/ai-job-text-step.js.map +1 -1
- package/src/lib/jobs/ai-job-workflow-step.d.ts +54 -4
- package/src/lib/jobs/ai-job-workflow-step.js +318 -13
- package/src/lib/jobs/ai-job-workflow-step.js.map +1 -1
- package/src/lib/jobs/ai-jobs.d.ts +90 -2
- package/src/lib/jobs/ai-jobs.js +495 -61
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-logic-records.d.ts +40 -0
- package/src/lib/jobs/ai-logic-records.js +55 -0
- package/src/lib/jobs/ai-logic-records.js.map +1 -0
- package/src/lib/jobs/ai-site-publish.d.ts +7 -0
- package/src/lib/jobs/ai-site-publish.js +9 -0
- package/src/lib/jobs/ai-site-publish.js.map +1 -1
- package/src/lib/jobs/ai-workflow-records.d.ts +4 -0
- package/src/lib/jobs/ai-workflow-records.js +40 -1
- package/src/lib/jobs/ai-workflow-records.js.map +1 -1
- package/src/lib/model/ai-automation-draft.d.ts +18 -0
- package/src/lib/model/ai-automation-draft.js +86 -0
- package/src/lib/model/ai-automation-draft.js.map +1 -1
- package/src/lib/model/ai-build-job.d.ts +201 -0
- package/src/lib/model/ai-build-job.js +471 -0
- package/src/lib/model/ai-build-job.js.map +1 -0
- package/src/lib/model/ai-build-plan.d.ts +61 -0
- package/src/lib/model/ai-build-plan.js +154 -9
- package/src/lib/model/ai-build-plan.js.map +1 -1
- package/src/lib/model/ai-build-progress.d.ts +56 -0
- package/src/lib/model/ai-build-progress.js +128 -0
- package/src/lib/model/ai-build-progress.js.map +1 -0
- package/src/lib/model/ai-insight.d.ts +20 -10
- package/src/lib/model/ai-insight.js +72 -9
- package/src/lib/model/ai-insight.js.map +1 -1
- package/src/lib/model/ai-job-activity.js +3 -1
- package/src/lib/model/ai-job-activity.js.map +1 -1
- package/src/lib/model/ai-job-failure-copy.d.ts +20 -1
- package/src/lib/model/ai-job-failure-copy.js +28 -1
- package/src/lib/model/ai-job-failure-copy.js.map +1 -1
- package/src/lib/model/ai-job-notice.d.ts +3 -0
- package/src/lib/model/ai-job-notice.js +11 -2
- package/src/lib/model/ai-job-notice.js.map +1 -1
- package/src/lib/model/ai-jobs.types.d.ts +87 -2
- package/src/lib/model/ai-jobs.types.js +3 -1
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-logic-job.d.ts +108 -0
- package/src/lib/model/ai-logic-job.js +327 -0
- package/src/lib/model/ai-logic-job.js.map +1 -0
- package/src/lib/model/ai-media-credits.d.ts +52 -0
- package/src/lib/model/ai-media-credits.js +61 -0
- package/src/lib/model/ai-media-credits.js.map +1 -0
- package/src/lib/model/ai-overlay-copy.d.ts +114 -0
- package/src/lib/model/ai-overlay-copy.js +175 -0
- package/src/lib/model/ai-overlay-copy.js.map +1 -0
- package/src/lib/model/ai-site-build-progress.d.ts +28 -3
- package/src/lib/model/ai-site-build-progress.js +231 -17
- package/src/lib/model/ai-site-build-progress.js.map +1 -1
- package/src/lib/model/ai-site-start-seo.d.ts +16 -0
- package/src/lib/model/ai-site-start-seo.js +54 -4
- package/src/lib/model/ai-site-start-seo.js.map +1 -1
- package/src/lib/model/ai-site-start.d.ts +14 -0
- package/src/lib/model/ai-site-start.js +43 -0
- package/src/lib/model/ai-site-start.js.map +1 -1
- package/src/lib/model/ai-svg.d.ts +69 -0
- package/src/lib/model/ai-svg.js +265 -0
- package/src/lib/model/ai-svg.js.map +1 -0
- package/src/lib/model/ai-usage-by-user.d.ts +3 -2
- package/src/lib/model/ai-usage-by-user.js.map +1 -1
- package/src/lib/model/ai-workflow-job.d.ts +92 -4
- package/src/lib/model/ai-workflow-job.js +124 -7
- package/src/lib/model/ai-workflow-job.js.map +1 -1
- package/src/lib/model/assist-build.d.ts +58 -0
- package/src/lib/model/assist-build.js +52 -0
- package/src/lib/model/assist-build.js.map +1 -0
- package/src/lib/model/assist-edit.d.ts +48 -3
- package/src/lib/model/assist-edit.js +48 -4
- package/src/lib/model/assist-edit.js.map +1 -1
- package/src/lib/plugin-config.js +2 -0
- package/src/lib/plugin-config.js.map +1 -1
- package/src/lib/plugin.js +240 -11
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/providers/catalog.d.ts +81 -4
- package/src/lib/providers/catalog.js +80 -9
- package/src/lib/providers/catalog.js.map +1 -1
- package/src/lib/providers/image-contract.d.ts +116 -0
- package/src/lib/providers/image-contract.js +74 -0
- package/src/lib/providers/image-contract.js.map +1 -0
- package/src/lib/providers/model-choice.js +11 -0
- package/src/lib/providers/model-choice.js.map +1 -1
- package/src/lib/providers/routing.js +18 -0
- package/src/lib/providers/routing.js.map +1 -1
- package/src/lib/providers/vertex-image.d.ts +121 -0
- package/src/lib/providers/vertex-image.js +312 -0
- package/src/lib/providers/vertex-image.js.map +1 -0
- package/src/lib/runtime/ai-doctrine-validators.d.ts +19 -0
- package/src/lib/runtime/ai-doctrine-validators.js +89 -0
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.d.ts +6 -0
- package/src/lib/runtime/ai-doctrine.js +16 -6
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-eval-live.js +4 -0
- package/src/lib/runtime/ai-eval-live.js.map +1 -1
- package/src/lib/runtime/ai-eval.d.ts +15 -1
- package/src/lib/runtime/ai-eval.js +52 -1
- package/src/lib/runtime/ai-eval.js.map +1 -1
- package/src/lib/runtime/experiment-variant-copy.d.ts +34 -0
- package/src/lib/runtime/experiment-variant-copy.js +102 -0
- package/src/lib/runtime/experiment-variant-copy.js.map +1 -0
- package/src/lib/server/ai-experiment-versions.d.ts +51 -0
- package/src/lib/server/ai-experiment-versions.js +270 -0
- package/src/lib/server/ai-experiment-versions.js.map +1 -0
- package/src/lib/server/ai-jobs-resume.js +74 -4
- package/src/lib/server/ai-jobs-resume.js.map +1 -1
- package/src/lib/server/ai-media-image.d.ts +66 -0
- package/src/lib/server/ai-media-image.js +521 -0
- package/src/lib/server/ai-media-image.js.map +1 -0
- package/src/lib/server/ai-media-svg.d.ts +91 -0
- package/src/lib/server/ai-media-svg.js +186 -0
- package/src/lib/server/ai-media-svg.js.map +1 -0
- package/src/lib/server/assist-build.d.ts +54 -0
- package/src/lib/server/assist-build.js +121 -0
- package/src/lib/server/assist-build.js.map +1 -0
- package/src/lib/server/assist-chat.js +108 -12
- package/src/lib/server/assist-chat.js.map +1 -1
- package/src/lib/server/assist-edit.js +213 -3
- package/src/lib/server/assist-edit.js.map +1 -1
- package/src/lib/server/assist-view-context.js +242 -4
- package/src/lib/server/assist-view-context.js.map +1 -1
- package/src/lib/server.js +26 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/tools/ai-logic-tool.d.ts +27 -0
- package/src/lib/tools/ai-logic-tool.js +207 -0
- package/src/lib/tools/ai-logic-tool.js.map +1 -0
- package/src/lib/tools/ai-overlay-tool.d.ts +35 -0
- package/src/lib/tools/ai-overlay-tool.js +107 -0
- package/src/lib/tools/ai-overlay-tool.js.map +1 -0
- package/src/lib/tools/ai-workflow-tool.d.ts +11 -0
- package/src/lib/tools/ai-workflow-tool.js +31 -0
- package/src/lib/tools/ai-workflow-tool.js.map +1 -1
- package/src/lib/usage/assist-job-refund.d.ts +31 -3
- package/src/lib/usage/assist-job-refund.js +46 -10
- package/src/lib/usage/assist-job-refund.js.map +1 -1
- package/src/lib/usage/assist-usage.d.ts +5 -0
- package/src/lib/usage/assist-usage.js +2 -0
- package/src/lib/usage/assist-usage.js.map +1 -1
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ 'use client';
|
|
17
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
18
|
+
import { pluginDocsHelp } from "@aglyn/aglyn/app-utils/docs-help";
|
|
19
|
+
import { mdiCreation } from "@aglyn/shared-data-mdi";
|
|
20
|
+
import { MdiIcon } from "@aglyn/shared-ui-jsx";
|
|
21
|
+
import { useHostOrgId, useUser } from "@aglyn/tenant-feature-instance";
|
|
22
|
+
import { Alert, Box, Button, CircularProgress, Dialog, DialogActions, DialogContent, DialogTitle, Link, Stack, TextField, ToggleButton, ToggleButtonGroup, Typography } from "@mui/material";
|
|
23
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
24
|
+
import { AI_OVERLAY_COPY_TASK, AI_OVERLAY_CURRENT_MAX_CHARS, aiOverlayLimitInputs, aiOverlayTriggersInput, readAiOverlayCopy } from "../model/ai-overlay-copy.js";
|
|
25
|
+
import { AiUpsellButton } from "./ai-upsell-dialog.component.js";
|
|
26
|
+
import { aiJobProblem, useAiJobRun } from "./use-ai-job-run.js";
|
|
27
|
+
/**
|
|
28
|
+
* Overlays by AI in the console (AGL-3603): two widgets in the zones the
|
|
29
|
+
* marketing plugin's overlays list hosts, each starting a `text` job asked for
|
|
30
|
+
* overlay copy (`inputs.task: 'overlay'`).
|
|
31
|
+
*
|
|
32
|
+
* The overlay, its schedule, its targeting and its on-switch are the marketing
|
|
33
|
+
* plugin's, and neither plugin imports the other: the props below restate the
|
|
34
|
+
* halves of the zones' contracts these widgets read.
|
|
35
|
+
*
|
|
36
|
+
* ## Neither widget writes
|
|
37
|
+
*
|
|
38
|
+
* "Write with AI", in the overlay editor, fills the editor's fields unsaved;
|
|
39
|
+
* the editor's Save is the write. "Create with AI", beside New bar and New
|
|
40
|
+
* popup, hands the copy to the list's `createOverlayDraft`, which writes the
|
|
41
|
+
* overlay switched off and opens it in the editor — a visitor sees nothing
|
|
42
|
+
* until a person turns it on.
|
|
43
|
+
*/ const WRITE_FAILED_COPY = 'The copy could not be written. Try again.';
|
|
44
|
+
/** The longest brief a person types here. */ const BRIEF_MAX_CHARS = 1000;
|
|
45
|
+
/** The proposal a finished overlay job carries. */ export function aiOverlayProposalOf(job) {
|
|
46
|
+
if ((job == null ? void 0 : job.status) !== 'done') return null;
|
|
47
|
+
for (const output of job.outputs){
|
|
48
|
+
const proposal = readAiOverlayCopy(output.proposal);
|
|
49
|
+
if (proposal) return proposal;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
/** A checked proposal as the values a zone's callback reads: only the fields it filled. */ export function aiOverlayProposalValues(proposal) {
|
|
54
|
+
const values = {};
|
|
55
|
+
if (proposal.name) values.name = proposal.name;
|
|
56
|
+
if (proposal.kind === 'bar') {
|
|
57
|
+
if (proposal.text) values.text = proposal.text;
|
|
58
|
+
return values;
|
|
59
|
+
}
|
|
60
|
+
if (proposal.headline) values.headline = proposal.headline;
|
|
61
|
+
if (proposal.body) values.body = proposal.body;
|
|
62
|
+
if (proposal.ctaLabel) values.ctaLabel = proposal.ctaLabel;
|
|
63
|
+
if (proposal.trigger) {
|
|
64
|
+
values.trigger = proposal.trigger;
|
|
65
|
+
if (proposal.triggerValue !== null) values.triggerValue = proposal.triggerValue;
|
|
66
|
+
}
|
|
67
|
+
return values;
|
|
68
|
+
}
|
|
69
|
+
/** The editor's copy, as the job's `current` input reads it. */ export function aiOverlayCurrentCopy(kind, copy) {
|
|
70
|
+
const lines = kind === 'bar' ? [
|
|
71
|
+
copy.text
|
|
72
|
+
] : [
|
|
73
|
+
copy.headline,
|
|
74
|
+
copy.body,
|
|
75
|
+
copy.ctaLabel ? `Button: ${copy.ctaLabel}` : ''
|
|
76
|
+
];
|
|
77
|
+
return lines.map((line)=>line.trim()).filter(Boolean).join('\n\n').slice(0, AI_OVERLAY_CURRENT_MAX_CHARS);
|
|
78
|
+
}
|
|
79
|
+
/** The job's inputs for one overlay. */ export function aiOverlayJobInputs(kind, rules, current) {
|
|
80
|
+
const inputs = {
|
|
81
|
+
task: AI_OVERLAY_COPY_TASK,
|
|
82
|
+
overlayKind: kind,
|
|
83
|
+
triggers: aiOverlayTriggersInput(rules.triggers)
|
|
84
|
+
};
|
|
85
|
+
for (const [key, value] of Object.entries(aiOverlayLimitInputs(rules.limits))){
|
|
86
|
+
inputs[key] = String(value);
|
|
87
|
+
}
|
|
88
|
+
if (current) inputs['current'] = current;
|
|
89
|
+
return inputs;
|
|
90
|
+
}
|
|
91
|
+
/** How a proposed trigger reads, in the zone's own words. */ function triggerText(proposal, triggers) {
|
|
92
|
+
var _ref;
|
|
93
|
+
if (!proposal.trigger) return null;
|
|
94
|
+
const rule = triggers.find((entry)=>entry.id === proposal.trigger);
|
|
95
|
+
const label = (_ref = rule == null ? void 0 : rule.label) != null ? _ref : proposal.trigger;
|
|
96
|
+
if (proposal.triggerValue === null || !(rule == null ? void 0 : rule.unit)) return label;
|
|
97
|
+
return `${label}: ${proposal.triggerValue}${rule.unit === 'percent' ? '%' : ' seconds'}`;
|
|
98
|
+
}
|
|
99
|
+
/** One proposal, drawn the same way in both widgets. */ export function AiOverlayProposal({ proposal, triggers }) {
|
|
100
|
+
const opens = proposal.kind === 'popup' ? triggerText(proposal, triggers) : null;
|
|
101
|
+
return /*#__PURE__*/ _jsx(Box, {
|
|
102
|
+
sx: {
|
|
103
|
+
border: 1,
|
|
104
|
+
borderColor: 'divider',
|
|
105
|
+
borderRadius: 1,
|
|
106
|
+
p: 1
|
|
107
|
+
},
|
|
108
|
+
"aria-label": "Proposed copy",
|
|
109
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
110
|
+
spacing: 0.5,
|
|
111
|
+
children: [
|
|
112
|
+
proposal.name ? /*#__PURE__*/ _jsx(Typography, {
|
|
113
|
+
variant: "caption",
|
|
114
|
+
color: "text.secondary",
|
|
115
|
+
children: proposal.name
|
|
116
|
+
}) : null,
|
|
117
|
+
proposal.kind === 'bar' ? /*#__PURE__*/ _jsx(Typography, {
|
|
118
|
+
variant: "body2",
|
|
119
|
+
children: proposal.text
|
|
120
|
+
}) : /*#__PURE__*/ _jsxs(_Fragment, {
|
|
121
|
+
children: [
|
|
122
|
+
proposal.headline ? /*#__PURE__*/ _jsx(Typography, {
|
|
123
|
+
variant: "subtitle2",
|
|
124
|
+
children: proposal.headline
|
|
125
|
+
}) : null,
|
|
126
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
127
|
+
variant: "body2",
|
|
128
|
+
sx: {
|
|
129
|
+
whiteSpace: 'pre-line',
|
|
130
|
+
wordBreak: 'break-word'
|
|
131
|
+
},
|
|
132
|
+
children: proposal.body
|
|
133
|
+
}),
|
|
134
|
+
proposal.ctaLabel ? /*#__PURE__*/ _jsx(Typography, {
|
|
135
|
+
variant: "body2",
|
|
136
|
+
children: `Button: ${proposal.ctaLabel}`
|
|
137
|
+
}) : null,
|
|
138
|
+
opens ? /*#__PURE__*/ _jsx(Typography, {
|
|
139
|
+
variant: "body2",
|
|
140
|
+
color: "text.secondary",
|
|
141
|
+
children: `Opens: ${opens}`
|
|
142
|
+
}) : null
|
|
143
|
+
]
|
|
144
|
+
}),
|
|
145
|
+
proposal.rationale ? /*#__PURE__*/ _jsx(Typography, {
|
|
146
|
+
variant: "caption",
|
|
147
|
+
color: "text.secondary",
|
|
148
|
+
children: proposal.rationale
|
|
149
|
+
}) : null
|
|
150
|
+
]
|
|
151
|
+
})
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
AiOverlayProposal.displayName = 'AiOverlayProposal';
|
|
155
|
+
const overlayHelp = (anchor, excerpt)=>pluginDocsHelp('aiMarketing', {
|
|
156
|
+
anchor,
|
|
157
|
+
excerpt
|
|
158
|
+
});
|
|
159
|
+
/**
|
|
160
|
+
* "Write with AI", among the overlay editor's fields. It proposes the copy and,
|
|
161
|
+
* for a popup, when it opens; it never proposes the link, the schedule, the
|
|
162
|
+
* pages or the on-switch.
|
|
163
|
+
*/ export function AiOverlayEditorCard(props) {
|
|
164
|
+
var _useHostOrgId, _aiJobProblem;
|
|
165
|
+
var _run_job, _run_job1, _run_job2, _run_job3;
|
|
166
|
+
const { hostId, kind, copy, proposeValues, limits, triggers } = props;
|
|
167
|
+
const orgId = (_useHostOrgId = useHostOrgId(hostId)) != null ? _useHostOrgId : undefined;
|
|
168
|
+
const { data: user } = useUser();
|
|
169
|
+
const run = useAiJobRun(user, WRITE_FAILED_COPY);
|
|
170
|
+
const [brief, setBrief] = useState('');
|
|
171
|
+
const [applied, setApplied] = useState(null);
|
|
172
|
+
const proposal = useMemo(()=>aiOverlayProposalOf(run.job), [
|
|
173
|
+
run.job
|
|
174
|
+
]);
|
|
175
|
+
const problem = (_aiJobProblem = aiJobProblem(run.job, WRITE_FAILED_COPY)) != null ? _aiJobProblem : ((_run_job = run.job) == null ? void 0 : _run_job.status) === 'done' && !proposal ? WRITE_FAILED_COPY : null;
|
|
176
|
+
const busy = run.starting || run.running;
|
|
177
|
+
const current = aiOverlayCurrentCopy(kind, copy);
|
|
178
|
+
const noun = kind === 'bar' ? 'bar' : 'popup';
|
|
179
|
+
const help = overlayHelp('#write-overlay-copy', 'Writes the copy for this overlay from a brief, and for a popup when it opens. It fills the fields above unsaved; nothing is saved until you save the overlay.');
|
|
180
|
+
const write = ()=>{
|
|
181
|
+
if (!orgId || !(brief.trim() || current)) return;
|
|
182
|
+
setApplied(null);
|
|
183
|
+
void run.start({
|
|
184
|
+
orgId,
|
|
185
|
+
hostId,
|
|
186
|
+
kind: 'text',
|
|
187
|
+
brief: brief.trim() || `Improve the copy of this ${noun}.`,
|
|
188
|
+
inputs: aiOverlayJobInputs(kind, {
|
|
189
|
+
limits,
|
|
190
|
+
triggers
|
|
191
|
+
}, current)
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
const apply = ()=>{
|
|
195
|
+
if (!proposal || !run.job) return;
|
|
196
|
+
proposeValues(aiOverlayProposalValues(proposal), run.job.id);
|
|
197
|
+
setApplied(run.job.id);
|
|
198
|
+
};
|
|
199
|
+
return /*#__PURE__*/ _jsx(Box, {
|
|
200
|
+
sx: {
|
|
201
|
+
border: 1,
|
|
202
|
+
borderColor: 'divider',
|
|
203
|
+
borderRadius: 1,
|
|
204
|
+
p: 1.5
|
|
205
|
+
},
|
|
206
|
+
"aria-label": "Write with AI",
|
|
207
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
208
|
+
spacing: 1,
|
|
209
|
+
children: [
|
|
210
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
211
|
+
direction: "row",
|
|
212
|
+
spacing: 1,
|
|
213
|
+
sx: {
|
|
214
|
+
alignItems: 'baseline'
|
|
215
|
+
},
|
|
216
|
+
children: [
|
|
217
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
218
|
+
variant: "subtitle2",
|
|
219
|
+
sx: {
|
|
220
|
+
flexGrow: 1
|
|
221
|
+
},
|
|
222
|
+
children: 'Write with AI'
|
|
223
|
+
}),
|
|
224
|
+
/*#__PURE__*/ _jsx(Link, {
|
|
225
|
+
href: help.href,
|
|
226
|
+
target: "_blank",
|
|
227
|
+
rel: "noopener",
|
|
228
|
+
variant: "caption",
|
|
229
|
+
title: help.excerpt,
|
|
230
|
+
children: 'How it works'
|
|
231
|
+
})
|
|
232
|
+
]
|
|
233
|
+
}),
|
|
234
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
235
|
+
size: "small",
|
|
236
|
+
multiline: true,
|
|
237
|
+
minRows: 2,
|
|
238
|
+
label: `What is this ${noun} for?`,
|
|
239
|
+
placeholder: kind === 'bar' ? 'Free delivery on orders over [amount] this weekend' : 'Invite first-time visitors to book a free consultation',
|
|
240
|
+
helperText: current ? 'The copy above is sent with this, so it can be improved rather than replaced.' : 'Name the offer or the news, and who it is for.',
|
|
241
|
+
value: brief,
|
|
242
|
+
onChange: (event)=>setBrief(event.target.value.slice(0, BRIEF_MAX_CHARS)),
|
|
243
|
+
disabled: busy
|
|
244
|
+
}),
|
|
245
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
246
|
+
direction: "row",
|
|
247
|
+
spacing: 1,
|
|
248
|
+
sx: {
|
|
249
|
+
alignItems: 'center'
|
|
250
|
+
},
|
|
251
|
+
children: [
|
|
252
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
253
|
+
size: "small",
|
|
254
|
+
variant: "outlined",
|
|
255
|
+
startIcon: /*#__PURE__*/ _jsx(MdiIcon, {
|
|
256
|
+
path: mdiCreation.path
|
|
257
|
+
}),
|
|
258
|
+
disabled: busy || !orgId || !(brief.trim() || current),
|
|
259
|
+
onClick: write,
|
|
260
|
+
children: run.job && !busy ? 'Write it again' : 'Write with AI'
|
|
261
|
+
}),
|
|
262
|
+
busy ? /*#__PURE__*/ _jsx(CircularProgress, {
|
|
263
|
+
size: 16,
|
|
264
|
+
"aria-label": "Writing the copy"
|
|
265
|
+
}) : null
|
|
266
|
+
]
|
|
267
|
+
}),
|
|
268
|
+
run.notice ? /*#__PURE__*/ _jsx(Alert, {
|
|
269
|
+
severity: "warning",
|
|
270
|
+
children: run.notice
|
|
271
|
+
}) : null,
|
|
272
|
+
problem ? /*#__PURE__*/ _jsx(Alert, {
|
|
273
|
+
severity: ((_run_job1 = run.job) == null ? void 0 : _run_job1.status) === 'failed' ? 'error' : 'warning',
|
|
274
|
+
children: problem
|
|
275
|
+
}) : null,
|
|
276
|
+
proposal ? /*#__PURE__*/ _jsxs(Stack, {
|
|
277
|
+
spacing: 1,
|
|
278
|
+
children: [
|
|
279
|
+
/*#__PURE__*/ _jsx(AiOverlayProposal, {
|
|
280
|
+
proposal: proposal,
|
|
281
|
+
triggers: triggers
|
|
282
|
+
}),
|
|
283
|
+
/*#__PURE__*/ _jsx(Stack, {
|
|
284
|
+
direction: "row",
|
|
285
|
+
spacing: 1,
|
|
286
|
+
children: /*#__PURE__*/ _jsx(Button, {
|
|
287
|
+
size: "small",
|
|
288
|
+
variant: "contained",
|
|
289
|
+
disabled: applied === ((_run_job2 = run.job) == null ? void 0 : _run_job2.id),
|
|
290
|
+
onClick: apply,
|
|
291
|
+
children: 'Put in the fields'
|
|
292
|
+
})
|
|
293
|
+
}),
|
|
294
|
+
applied === ((_run_job3 = run.job) == null ? void 0 : _run_job3.id) ? /*#__PURE__*/ _jsx(Alert, {
|
|
295
|
+
severity: "success",
|
|
296
|
+
children: 'In the fields above. Review them, add the link, then Save — or Cancel to leave the overlay as it was.'
|
|
297
|
+
}) : null
|
|
298
|
+
]
|
|
299
|
+
}) : null
|
|
300
|
+
]
|
|
301
|
+
})
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
AiOverlayEditorCard.displayName = 'AiOverlayEditorCard';
|
|
305
|
+
/**
|
|
306
|
+
* "Create with AI", beside New bar and New popup and in the list's empty
|
|
307
|
+
* state: a brief becomes a new overlay, written switched off and opened in the
|
|
308
|
+
* editor.
|
|
309
|
+
*/ export function AiCreateOverlayButton(props) {
|
|
310
|
+
var _useHostOrgId, _aiJobProblem;
|
|
311
|
+
var _run_job, _run_job1;
|
|
312
|
+
const { hostId, createOverlayDraft, limits, triggers } = props;
|
|
313
|
+
const orgId = (_useHostOrgId = useHostOrgId(hostId)) != null ? _useHostOrgId : undefined;
|
|
314
|
+
const { data: user } = useUser();
|
|
315
|
+
const run = useAiJobRun(user, WRITE_FAILED_COPY);
|
|
316
|
+
const [open, setOpen] = useState(false);
|
|
317
|
+
const [kind, setKind] = useState('popup');
|
|
318
|
+
const [brief, setBrief] = useState('');
|
|
319
|
+
const [saving, setSaving] = useState(false);
|
|
320
|
+
const [saveError, setSaveError] = useState(null);
|
|
321
|
+
/** The job whose copy was handed to the list, so it is created once. */ const createdRef = useRef(null);
|
|
322
|
+
const proposal = useMemo(()=>aiOverlayProposalOf(run.job), [
|
|
323
|
+
run.job
|
|
324
|
+
]);
|
|
325
|
+
const problem = (_aiJobProblem = aiJobProblem(run.job, WRITE_FAILED_COPY)) != null ? _aiJobProblem : ((_run_job = run.job) == null ? void 0 : _run_job.status) === 'done' && !proposal ? WRITE_FAILED_COPY : null;
|
|
326
|
+
// Once the copy arrives it becomes the overlay, switched off, and the list
|
|
327
|
+
// opens it in the editor; this dialog has nothing more to show.
|
|
328
|
+
useEffect(()=>{
|
|
329
|
+
var _run_job;
|
|
330
|
+
const jobId = (_run_job = run.job) == null ? void 0 : _run_job.id;
|
|
331
|
+
if (!proposal || !jobId || createdRef.current === jobId) return;
|
|
332
|
+
createdRef.current = jobId;
|
|
333
|
+
setSaving(true);
|
|
334
|
+
setSaveError(null);
|
|
335
|
+
void createOverlayDraft(proposal.kind, aiOverlayProposalValues(proposal)).then((result)=>{
|
|
336
|
+
if (result.ok === false) {
|
|
337
|
+
setSaveError(result.error);
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
setOpen(false);
|
|
341
|
+
setBrief('');
|
|
342
|
+
run.reset();
|
|
343
|
+
}).catch(()=>setSaveError('The overlay could not be saved. Try again.')).finally(()=>setSaving(false));
|
|
344
|
+
}, [
|
|
345
|
+
proposal,
|
|
346
|
+
run,
|
|
347
|
+
createOverlayDraft
|
|
348
|
+
]);
|
|
349
|
+
// Drawn from the shell's gates alone (AGL-3601): nothing asks a server until
|
|
350
|
+
// it is used, and a plan without the add-on gets the add-on's dialog.
|
|
351
|
+
if (props.entitled === false) {
|
|
352
|
+
return props.upgrade ? /*#__PURE__*/ _jsx(AiUpsellButton, {
|
|
353
|
+
kind: "overlay",
|
|
354
|
+
upgrade: props.upgrade
|
|
355
|
+
}) : null;
|
|
356
|
+
}
|
|
357
|
+
const busy = run.starting || run.running || saving;
|
|
358
|
+
const help = overlayHelp('#create-an-overlay', 'Writes a new announcement bar or popup from a brief and saves it switched off, so no visitor sees it until you turn it on.');
|
|
359
|
+
const start = ()=>{
|
|
360
|
+
if (!orgId || !brief.trim()) return;
|
|
361
|
+
createdRef.current = null;
|
|
362
|
+
setSaveError(null);
|
|
363
|
+
void run.start({
|
|
364
|
+
orgId,
|
|
365
|
+
hostId,
|
|
366
|
+
kind: 'text',
|
|
367
|
+
brief: brief.trim(),
|
|
368
|
+
inputs: aiOverlayJobInputs(kind, {
|
|
369
|
+
limits,
|
|
370
|
+
triggers
|
|
371
|
+
}, '')
|
|
372
|
+
});
|
|
373
|
+
};
|
|
374
|
+
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
375
|
+
children: [
|
|
376
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
377
|
+
size: "small",
|
|
378
|
+
variant: "outlined",
|
|
379
|
+
startIcon: /*#__PURE__*/ _jsx(MdiIcon, {
|
|
380
|
+
path: mdiCreation.path
|
|
381
|
+
}),
|
|
382
|
+
onClick: ()=>setOpen(true),
|
|
383
|
+
children: 'Create with AI'
|
|
384
|
+
}),
|
|
385
|
+
/*#__PURE__*/ _jsxs(Dialog, {
|
|
386
|
+
open: open,
|
|
387
|
+
onClose: busy ? undefined : ()=>setOpen(false),
|
|
388
|
+
fullWidth: true,
|
|
389
|
+
maxWidth: "sm",
|
|
390
|
+
children: [
|
|
391
|
+
/*#__PURE__*/ _jsx(DialogTitle, {
|
|
392
|
+
children: 'Create an overlay with AI'
|
|
393
|
+
}),
|
|
394
|
+
/*#__PURE__*/ _jsx(DialogContent, {
|
|
395
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
396
|
+
spacing: 2,
|
|
397
|
+
sx: {
|
|
398
|
+
pt: 1
|
|
399
|
+
},
|
|
400
|
+
children: [
|
|
401
|
+
/*#__PURE__*/ _jsxs(ToggleButtonGroup, {
|
|
402
|
+
exclusive: true,
|
|
403
|
+
size: "small",
|
|
404
|
+
value: kind,
|
|
405
|
+
onChange: (_event, next)=>{
|
|
406
|
+
if (next) setKind(next);
|
|
407
|
+
},
|
|
408
|
+
"aria-label": "What to create",
|
|
409
|
+
disabled: busy,
|
|
410
|
+
children: [
|
|
411
|
+
/*#__PURE__*/ _jsx(ToggleButton, {
|
|
412
|
+
value: "popup",
|
|
413
|
+
children: 'Popup'
|
|
414
|
+
}),
|
|
415
|
+
/*#__PURE__*/ _jsx(ToggleButton, {
|
|
416
|
+
value: "bar",
|
|
417
|
+
children: 'Announcement bar'
|
|
418
|
+
})
|
|
419
|
+
]
|
|
420
|
+
}),
|
|
421
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
422
|
+
label: kind === 'bar' ? 'What should the bar announce?' : 'What is the popup for?',
|
|
423
|
+
placeholder: kind === 'bar' ? 'Our spring sale: [discount] off everything until [date]' : 'Ask visitors reading our services page to book a free consultation',
|
|
424
|
+
multiline: true,
|
|
425
|
+
minRows: 3,
|
|
426
|
+
value: brief,
|
|
427
|
+
onChange: (event)=>setBrief(event.target.value.slice(0, BRIEF_MAX_CHARS)),
|
|
428
|
+
disabled: busy,
|
|
429
|
+
autoFocus: true
|
|
430
|
+
}),
|
|
431
|
+
/*#__PURE__*/ _jsxs(Typography, {
|
|
432
|
+
variant: "body2",
|
|
433
|
+
color: "text.secondary",
|
|
434
|
+
children: [
|
|
435
|
+
'The overlay is saved switched off and opened in the editor, where you add its link, ' + 'its pages and its schedule. No visitor sees it until you turn it on.',
|
|
436
|
+
' ',
|
|
437
|
+
/*#__PURE__*/ _jsx(Link, {
|
|
438
|
+
href: help.href,
|
|
439
|
+
target: "_blank",
|
|
440
|
+
rel: "noopener",
|
|
441
|
+
title: help.excerpt,
|
|
442
|
+
children: 'How it works'
|
|
443
|
+
})
|
|
444
|
+
]
|
|
445
|
+
}),
|
|
446
|
+
busy ? /*#__PURE__*/ _jsxs(Stack, {
|
|
447
|
+
direction: "row",
|
|
448
|
+
spacing: 1,
|
|
449
|
+
sx: {
|
|
450
|
+
alignItems: 'center'
|
|
451
|
+
},
|
|
452
|
+
children: [
|
|
453
|
+
/*#__PURE__*/ _jsx(CircularProgress, {
|
|
454
|
+
size: 16,
|
|
455
|
+
"aria-label": "Writing the overlay"
|
|
456
|
+
}),
|
|
457
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
458
|
+
variant: "body2",
|
|
459
|
+
color: "text.secondary",
|
|
460
|
+
children: saving ? 'Saving the overlay.' : 'Writing the copy.'
|
|
461
|
+
})
|
|
462
|
+
]
|
|
463
|
+
}) : null,
|
|
464
|
+
run.notice ? /*#__PURE__*/ _jsx(Alert, {
|
|
465
|
+
severity: "warning",
|
|
466
|
+
children: run.notice
|
|
467
|
+
}) : null,
|
|
468
|
+
problem ? /*#__PURE__*/ _jsx(Alert, {
|
|
469
|
+
severity: ((_run_job1 = run.job) == null ? void 0 : _run_job1.status) === 'failed' ? 'error' : 'warning',
|
|
470
|
+
children: problem
|
|
471
|
+
}) : null,
|
|
472
|
+
saveError ? /*#__PURE__*/ _jsx(Alert, {
|
|
473
|
+
severity: "error",
|
|
474
|
+
children: saveError
|
|
475
|
+
}) : null,
|
|
476
|
+
proposal && saveError ? /*#__PURE__*/ _jsx(AiOverlayProposal, {
|
|
477
|
+
proposal: proposal,
|
|
478
|
+
triggers: triggers
|
|
479
|
+
}) : null
|
|
480
|
+
]
|
|
481
|
+
})
|
|
482
|
+
}),
|
|
483
|
+
/*#__PURE__*/ _jsxs(DialogActions, {
|
|
484
|
+
children: [
|
|
485
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
486
|
+
onClick: ()=>setOpen(false),
|
|
487
|
+
disabled: busy,
|
|
488
|
+
children: 'Cancel'
|
|
489
|
+
}),
|
|
490
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
491
|
+
variant: "contained",
|
|
492
|
+
onClick: start,
|
|
493
|
+
disabled: busy || !orgId || !brief.trim(),
|
|
494
|
+
children: 'Create the overlay'
|
|
495
|
+
})
|
|
496
|
+
]
|
|
497
|
+
})
|
|
498
|
+
]
|
|
499
|
+
})
|
|
500
|
+
]
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
AiCreateOverlayButton.displayName = 'AiCreateOverlayButton';
|
|
504
|
+
|
|
505
|
+
//# sourceMappingURL=ai-overlay-cards.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-overlay-cards.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport type { ConsoleWidgetEntitlementProps } from '@aglyn/aglyn/plugin-manager/feature-plugins'\nimport { pluginDocsHelp } from '@aglyn/aglyn/app-utils/docs-help'\nimport { mdiCreation } from '@aglyn/shared-data-mdi'\nimport { MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { useHostOrgId, useUser } from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Box,\n Button,\n CircularProgress,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Link,\n Stack,\n TextField,\n ToggleButton,\n ToggleButtonGroup,\n Typography,\n} from '@mui/material'\nimport { useEffect, useMemo, useRef, useState } from 'react'\nimport type { AiJobSummary } from '../model/ai-jobs.types'\nimport {\n AI_OVERLAY_COPY_TASK,\n AI_OVERLAY_CURRENT_MAX_CHARS,\n aiOverlayLimitInputs,\n aiOverlayTriggersInput,\n readAiOverlayCopy,\n type AiOverlayCopyField,\n type AiOverlayCopyProposal,\n type AiOverlayKind,\n type AiOverlayTriggerRule,\n} from '../model/ai-overlay-copy'\nimport { AiUpsellButton } from './ai-upsell-dialog.component'\nimport { aiJobProblem, useAiJobRun } from './use-ai-job-run'\n\n/**\n * Overlays by AI in the console (AGL-3603): two widgets in the zones the\n * marketing plugin's overlays list hosts, each starting a `text` job asked for\n * overlay copy (`inputs.task: 'overlay'`).\n *\n * The overlay, its schedule, its targeting and its on-switch are the marketing\n * plugin's, and neither plugin imports the other: the props below restate the\n * halves of the zones' contracts these widgets read.\n *\n * ## Neither widget writes\n *\n * \"Write with AI\", in the overlay editor, fills the editor's fields unsaved;\n * the editor's Save is the write. \"Create with AI\", beside New bar and New\n * popup, hands the copy to the list's `createOverlayDraft`, which writes the\n * overlay switched off and opens it in the editor — a visitor sees nothing\n * until a person turns it on.\n */\n\nconst WRITE_FAILED_COPY = 'The copy could not be written. Try again.'\n\n/** The longest brief a person types here. */\nconst BRIEF_MAX_CHARS = 1_000\n\n/** The zone's rules, as the list hands them over. */\ninterface OverlayRules {\n limits: Readonly<Partial<Record<AiOverlayCopyField, number>>>\n triggers: readonly AiOverlayTriggerRule[]\n}\n\n/** What one proposal sets, as the zones' `proposeValues` and `createOverlayDraft` read it. */\nexport interface AiOverlayProposalValues {\n name?: string\n text?: string\n headline?: string\n body?: string\n ctaLabel?: string\n trigger?: string\n triggerValue?: number\n}\n\n/** The overlay editor's copy, as the `overlayEditor` zone hands it over. */\nexport interface AiOverlayEditorCopy {\n name: string\n text: string\n headline: string\n body: string\n ctaLabel: string\n ctaHref: string\n trigger: string\n triggerValue: number | null\n}\n\n/** What the `overlayEditor` zone hands this widget. */\nexport interface AiOverlayEditorCardProps extends OverlayRules {\n hostId: string\n overlayId: string\n kind: AiOverlayKind\n copy: AiOverlayEditorCopy\n proposeValues: (proposal: AiOverlayProposalValues, key: string) => void\n}\n\n/** What the `hostOverlays` zone hands this widget. */\nexport interface AiCreateOverlayButtonProps extends OverlayRules, ConsoleWidgetEntitlementProps {\n hostId: string\n createOverlayDraft: (\n kind: AiOverlayKind,\n proposal: AiOverlayProposalValues,\n ) => Promise<{ ok: true; id: string } | { ok: false; error: string }>\n}\n\n/** The proposal a finished overlay job carries. */\nexport function aiOverlayProposalOf(job: AiJobSummary | null): AiOverlayCopyProposal | null {\n if (job?.status !== 'done') return null\n for (const output of job.outputs) {\n const proposal = readAiOverlayCopy(output.proposal)\n if (proposal) return proposal\n }\n return null\n}\n\n/** A checked proposal as the values a zone's callback reads: only the fields it filled. */\nexport function aiOverlayProposalValues(proposal: AiOverlayCopyProposal): AiOverlayProposalValues {\n const values: AiOverlayProposalValues = {}\n if (proposal.name) values.name = proposal.name\n if (proposal.kind === 'bar') {\n if (proposal.text) values.text = proposal.text\n return values\n }\n if (proposal.headline) values.headline = proposal.headline\n if (proposal.body) values.body = proposal.body\n if (proposal.ctaLabel) values.ctaLabel = proposal.ctaLabel\n if (proposal.trigger) {\n values.trigger = proposal.trigger\n if (proposal.triggerValue !== null) values.triggerValue = proposal.triggerValue\n }\n return values\n}\n\n/** The editor's copy, as the job's `current` input reads it. */\nexport function aiOverlayCurrentCopy(kind: AiOverlayKind, copy: AiOverlayEditorCopy): string {\n const lines =\n kind === 'bar'\n ? [copy.text]\n : [copy.headline, copy.body, copy.ctaLabel ? `Button: ${copy.ctaLabel}` : '']\n return lines\n .map((line) => line.trim())\n .filter(Boolean)\n .join('\\n\\n')\n .slice(0, AI_OVERLAY_CURRENT_MAX_CHARS)\n}\n\n/** The job's inputs for one overlay. */\nexport function aiOverlayJobInputs(\n kind: AiOverlayKind,\n rules: OverlayRules,\n current: string,\n): Record<string, string> {\n const inputs: Record<string, string> = {\n task: AI_OVERLAY_COPY_TASK,\n overlayKind: kind,\n triggers: aiOverlayTriggersInput(rules.triggers),\n }\n for (const [key, value] of Object.entries(aiOverlayLimitInputs(rules.limits))) {\n inputs[key] = String(value)\n }\n if (current) inputs['current'] = current\n return inputs\n}\n\n/** How a proposed trigger reads, in the zone's own words. */\nfunction triggerText(\n proposal: AiOverlayCopyProposal,\n triggers: readonly AiOverlayTriggerRule[],\n): string | null {\n if (!proposal.trigger) return null\n const rule = triggers.find((entry) => entry.id === proposal.trigger)\n const label = rule?.label ?? proposal.trigger\n if (proposal.triggerValue === null || !rule?.unit) return label\n return `${label}: ${proposal.triggerValue}${rule.unit === 'percent' ? '%' : ' seconds'}`\n}\n\n/** One proposal, drawn the same way in both widgets. */\nexport function AiOverlayProposal({\n proposal,\n triggers,\n}: {\n proposal: AiOverlayCopyProposal\n triggers: readonly AiOverlayTriggerRule[]\n}) {\n const opens = proposal.kind === 'popup' ? triggerText(proposal, triggers) : null\n return (\n <Box\n sx={{ border: 1, borderColor: 'divider', borderRadius: 1, p: 1 }}\n aria-label=\"Proposed copy\"\n >\n <Stack spacing={0.5}>\n {proposal.name ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {proposal.name}\n </Typography>\n ) : null}\n {proposal.kind === 'bar' ? (\n <Typography variant=\"body2\">{proposal.text}</Typography>\n ) : (\n <>\n {proposal.headline ? (\n <Typography variant=\"subtitle2\">{proposal.headline}</Typography>\n ) : null}\n <Typography variant=\"body2\" sx={{ whiteSpace: 'pre-line', wordBreak: 'break-word' }}>\n {proposal.body}\n </Typography>\n {proposal.ctaLabel ? (\n <Typography variant=\"body2\">{`Button: ${proposal.ctaLabel}`}</Typography>\n ) : null}\n {opens ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`Opens: ${opens}`}\n </Typography>\n ) : null}\n </>\n )}\n {proposal.rationale ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {proposal.rationale}\n </Typography>\n ) : null}\n </Stack>\n </Box>\n )\n}\nAiOverlayProposal.displayName = 'AiOverlayProposal'\n\nconst overlayHelp = (anchor: '#write-overlay-copy' | '#create-an-overlay', excerpt: string) =>\n pluginDocsHelp('aiMarketing', { anchor, excerpt })\n\n/**\n * \"Write with AI\", among the overlay editor's fields. It proposes the copy and,\n * for a popup, when it opens; it never proposes the link, the schedule, the\n * pages or the on-switch.\n */\nexport function AiOverlayEditorCard(props: AiOverlayEditorCardProps) {\n const { hostId, kind, copy, proposeValues, limits, triggers } = props\n const orgId = useHostOrgId(hostId) ?? undefined\n const { data: user } = useUser()\n const run = useAiJobRun(user, WRITE_FAILED_COPY)\n const [brief, setBrief] = useState('')\n const [applied, setApplied] = useState<string | null>(null)\n const proposal = useMemo(() => aiOverlayProposalOf(run.job), [run.job])\n const problem =\n aiJobProblem(run.job, WRITE_FAILED_COPY) ??\n (run.job?.status === 'done' && !proposal ? WRITE_FAILED_COPY : null)\n\n\n const busy = run.starting || run.running\n const current = aiOverlayCurrentCopy(kind, copy)\n const noun = kind === 'bar' ? 'bar' : 'popup'\n const help = overlayHelp('#write-overlay-copy', 'Writes the copy for this overlay from a brief, and for a popup when it opens. It fills the fields above unsaved; nothing is saved until you save the overlay.')\n const write = () => {\n if (!orgId || !(brief.trim() || current)) return\n setApplied(null)\n void run.start({\n orgId,\n hostId,\n kind: 'text',\n brief: brief.trim() || `Improve the copy of this ${noun}.`,\n inputs: aiOverlayJobInputs(kind, { limits, triggers }, current),\n })\n }\n const apply = () => {\n if (!proposal || !run.job) return\n proposeValues(aiOverlayProposalValues(proposal), run.job.id)\n setApplied(run.job.id)\n }\n\n return (\n <Box\n sx={{ border: 1, borderColor: 'divider', borderRadius: 1, p: 1.5 }}\n aria-label=\"Write with AI\"\n >\n <Stack spacing={1}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'baseline' }}>\n <Typography variant=\"subtitle2\" sx={{ flexGrow: 1 }}>\n {'Write with AI'}\n </Typography>\n <Link href={help.href} target=\"_blank\" rel=\"noopener\" variant=\"caption\" title={help.excerpt}>\n {'How it works'}\n </Link>\n </Stack>\n <TextField\n size=\"small\"\n multiline\n minRows={2}\n label={`What is this ${noun} for?`}\n placeholder={\n kind === 'bar'\n ? 'Free delivery on orders over [amount] this weekend'\n : 'Invite first-time visitors to book a free consultation'\n }\n helperText={\n current\n ? 'The copy above is sent with this, so it can be improved rather than replaced.'\n : 'Name the offer or the news, and who it is for.'\n }\n value={brief}\n onChange={(event) => setBrief(event.target.value.slice(0, BRIEF_MAX_CHARS))}\n disabled={busy}\n />\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Button\n size=\"small\"\n variant=\"outlined\"\n startIcon={<MdiIcon path={mdiCreation.path} />}\n disabled={busy || !orgId || !(brief.trim() || current)}\n onClick={write}\n >\n {run.job && !busy ? 'Write it again' : 'Write with AI'}\n </Button>\n {busy ? <CircularProgress size={16} aria-label=\"Writing the copy\" /> : null}\n </Stack>\n {run.notice ? <Alert severity=\"warning\">{run.notice}</Alert> : null}\n {problem ? (\n <Alert severity={run.job?.status === 'failed' ? 'error' : 'warning'}>{problem}</Alert>\n ) : null}\n {proposal ? (\n <Stack spacing={1}>\n <AiOverlayProposal proposal={proposal} triggers={triggers} />\n <Stack direction=\"row\" spacing={1}>\n <Button\n size=\"small\"\n variant=\"contained\"\n disabled={applied === run.job?.id}\n onClick={apply}\n >\n {'Put in the fields'}\n </Button>\n </Stack>\n {applied === run.job?.id ? (\n <Alert severity=\"success\">\n {'In the fields above. Review them, add the link, then Save — or Cancel to leave the overlay as it was.'}\n </Alert>\n ) : null}\n </Stack>\n ) : null}\n </Stack>\n </Box>\n )\n}\nAiOverlayEditorCard.displayName = 'AiOverlayEditorCard'\n\n/**\n * \"Create with AI\", beside New bar and New popup and in the list's empty\n * state: a brief becomes a new overlay, written switched off and opened in the\n * editor.\n */\nexport function AiCreateOverlayButton(props: AiCreateOverlayButtonProps) {\n const { hostId, createOverlayDraft, limits, triggers } = props\n const orgId = useHostOrgId(hostId) ?? undefined\n const { data: user } = useUser()\n const run = useAiJobRun(user, WRITE_FAILED_COPY)\n const [open, setOpen] = useState(false)\n const [kind, setKind] = useState<AiOverlayKind>('popup')\n const [brief, setBrief] = useState('')\n const [saving, setSaving] = useState(false)\n const [saveError, setSaveError] = useState<string | null>(null)\n /** The job whose copy was handed to the list, so it is created once. */\n const createdRef = useRef<string | null>(null)\n const proposal = useMemo(() => aiOverlayProposalOf(run.job), [run.job])\n const problem =\n aiJobProblem(run.job, WRITE_FAILED_COPY) ??\n (run.job?.status === 'done' && !proposal ? WRITE_FAILED_COPY : null)\n\n // Once the copy arrives it becomes the overlay, switched off, and the list\n // opens it in the editor; this dialog has nothing more to show.\n useEffect(() => {\n const jobId = run.job?.id\n if (!proposal || !jobId || createdRef.current === jobId) return\n createdRef.current = jobId\n setSaving(true)\n setSaveError(null)\n void createOverlayDraft(proposal.kind, aiOverlayProposalValues(proposal))\n .then((result) => {\n if (result.ok === false) {\n setSaveError(result.error)\n return\n }\n setOpen(false)\n setBrief('')\n run.reset()\n })\n .catch(() => setSaveError('The overlay could not be saved. Try again.'))\n .finally(() => setSaving(false))\n }, [proposal, run, createOverlayDraft])\n\n // Drawn from the shell's gates alone (AGL-3601): nothing asks a server until\n // it is used, and a plan without the add-on gets the add-on's dialog.\n if (props.entitled === false) {\n return props.upgrade ? <AiUpsellButton kind=\"overlay\" upgrade={props.upgrade} /> : null\n }\n\n const busy = run.starting || run.running || saving\n const help = overlayHelp('#create-an-overlay', 'Writes a new announcement bar or popup from a brief and saves it switched off, so no visitor sees it until you turn it on.')\n const start = () => {\n if (!orgId || !brief.trim()) return\n createdRef.current = null\n setSaveError(null)\n void run.start({\n orgId,\n hostId,\n kind: 'text',\n brief: brief.trim(),\n inputs: aiOverlayJobInputs(kind, { limits, triggers }, ''),\n })\n }\n\n return (\n <>\n <Button\n size=\"small\"\n variant=\"outlined\"\n startIcon={<MdiIcon path={mdiCreation.path} />}\n onClick={() => setOpen(true)}\n >\n {'Create with AI'}\n </Button>\n <Dialog open={open} onClose={busy ? undefined : () => setOpen(false)} fullWidth maxWidth=\"sm\">\n <DialogTitle>{'Create an overlay with AI'}</DialogTitle>\n <DialogContent>\n <Stack spacing={2} sx={{ pt: 1 }}>\n <ToggleButtonGroup\n exclusive\n size=\"small\"\n value={kind}\n onChange={(_event, next: AiOverlayKind | null) => {\n if (next) setKind(next)\n }}\n aria-label=\"What to create\"\n disabled={busy}\n >\n <ToggleButton value=\"popup\">{'Popup'}</ToggleButton>\n <ToggleButton value=\"bar\">{'Announcement bar'}</ToggleButton>\n </ToggleButtonGroup>\n <TextField\n label={kind === 'bar' ? 'What should the bar announce?' : 'What is the popup for?'}\n placeholder={\n kind === 'bar'\n ? 'Our spring sale: [discount] off everything until [date]'\n : 'Ask visitors reading our services page to book a free consultation'\n }\n multiline\n minRows={3}\n value={brief}\n onChange={(event) => setBrief(event.target.value.slice(0, BRIEF_MAX_CHARS))}\n disabled={busy}\n autoFocus\n />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'The overlay is saved switched off and opened in the editor, where you add its link, ' +\n 'its pages and its schedule. No visitor sees it until you turn it on.'}\n {' '}\n <Link href={help.href} target=\"_blank\" rel=\"noopener\" title={help.excerpt}>\n {'How it works'}\n </Link>\n </Typography>\n {busy ? (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <CircularProgress size={16} aria-label=\"Writing the overlay\" />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {saving ? 'Saving the overlay.' : 'Writing the copy.'}\n </Typography>\n </Stack>\n ) : null}\n {run.notice ? <Alert severity=\"warning\">{run.notice}</Alert> : null}\n {problem ? (\n <Alert severity={run.job?.status === 'failed' ? 'error' : 'warning'}>{problem}</Alert>\n ) : null}\n {saveError ? <Alert severity=\"error\">{saveError}</Alert> : null}\n {proposal && saveError ? <AiOverlayProposal proposal={proposal} triggers={triggers} /> : null}\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setOpen(false)} disabled={busy}>\n {'Cancel'}\n </Button>\n <Button variant=\"contained\" onClick={start} disabled={busy || !orgId || !brief.trim()}>\n {'Create the overlay'}\n </Button>\n </DialogActions>\n </Dialog>\n </>\n )\n}\nAiCreateOverlayButton.displayName = 'AiCreateOverlayButton'\n"],"names":["pluginDocsHelp","mdiCreation","MdiIcon","useHostOrgId","useUser","Alert","Box","Button","CircularProgress","Dialog","DialogActions","DialogContent","DialogTitle","Link","Stack","TextField","ToggleButton","ToggleButtonGroup","Typography","useEffect","useMemo","useRef","useState","AI_OVERLAY_COPY_TASK","AI_OVERLAY_CURRENT_MAX_CHARS","aiOverlayLimitInputs","aiOverlayTriggersInput","readAiOverlayCopy","AiUpsellButton","aiJobProblem","useAiJobRun","WRITE_FAILED_COPY","BRIEF_MAX_CHARS","aiOverlayProposalOf","job","status","output","outputs","proposal","aiOverlayProposalValues","values","name","kind","text","headline","body","ctaLabel","trigger","triggerValue","aiOverlayCurrentCopy","copy","lines","map","line","trim","filter","Boolean","join","slice","aiOverlayJobInputs","rules","current","inputs","task","overlayKind","triggers","key","value","Object","entries","limits","String","triggerText","rule","find","entry","id","label","unit","AiOverlayProposal","opens","sx","border","borderColor","borderRadius","p","aria-label","spacing","variant","color","whiteSpace","wordBreak","rationale","displayName","overlayHelp","anchor","excerpt","AiOverlayEditorCard","props","run","hostId","proposeValues","orgId","undefined","data","user","brief","setBrief","applied","setApplied","problem","busy","starting","running","noun","help","write","start","apply","direction","alignItems","flexGrow","href","target","rel","title","size","multiline","minRows","placeholder","helperText","onChange","event","disabled","startIcon","path","onClick","notice","severity","AiCreateOverlayButton","createOverlayDraft","open","setOpen","setKind","saving","setSaving","saveError","setSaveError","createdRef","jobId","then","result","ok","error","reset","catch","finally","entitled","upgrade","onClose","fullWidth","maxWidth","pt","exclusive","_event","next","autoFocus"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAGA,SAASA,cAAc,QAAQ,mCAAkC;AACjE,SAASC,WAAW,QAAQ,yBAAwB;AACpD,SAASC,OAAO,QAAQ,uBAAsB;AAC9C,SAASC,YAAY,EAAEC,OAAO,QAAQ,iCAAgC;AACtE,SACEC,KAAK,EACLC,GAAG,EACHC,MAAM,EACNC,gBAAgB,EAChBC,MAAM,EACNC,aAAa,EACbC,aAAa,EACbC,WAAW,EACXC,IAAI,EACJC,KAAK,EACLC,SAAS,EACTC,YAAY,EACZC,iBAAiB,EACjBC,UAAU,QACL,gBAAe;AACtB,SAASC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AAE5D,SACEC,oBAAoB,EACpBC,4BAA4B,EAC5BC,oBAAoB,EACpBC,sBAAsB,EACtBC,iBAAiB,QAKZ,8BAA0B;AACjC,SAASC,cAAc,QAAQ,kCAA8B;AAC7D,SAASC,YAAY,EAAEC,WAAW,QAAQ,sBAAkB;AAE5D;;;;;;;;;;;;;;;;CAgBC,GAED,MAAMC,oBAAoB;AAE1B,2CAA2C,GAC3C,MAAMC,kBAAkB;AAiDxB,iDAAiD,GACjD,OAAO,SAASC,oBAAoBC,GAAwB;IAC1D,IAAIA,CAAAA,uBAAAA,IAAKC,MAAM,MAAK,QAAQ,OAAO;IACnC,KAAK,MAAMC,UAAUF,IAAIG,OAAO,CAAE;QAChC,MAAMC,WAAWX,kBAAkBS,OAAOE,QAAQ;QAClD,IAAIA,UAAU,OAAOA;IACvB;IACA,OAAO;AACT;AAEA,yFAAyF,GACzF,OAAO,SAASC,wBAAwBD,QAA+B;IACrE,MAAME,SAAkC,CAAC;IACzC,IAAIF,SAASG,IAAI,EAAED,OAAOC,IAAI,GAAGH,SAASG,IAAI;IAC9C,IAAIH,SAASI,IAAI,KAAK,OAAO;QAC3B,IAAIJ,SAASK,IAAI,EAAEH,OAAOG,IAAI,GAAGL,SAASK,IAAI;QAC9C,OAAOH;IACT;IACA,IAAIF,SAASM,QAAQ,EAAEJ,OAAOI,QAAQ,GAAGN,SAASM,QAAQ;IAC1D,IAAIN,SAASO,IAAI,EAAEL,OAAOK,IAAI,GAAGP,SAASO,IAAI;IAC9C,IAAIP,SAASQ,QAAQ,EAAEN,OAAOM,QAAQ,GAAGR,SAASQ,QAAQ;IAC1D,IAAIR,SAASS,OAAO,EAAE;QACpBP,OAAOO,OAAO,GAAGT,SAASS,OAAO;QACjC,IAAIT,SAASU,YAAY,KAAK,MAAMR,OAAOQ,YAAY,GAAGV,SAASU,YAAY;IACjF;IACA,OAAOR;AACT;AAEA,8DAA8D,GAC9D,OAAO,SAASS,qBAAqBP,IAAmB,EAAEQ,IAAyB;IACjF,MAAMC,QACJT,SAAS,QACL;QAACQ,KAAKP,IAAI;KAAC,GACX;QAACO,KAAKN,QAAQ;QAAEM,KAAKL,IAAI;QAAEK,KAAKJ,QAAQ,GAAG,CAAC,QAAQ,EAAEI,KAAKJ,QAAQ,EAAE,GAAG;KAAG;IACjF,OAAOK,MACJC,GAAG,CAAC,CAACC,OAASA,KAAKC,IAAI,IACvBC,MAAM,CAACC,SACPC,IAAI,CAAC,QACLC,KAAK,CAAC,GAAGlC;AACd;AAEA,sCAAsC,GACtC,OAAO,SAASmC,mBACdjB,IAAmB,EACnBkB,KAAmB,EACnBC,OAAe;IAEf,MAAMC,SAAiC;QACrCC,MAAMxC;QACNyC,aAAatB;QACbuB,UAAUvC,uBAAuBkC,MAAMK,QAAQ;IACjD;IACA,KAAK,MAAM,CAACC,KAAKC,MAAM,IAAIC,OAAOC,OAAO,CAAC5C,qBAAqBmC,MAAMU,MAAM,GAAI;QAC7ER,MAAM,CAACI,IAAI,GAAGK,OAAOJ;IACvB;IACA,IAAIN,SAASC,MAAM,CAAC,UAAU,GAAGD;IACjC,OAAOC;AACT;AAEA,2DAA2D,GAC3D,SAASU,YACPlC,QAA+B,EAC/B2B,QAAyC;;IAEzC,IAAI,CAAC3B,SAASS,OAAO,EAAE,OAAO;IAC9B,MAAM0B,OAAOR,SAASS,IAAI,CAAC,CAACC,QAAUA,MAAMC,EAAE,KAAKtC,SAASS,OAAO;IACnE,MAAM8B,gBAAQJ,wBAAAA,KAAMI,KAAK,mBAAIvC,SAASS,OAAO;IAC7C,IAAIT,SAASU,YAAY,KAAK,QAAQ,EAACyB,wBAAAA,KAAMK,IAAI,GAAE,OAAOD;IAC1D,OAAO,GAAGA,MAAM,EAAE,EAAEvC,SAASU,YAAY,GAAGyB,KAAKK,IAAI,KAAK,YAAY,MAAM,YAAY;AAC1F;AAEA,sDAAsD,GACtD,OAAO,SAASC,kBAAkB,EAChCzC,QAAQ,EACR2B,QAAQ,EAIT;IACC,MAAMe,QAAQ1C,SAASI,IAAI,KAAK,UAAU8B,YAAYlC,UAAU2B,YAAY;IAC5E,qBACE,KAAC3D;QACC2E,IAAI;YAAEC,QAAQ;YAAGC,aAAa;YAAWC,cAAc;YAAGC,GAAG;QAAE;QAC/DC,cAAW;kBAEX,cAAA,MAACxE;YAAMyE,SAAS;;gBACbjD,SAASG,IAAI,iBACZ,KAACvB;oBAAWsE,SAAQ;oBAAUC,OAAM;8BACjCnD,SAASG,IAAI;qBAEd;gBACHH,SAASI,IAAI,KAAK,sBACjB,KAACxB;oBAAWsE,SAAQ;8BAASlD,SAASK,IAAI;mCAE1C;;wBACGL,SAASM,QAAQ,iBAChB,KAAC1B;4BAAWsE,SAAQ;sCAAalD,SAASM,QAAQ;6BAChD;sCACJ,KAAC1B;4BAAWsE,SAAQ;4BAAQP,IAAI;gCAAES,YAAY;gCAAYC,WAAW;4BAAa;sCAC/ErD,SAASO,IAAI;;wBAEfP,SAASQ,QAAQ,iBAChB,KAAC5B;4BAAWsE,SAAQ;sCAAS,CAAC,QAAQ,EAAElD,SAASQ,QAAQ,EAAE;6BACzD;wBACHkC,sBACC,KAAC9D;4BAAWsE,SAAQ;4BAAQC,OAAM;sCAC/B,CAAC,OAAO,EAAET,OAAO;6BAElB;;;gBAGP1C,SAASsD,SAAS,iBACjB,KAAC1E;oBAAWsE,SAAQ;oBAAUC,OAAM;8BACjCnD,SAASsD,SAAS;qBAEnB;;;;AAIZ;AACAb,kBAAkBc,WAAW,GAAG;AAEhC,MAAMC,cAAc,CAACC,QAAsDC,UACzEhG,eAAe,eAAe;QAAE+F;QAAQC;IAAQ;AAElD;;;;CAIC,GACD,OAAO,SAASC,oBAAoBC,KAA+B;QAEnD/F,eAOZ0B;QACCsE,UAuEsBA,WASWA,WAMbA;IA/FvB,MAAM,EAAEC,MAAM,EAAE1D,IAAI,EAAEQ,IAAI,EAAEmD,aAAa,EAAE/B,MAAM,EAAEL,QAAQ,EAAE,GAAGiC;IAChE,MAAMI,SAAQnG,gBAAAA,aAAaiG,mBAAbjG,gBAAwBoG;IACtC,MAAM,EAAEC,MAAMC,IAAI,EAAE,GAAGrG;IACvB,MAAM+F,MAAMrE,YAAY2E,MAAM1E;IAC9B,MAAM,CAAC2E,OAAOC,SAAS,GAAGrF,SAAS;IACnC,MAAM,CAACsF,SAASC,WAAW,GAAGvF,SAAwB;IACtD,MAAMgB,WAAWlB,QAAQ,IAAMa,oBAAoBkE,IAAIjE,GAAG,GAAG;QAACiE,IAAIjE,GAAG;KAAC;IACtE,MAAM4E,WACJjF,gBAAAA,aAAasE,IAAIjE,GAAG,EAAEH,8BAAtBF,gBACCsE,EAAAA,WAAAA,IAAIjE,GAAG,qBAAPiE,SAAShE,MAAM,MAAK,UAAU,CAACG,WAAWP,oBAAoB;IAGjE,MAAMgF,OAAOZ,IAAIa,QAAQ,IAAIb,IAAIc,OAAO;IACxC,MAAMpD,UAAUZ,qBAAqBP,MAAMQ;IAC3C,MAAMgE,OAAOxE,SAAS,QAAQ,QAAQ;IACtC,MAAMyE,OAAOrB,YAAY,uBAAuB;IAChD,MAAMsB,QAAQ;QACZ,IAAI,CAACd,SAAS,CAAEI,CAAAA,MAAMpD,IAAI,MAAMO,OAAM,GAAI;QAC1CgD,WAAW;QACX,KAAKV,IAAIkB,KAAK,CAAC;YACbf;YACAF;YACA1D,MAAM;YACNgE,OAAOA,MAAMpD,IAAI,MAAM,CAAC,yBAAyB,EAAE4D,KAAK,CAAC,CAAC;YAC1DpD,QAAQH,mBAAmBjB,MAAM;gBAAE4B;gBAAQL;YAAS,GAAGJ;QACzD;IACF;IACA,MAAMyD,QAAQ;QACZ,IAAI,CAAChF,YAAY,CAAC6D,IAAIjE,GAAG,EAAE;QAC3BmE,cAAc9D,wBAAwBD,WAAW6D,IAAIjE,GAAG,CAAC0C,EAAE;QAC3DiC,WAAWV,IAAIjE,GAAG,CAAC0C,EAAE;IACvB;IAEA,qBACE,KAACtE;QACC2E,IAAI;YAAEC,QAAQ;YAAGC,aAAa;YAAWC,cAAc;YAAGC,GAAG;QAAI;QACjEC,cAAW;kBAEX,cAAA,MAACxE;YAAMyE,SAAS;;8BACd,MAACzE;oBAAMyG,WAAU;oBAAMhC,SAAS;oBAAGN,IAAI;wBAAEuC,YAAY;oBAAW;;sCAC9D,KAACtG;4BAAWsE,SAAQ;4BAAYP,IAAI;gCAAEwC,UAAU;4BAAE;sCAC/C;;sCAEH,KAAC5G;4BAAK6G,MAAMP,KAAKO,IAAI;4BAAEC,QAAO;4BAASC,KAAI;4BAAWpC,SAAQ;4BAAUqC,OAAOV,KAAKnB,OAAO;sCACxF;;;;8BAGL,KAACjF;oBACC+G,MAAK;oBACLC,SAAS;oBACTC,SAAS;oBACTnD,OAAO,CAAC,aAAa,EAAEqC,KAAK,KAAK,CAAC;oBAClCe,aACEvF,SAAS,QACL,uDACA;oBAENwF,YACErE,UACI,kFACA;oBAENM,OAAOuC;oBACPyB,UAAU,CAACC,QAAUzB,SAASyB,MAAMT,MAAM,CAACxD,KAAK,CAACT,KAAK,CAAC,GAAG1B;oBAC1DqG,UAAUtB;;8BAEZ,MAACjG;oBAAMyG,WAAU;oBAAMhC,SAAS;oBAAGN,IAAI;wBAAEuC,YAAY;oBAAS;;sCAC5D,KAACjH;4BACCuH,MAAK;4BACLtC,SAAQ;4BACR8C,yBAAW,KAACpI;gCAAQqI,MAAMtI,YAAYsI,IAAI;;4BAC1CF,UAAUtB,QAAQ,CAACT,SAAS,CAAEI,CAAAA,MAAMpD,IAAI,MAAMO,OAAM;4BACpD2E,SAASpB;sCAERjB,IAAIjE,GAAG,IAAI,CAAC6E,OAAO,mBAAmB;;wBAExCA,qBAAO,KAACvG;4BAAiBsH,MAAM;4BAAIxC,cAAW;6BAAwB;;;gBAExEa,IAAIsC,MAAM,iBAAG,KAACpI;oBAAMqI,UAAS;8BAAWvC,IAAIsC,MAAM;qBAAY;gBAC9D3B,wBACC,KAACzG;oBAAMqI,UAAUvC,EAAAA,YAAAA,IAAIjE,GAAG,qBAAPiE,UAAShE,MAAM,MAAK,WAAW,UAAU;8BAAY2E;qBACpE;gBACHxE,yBACC,MAACxB;oBAAMyE,SAAS;;sCACd,KAACR;4BAAkBzC,UAAUA;4BAAU2B,UAAUA;;sCACjD,KAACnD;4BAAMyG,WAAU;4BAAMhC,SAAS;sCAC9B,cAAA,KAAChF;gCACCuH,MAAK;gCACLtC,SAAQ;gCACR6C,UAAUzB,cAAYT,YAAAA,IAAIjE,GAAG,qBAAPiE,UAASvB,EAAE;gCACjC4D,SAASlB;0CAER;;;wBAGJV,cAAYT,YAAAA,IAAIjE,GAAG,qBAAPiE,UAASvB,EAAE,kBACtB,KAACvE;4BAAMqI,UAAS;sCACb;6BAED;;qBAEJ;;;;AAIZ;AACAzC,oBAAoBJ,WAAW,GAAG;AAElC;;;;CAIC,GACD,OAAO,SAAS8C,sBAAsBzC,KAAiC;QAEvD/F,eAYZ0B;QACCsE,UAwG0BA;IAtH7B,MAAM,EAAEC,MAAM,EAAEwC,kBAAkB,EAAEtE,MAAM,EAAEL,QAAQ,EAAE,GAAGiC;IACzD,MAAMI,SAAQnG,gBAAAA,aAAaiG,mBAAbjG,gBAAwBoG;IACtC,MAAM,EAAEC,MAAMC,IAAI,EAAE,GAAGrG;IACvB,MAAM+F,MAAMrE,YAAY2E,MAAM1E;IAC9B,MAAM,CAAC8G,MAAMC,QAAQ,GAAGxH,SAAS;IACjC,MAAM,CAACoB,MAAMqG,QAAQ,GAAGzH,SAAwB;IAChD,MAAM,CAACoF,OAAOC,SAAS,GAAGrF,SAAS;IACnC,MAAM,CAAC0H,QAAQC,UAAU,GAAG3H,SAAS;IACrC,MAAM,CAAC4H,WAAWC,aAAa,GAAG7H,SAAwB;IAC1D,sEAAsE,GACtE,MAAM8H,aAAa/H,OAAsB;IACzC,MAAMiB,WAAWlB,QAAQ,IAAMa,oBAAoBkE,IAAIjE,GAAG,GAAG;QAACiE,IAAIjE,GAAG;KAAC;IACtE,MAAM4E,WACJjF,gBAAAA,aAAasE,IAAIjE,GAAG,EAAEH,8BAAtBF,gBACCsE,EAAAA,WAAAA,IAAIjE,GAAG,qBAAPiE,SAAShE,MAAM,MAAK,UAAU,CAACG,WAAWP,oBAAoB;IAEjE,2EAA2E;IAC3E,gEAAgE;IAChEZ,UAAU;YACMgF;QAAd,MAAMkD,SAAQlD,WAAAA,IAAIjE,GAAG,qBAAPiE,SAASvB,EAAE;QACzB,IAAI,CAACtC,YAAY,CAAC+G,SAASD,WAAWvF,OAAO,KAAKwF,OAAO;QACzDD,WAAWvF,OAAO,GAAGwF;QACrBJ,UAAU;QACVE,aAAa;QACb,KAAKP,mBAAmBtG,SAASI,IAAI,EAAEH,wBAAwBD,WAC5DgH,IAAI,CAAC,CAACC;YACL,IAAIA,OAAOC,EAAE,KAAK,OAAO;gBACvBL,aAAaI,OAAOE,KAAK;gBACzB;YACF;YACAX,QAAQ;YACRnC,SAAS;YACTR,IAAIuD,KAAK;QACX,GACCC,KAAK,CAAC,IAAMR,aAAa,+CACzBS,OAAO,CAAC,IAAMX,UAAU;IAC7B,GAAG;QAAC3G;QAAU6D;QAAKyC;KAAmB;IAEtC,6EAA6E;IAC7E,sEAAsE;IACtE,IAAI1C,MAAM2D,QAAQ,KAAK,OAAO;QAC5B,OAAO3D,MAAM4D,OAAO,iBAAG,KAAClI;YAAec,MAAK;YAAUoH,SAAS5D,MAAM4D,OAAO;aAAO;IACrF;IAEA,MAAM/C,OAAOZ,IAAIa,QAAQ,IAAIb,IAAIc,OAAO,IAAI+B;IAC5C,MAAM7B,OAAOrB,YAAY,sBAAsB;IAC/C,MAAMuB,QAAQ;QACZ,IAAI,CAACf,SAAS,CAACI,MAAMpD,IAAI,IAAI;QAC7B8F,WAAWvF,OAAO,GAAG;QACrBsF,aAAa;QACb,KAAKhD,IAAIkB,KAAK,CAAC;YACbf;YACAF;YACA1D,MAAM;YACNgE,OAAOA,MAAMpD,IAAI;YACjBQ,QAAQH,mBAAmBjB,MAAM;gBAAE4B;gBAAQL;YAAS,GAAG;QACzD;IACF;IAEA,qBACE;;0BACE,KAAC1D;gBACCuH,MAAK;gBACLtC,SAAQ;gBACR8C,yBAAW,KAACpI;oBAAQqI,MAAMtI,YAAYsI,IAAI;;gBAC1CC,SAAS,IAAMM,QAAQ;0BAEtB;;0BAEH,MAACrI;gBAAOoI,MAAMA;gBAAMkB,SAAShD,OAAOR,YAAY,IAAMuC,QAAQ;gBAAQkB,SAAS;gBAACC,UAAS;;kCACvF,KAACrJ;kCAAa;;kCACd,KAACD;kCACC,cAAA,MAACG;4BAAMyE,SAAS;4BAAGN,IAAI;gCAAEiF,IAAI;4BAAE;;8CAC7B,MAACjJ;oCACCkJ,SAAS;oCACTrC,MAAK;oCACL3D,OAAOzB;oCACPyF,UAAU,CAACiC,QAAQC;wCACjB,IAAIA,MAAMtB,QAAQsB;oCACpB;oCACA/E,cAAW;oCACX+C,UAAUtB;;sDAEV,KAAC/F;4CAAamD,OAAM;sDAAS;;sDAC7B,KAACnD;4CAAamD,OAAM;sDAAO;;;;8CAE7B,KAACpD;oCACC8D,OAAOnC,SAAS,QAAQ,kCAAkC;oCAC1DuF,aACEvF,SAAS,QACL,4DACA;oCAENqF,SAAS;oCACTC,SAAS;oCACT7D,OAAOuC;oCACPyB,UAAU,CAACC,QAAUzB,SAASyB,MAAMT,MAAM,CAACxD,KAAK,CAACT,KAAK,CAAC,GAAG1B;oCAC1DqG,UAAUtB;oCACVuD,SAAS;;8CAEX,MAACpJ;oCAAWsE,SAAQ;oCAAQC,OAAM;;wCAC/B,yFACC;wCACD;sDACD,KAAC5E;4CAAK6G,MAAMP,KAAKO,IAAI;4CAAEC,QAAO;4CAASC,KAAI;4CAAWC,OAAOV,KAAKnB,OAAO;sDACtE;;;;gCAGJe,qBACC,MAACjG;oCAAMyG,WAAU;oCAAMhC,SAAS;oCAAGN,IAAI;wCAAEuC,YAAY;oCAAS;;sDAC5D,KAAChH;4CAAiBsH,MAAM;4CAAIxC,cAAW;;sDACvC,KAACpE;4CAAWsE,SAAQ;4CAAQC,OAAM;sDAC/BuD,SAAS,wBAAwB;;;qCAGpC;gCACH7C,IAAIsC,MAAM,iBAAG,KAACpI;oCAAMqI,UAAS;8CAAWvC,IAAIsC,MAAM;qCAAY;gCAC9D3B,wBACC,KAACzG;oCAAMqI,UAAUvC,EAAAA,YAAAA,IAAIjE,GAAG,qBAAPiE,UAAShE,MAAM,MAAK,WAAW,UAAU;8CAAY2E;qCACpE;gCACHoC,0BAAY,KAAC7I;oCAAMqI,UAAS;8CAASQ;qCAAqB;gCAC1D5G,YAAY4G,0BAAY,KAACnE;oCAAkBzC,UAAUA;oCAAU2B,UAAUA;qCAAe;;;;kCAG7F,MAACvD;;0CACC,KAACH;gCAAOiI,SAAS,IAAMM,QAAQ;gCAAQT,UAAUtB;0CAC9C;;0CAEH,KAACxG;gCAAOiF,SAAQ;gCAAYgD,SAASnB;gCAAOgB,UAAUtB,QAAQ,CAACT,SAAS,CAACI,MAAMpD,IAAI;0CAChF;;;;;;;;AAMb;AACAqF,sBAAsB9C,WAAW,GAAG"}
|
|
@@ -122,3 +122,8 @@ export interface ConsoleProductImportZoneProps {
|
|
|
122
122
|
options: Readonly<Record<string, boolean>>;
|
|
123
123
|
setOption: (key: string, on: boolean) => void;
|
|
124
124
|
}
|
|
125
|
+
/** What `productsCreate` hands each widget: the site and its org (AGL-3596). */
|
|
126
|
+
export interface ConsoleProductsCreateZoneProps {
|
|
127
|
+
hostId: string;
|
|
128
|
+
orgId: string | undefined;
|
|
129
|
+
}
|
|
@@ -27,6 +27,6 @@
|
|
|
27
27
|
* the injection zones reference.
|
|
28
28
|
*
|
|
29
29
|
* Types only: nothing here reaches a bundle.
|
|
30
|
-
*/ /**
|
|
30
|
+
*/ /** What `productsCreate` hands each widget: the site and its org (AGL-3596). */ export { };
|
|
31
31
|
|
|
32
32
|
//# sourceMappingURL=ai-product-zones.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-product-zones.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * What the commerce plugin's product zones hand this plugin's widgets.\n *\n * `productEditor`, `productsHub` and `productImport` are zones the commerce\n * plugin hosts and declares (`registerPluginZone`), with their props on its\n * own zone tokens. A plugin never imports another plugin, so the widgets\n * registered there read the props through the shapes restated here — the\n * zone's props as the host documents them, by the same names. A widget is\n * handed whatever the host passes, so this restates what the host SENDS; a\n * field dropped from the host's declaration leaves a widget reading\n * `undefined`, which is why every member below is one the host documents in\n * the injection zones reference.\n *\n * Types only: nothing here reaches a bundle.\n */\n\nexport type ConsoleProductType = 'physical' | 'digital' | 'service'\n\nexport interface ConsoleProductOption {\n name: string\n values: string[]\n}\n\n/** A product as the editor holds it: saved, or staged and unsaved. */\nexport interface ConsoleProductDraft {\n /** `null` for a product nobody has saved yet. */\n id: string | null\n name: string\n type: ConsoleProductType\n description: string\n tags: string[]\n categoryIds: string[]\n options: ConsoleProductOption[]\n /** The product's media, in order; the first is the photo the storefront leads with. */\n mediaUrls: string[]\n seoTitle: string\n seoDescription: string\n}\n\n/**\n * Copy proposed for one product. A field left out is left alone;\n * `optionNames` renames the product's options in order.\n */\nexport interface ConsoleProductCopyValues {\n description?: string\n tags?: string[]\n categoryIds?: string[]\n optionNames?: string[]\n seoTitle?: string\n seoDescription?: string\n}\n\n/** The `productEditor` zone: the product, and a door that stages copy as unsaved edits. */\nexport interface ConsoleProductEditorZoneProps {\n hostId: string\n orgId: string | undefined\n product: ConsoleProductDraft\n categories: ReadonlyArray<{ id: string; name: string }>\n proposeValues: (values: ConsoleProductCopyValues, key: string) => void\n}\n\n/** A catalog row as the products hub holds it. */\nexport interface ConsoleProductSummary {\n id: string\n name: string\n status: 'draft' | 'active' | 'archived'\n priceMissing: boolean\n hasPhoto: boolean\n}\n\n/** A new product proposed to the hub, which creates it as a draft with no price. */\nexport interface ConsoleProposedProduct {\n name: string\n type: ConsoleProductType\n description: string\n tags: string[]\n options: ConsoleProductOption[]\n seoTitle: string\n seoDescription: string\n}\n\n/** A discount proposed to the hub, which creates it switched off. */\nexport interface ConsoleProposedDiscount {\n name: string\n code: string | null\n kind: 'percent' | 'fixed' | 'free_shipping'\n valuePct: number | null\n valueCents: number | null\n minSubtotalCents: number | null\n}\n\n/** The `productsHub` zone: the catalog rows, the latest import, and the hub's writes. */\nexport interface ConsoleProductsHubZoneProps {\n hostId: string\n orgId: string | undefined\n products: readonly ConsoleProductSummary[]\n lastImport: {\n key: string\n productIds: readonly string[]\n options: Readonly<Record<string, boolean>>\n } | null\n applyProductCopy: (productId: string, values: ConsoleProductCopyValues) => Promise<void>\n createProductDrafts: (products: readonly ConsoleProposedProduct[]) => Promise<string[]>\n createCategories: (names: readonly string[]) => Promise<number>\n createDiscountDrafts: (discounts: readonly ConsoleProposedDiscount[]) => Promise<number>\n}\n\n/** The `productImport` zone: the import's size and the options set for it. */\nexport interface ConsoleProductImportZoneProps {\n hostId: string\n orgId: string | undefined\n count: number\n options: Readonly<Record<string, boolean>>\n setOption: (key: string, on: boolean) => void\n}\n"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;CAcC,
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/components/ai-product-zones.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * What the commerce plugin's product zones hand this plugin's widgets.\n *\n * `productEditor`, `productsHub` and `productImport` are zones the commerce\n * plugin hosts and declares (`registerPluginZone`), with their props on its\n * own zone tokens. A plugin never imports another plugin, so the widgets\n * registered there read the props through the shapes restated here — the\n * zone's props as the host documents them, by the same names. A widget is\n * handed whatever the host passes, so this restates what the host SENDS; a\n * field dropped from the host's declaration leaves a widget reading\n * `undefined`, which is why every member below is one the host documents in\n * the injection zones reference.\n *\n * Types only: nothing here reaches a bundle.\n */\n\nexport type ConsoleProductType = 'physical' | 'digital' | 'service'\n\nexport interface ConsoleProductOption {\n name: string\n values: string[]\n}\n\n/** A product as the editor holds it: saved, or staged and unsaved. */\nexport interface ConsoleProductDraft {\n /** `null` for a product nobody has saved yet. */\n id: string | null\n name: string\n type: ConsoleProductType\n description: string\n tags: string[]\n categoryIds: string[]\n options: ConsoleProductOption[]\n /** The product's media, in order; the first is the photo the storefront leads with. */\n mediaUrls: string[]\n seoTitle: string\n seoDescription: string\n}\n\n/**\n * Copy proposed for one product. A field left out is left alone;\n * `optionNames` renames the product's options in order.\n */\nexport interface ConsoleProductCopyValues {\n description?: string\n tags?: string[]\n categoryIds?: string[]\n optionNames?: string[]\n seoTitle?: string\n seoDescription?: string\n}\n\n/** The `productEditor` zone: the product, and a door that stages copy as unsaved edits. */\nexport interface ConsoleProductEditorZoneProps {\n hostId: string\n orgId: string | undefined\n product: ConsoleProductDraft\n categories: ReadonlyArray<{ id: string; name: string }>\n proposeValues: (values: ConsoleProductCopyValues, key: string) => void\n}\n\n/** A catalog row as the products hub holds it. */\nexport interface ConsoleProductSummary {\n id: string\n name: string\n status: 'draft' | 'active' | 'archived'\n priceMissing: boolean\n hasPhoto: boolean\n}\n\n/** A new product proposed to the hub, which creates it as a draft with no price. */\nexport interface ConsoleProposedProduct {\n name: string\n type: ConsoleProductType\n description: string\n tags: string[]\n options: ConsoleProductOption[]\n seoTitle: string\n seoDescription: string\n}\n\n/** A discount proposed to the hub, which creates it switched off. */\nexport interface ConsoleProposedDiscount {\n name: string\n code: string | null\n kind: 'percent' | 'fixed' | 'free_shipping'\n valuePct: number | null\n valueCents: number | null\n minSubtotalCents: number | null\n}\n\n/** The `productsHub` zone: the catalog rows, the latest import, and the hub's writes. */\nexport interface ConsoleProductsHubZoneProps {\n hostId: string\n orgId: string | undefined\n products: readonly ConsoleProductSummary[]\n lastImport: {\n key: string\n productIds: readonly string[]\n options: Readonly<Record<string, boolean>>\n } | null\n applyProductCopy: (productId: string, values: ConsoleProductCopyValues) => Promise<void>\n createProductDrafts: (products: readonly ConsoleProposedProduct[]) => Promise<string[]>\n createCategories: (names: readonly string[]) => Promise<number>\n createDiscountDrafts: (discounts: readonly ConsoleProposedDiscount[]) => Promise<number>\n}\n\n/** The `productImport` zone: the import's size and the options set for it. */\nexport interface ConsoleProductImportZoneProps {\n hostId: string\n orgId: string | undefined\n count: number\n options: Readonly<Record<string, boolean>>\n setOption: (key: string, on: boolean) => void\n}\n\n/** What `productsCreate` hands each widget: the site and its org (AGL-3596). */\nexport interface ConsoleProductsCreateZoneProps {\n hostId: string\n orgId: string | undefined\n}\n"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;CAcC,GAsGD,8EAA8E,GAC9E,WAGC"}
|