@aglyn/plugins-marketplace 1.2.0 → 1.4.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 (76) hide show
  1. package/README.md +1 -1
  2. package/package.json +14 -14
  3. package/src/lib/components/listing-content.component.js +11 -3
  4. package/src/lib/components/listing-content.component.js.map +1 -1
  5. package/src/lib/components/marketplace-pay-panel.component.d.ts +67 -0
  6. package/src/lib/components/marketplace-pay-panel.component.js +228 -0
  7. package/src/lib/components/marketplace-pay-panel.component.js.map +1 -0
  8. package/src/lib/components/publish-artifact-dialog.component.d.ts +1 -1
  9. package/src/lib/components/publish-artifact-dialog.component.js +144 -20
  10. package/src/lib/components/publish-artifact-dialog.component.js.map +1 -1
  11. package/src/lib/components/publish-starter-fields.component.d.ts +35 -0
  12. package/src/lib/components/publish-starter-fields.component.js +176 -0
  13. package/src/lib/components/publish-starter-fields.component.js.map +1 -0
  14. package/src/lib/components/starter-picker-shelf.component.d.ts +2 -2
  15. package/src/lib/components/starter-picker-shelf.component.js +28 -6
  16. package/src/lib/components/starter-picker-shelf.component.js.map +1 -1
  17. package/src/lib/hooks/use-marketplace-actions.d.ts +9 -3
  18. package/src/lib/hooks/use-marketplace-actions.js +47 -89
  19. package/src/lib/hooks/use-marketplace-actions.js.map +1 -1
  20. package/src/lib/hooks/use-marketplace-pay.d.ts +70 -0
  21. package/src/lib/hooks/use-marketplace-pay.js +359 -0
  22. package/src/lib/hooks/use-marketplace-pay.js.map +1 -0
  23. package/src/lib/hooks/use-starter-publish-facts.d.ts +25 -0
  24. package/src/lib/hooks/use-starter-publish-facts.js +116 -0
  25. package/src/lib/hooks/use-starter-publish-facts.js.map +1 -0
  26. package/src/lib/hooks/use-starter-purchase.d.ts +17 -22
  27. package/src/lib/hooks/use-starter-purchase.js +26 -73
  28. package/src/lib/hooks/use-starter-purchase.js.map +1 -1
  29. package/src/lib/model/marketplace-invoice.d.ts +52 -0
  30. package/src/lib/model/marketplace-invoice.js +75 -0
  31. package/src/lib/model/marketplace-invoice.js.map +1 -0
  32. package/src/lib/model/marketplace-pay.d.ts +42 -0
  33. package/src/lib/model/marketplace-pay.js +33 -0
  34. package/src/lib/model/marketplace-pay.js.map +1 -0
  35. package/src/lib/model/platform-seller.d.ts +37 -0
  36. package/src/lib/model/platform-seller.js +36 -0
  37. package/src/lib/model/platform-seller.js.map +1 -0
  38. package/src/lib/model/publisher-agreement.d.ts +15 -3
  39. package/src/lib/model/publisher-agreement.js +23 -3
  40. package/src/lib/model/publisher-agreement.js.map +1 -1
  41. package/src/lib/model/starter-publish.d.ts +159 -0
  42. package/src/lib/model/starter-publish.js +189 -0
  43. package/src/lib/model/starter-publish.js.map +1 -0
  44. package/src/lib/model/starter-query.d.ts +0 -8
  45. package/src/lib/model/starter-query.js +0 -10
  46. package/src/lib/model/starter-query.js.map +1 -1
  47. package/src/lib/server/billing-webhook.d.ts +6 -0
  48. package/src/lib/server/billing-webhook.js +269 -211
  49. package/src/lib/server/billing-webhook.js.map +1 -1
  50. package/src/lib/server/checkout.d.ts +2 -48
  51. package/src/lib/server/checkout.js +21 -241
  52. package/src/lib/server/checkout.js.map +1 -1
  53. package/src/lib/server/pay.d.ts +18 -0
  54. package/src/lib/server/pay.js +540 -0
  55. package/src/lib/server/pay.js.map +1 -0
  56. package/src/lib/server/platform-org.d.ts +23 -0
  57. package/src/lib/server/platform-org.js +27 -0
  58. package/src/lib/server/platform-org.js.map +1 -0
  59. package/src/lib/server/publish-preconditions.js +4 -1
  60. package/src/lib/server/publish-preconditions.js.map +1 -1
  61. package/src/lib/server/publish-starter.js +5 -2
  62. package/src/lib/server/publish-starter.js.map +1 -1
  63. package/src/lib/server/publisher-profile.d.ts +5 -0
  64. package/src/lib/server/publisher-profile.js +20 -1
  65. package/src/lib/server/publisher-profile.js.map +1 -1
  66. package/src/lib/server/publisher-standing.d.ts +26 -0
  67. package/src/lib/server/publisher-standing.js +66 -0
  68. package/src/lib/server/publisher-standing.js.map +1 -0
  69. package/src/lib/server/sale.d.ts +119 -0
  70. package/src/lib/server/sale.js +304 -0
  71. package/src/lib/server/sale.js.map +1 -0
  72. package/src/lib/server/starter-publish-facts.d.ts +36 -0
  73. package/src/lib/server/starter-publish-facts.js +135 -0
  74. package/src/lib/server/starter-publish-facts.js.map +1 -0
  75. package/src/lib/server.js +8 -0
  76. package/src/lib/server.js.map +1 -1
@@ -0,0 +1,67 @@
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
+ */
17
+ import type { BillingAddressValue } from '@aglyn/shared-ui-jsx/stripe/billing-address-form.component';
18
+ import { type PayPrerequisite, type PayQuote } from '../model/marketplace-pay';
19
+ /** Which part of paying for a listing is on screen. */
20
+ export type PayStep = {
21
+ kind: 'confirm';
22
+ quote: PayQuote;
23
+ }
24
+ /** A card is needed, and this person can add one: `null` until its form has a secret. */
25
+ | {
26
+ kind: 'card';
27
+ clientSecret: string | null;
28
+ } | {
29
+ kind: 'address';
30
+ }
31
+ /** Something is needed that this person cannot add. */
32
+ | {
33
+ kind: 'ask-billing';
34
+ need: PayPrerequisite;
35
+ amountCents: number | null;
36
+ };
37
+ export interface MarketplacePayPanelProps {
38
+ step: PayStep;
39
+ listingName: string;
40
+ busy: boolean;
41
+ /** Stripe's reason, or ours, for the last thing that did not go through. */
42
+ error: string | null;
43
+ /** The workspace's Billing page, when its address is known. */
44
+ billingHref?: string | null;
45
+ onPay: () => void;
46
+ onCardSaved: (setupIntentId: string) => Promise<void> | void;
47
+ onAddressSaved: (address: BillingAddressValue) => Promise<void> | void;
48
+ onCancel: () => void;
49
+ }
50
+ /**
51
+ * Paying for a listing, in place (AGL-4049).
52
+ *
53
+ * Inline, under the button that asked for it, in the listing's sidebar and in
54
+ * Create site alike, for the reason the billing card form is inline: a payment
55
+ * surface that appears over the page and looks like a different product is a
56
+ * reason to stop buying. Nothing here is a Dialog, and the card and address
57
+ * fields are Stripe's own, so the card data guarantee is the billing page's.
58
+ *
59
+ * The total is on screen before the Pay button is: a saved card charged
60
+ * without one is not a purchase anybody agreed to.
61
+ *
62
+ * Figma: "Aglyn Console (web)" → page "Marketplace · Publish & review" →
63
+ * section "✅ CURRENT · Paying in the console", and page "Sites · Create site"
64
+ * → frames "Choose your starter · Buy (card on file)" and "· Buy (add a card)".
65
+ */
66
+ export declare function MarketplacePayPanel(props: MarketplacePayPanelProps): import("react").JSX.Element;
67
+ export default MarketplacePayPanel;
@@ -0,0 +1,228 @@
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 { orgPermissionLabel } from "@aglyn/aglyn/app-utils/org-permissions";
19
+ import { PrerequisiteNotice } from "@aglyn/shared-ui-jsx/components/prerequisite-notice.component";
20
+ import { LazyBillingAddressForm, LazyBillingCardForm } from "@aglyn/shared-ui-jsx/stripe/lazy-stripe";
21
+ import { Alert, Button, CircularProgress, Divider, Stack, Typography } from "@mui/material";
22
+ import { Suspense } from "react";
23
+ import { formatPayCents, payCardLabel } from "../model/marketplace-pay.js";
24
+ const SUMMARY_LINE_SX = {
25
+ justifyContent: 'space-between'
26
+ };
27
+ function SummaryLine(props) {
28
+ const variant = props.strong ? 'subtitle2' : 'body2';
29
+ return /*#__PURE__*/ _jsxs(Stack, {
30
+ direction: "row",
31
+ spacing: 2,
32
+ sx: SUMMARY_LINE_SX,
33
+ children: [
34
+ /*#__PURE__*/ _jsx(Typography, {
35
+ variant: variant,
36
+ children: props.label
37
+ }),
38
+ /*#__PURE__*/ _jsx(Typography, {
39
+ variant: variant,
40
+ children: props.value
41
+ })
42
+ ]
43
+ });
44
+ }
45
+ const FormLoading = ()=>/*#__PURE__*/ _jsx(CircularProgress, {
46
+ size: 24,
47
+ "aria-label": "Loading the card form"
48
+ });
49
+ /**
50
+ * Paying for a listing, in place (AGL-4049).
51
+ *
52
+ * Inline, under the button that asked for it, in the listing's sidebar and in
53
+ * Create site alike, for the reason the billing card form is inline: a payment
54
+ * surface that appears over the page and looks like a different product is a
55
+ * reason to stop buying. Nothing here is a Dialog, and the card and address
56
+ * fields are Stripe's own, so the card data guarantee is the billing page's.
57
+ *
58
+ * The total is on screen before the Pay button is: a saved card charged
59
+ * without one is not a purchase anybody agreed to.
60
+ *
61
+ * Figma: "Aglyn Console (web)" → page "Marketplace · Publish & review" →
62
+ * section "✅ CURRENT · Paying in the console", and page "Sites · Create site"
63
+ * → frames "Choose your starter · Buy (card on file)" and "· Buy (add a card)".
64
+ */ export function MarketplacePayPanel(props) {
65
+ const { step, listingName, busy, error, billingHref, onPay, onCardSaved, onAddressSaved, onCancel } = props;
66
+ const failure = error ? /*#__PURE__*/ _jsx(Alert, {
67
+ severity: "warning",
68
+ "data-marketplace-pay-error": true,
69
+ children: error
70
+ }) : null;
71
+ if (step.kind === 'confirm') {
72
+ const { quote } = step;
73
+ return /*#__PURE__*/ _jsxs(Stack, {
74
+ spacing: 1.5,
75
+ "data-marketplace-pay": "confirm",
76
+ children: [
77
+ /*#__PURE__*/ _jsx(Typography, {
78
+ variant: "subtitle2",
79
+ children: `Buy ${quote.listingName}`
80
+ }),
81
+ /*#__PURE__*/ _jsxs(Stack, {
82
+ spacing: 0.5,
83
+ children: [
84
+ /*#__PURE__*/ _jsx(SummaryLine, {
85
+ label: "Price",
86
+ value: formatPayCents(quote.amountCents)
87
+ }),
88
+ /*#__PURE__*/ _jsx(SummaryLine, {
89
+ label: "Sales tax",
90
+ value: formatPayCents(quote.taxCents)
91
+ }),
92
+ /*#__PURE__*/ _jsx(Divider, {}),
93
+ /*#__PURE__*/ _jsx(SummaryLine, {
94
+ label: "Total",
95
+ value: formatPayCents(quote.totalCents),
96
+ strong: true
97
+ })
98
+ ]
99
+ }),
100
+ quote.canPay ? /*#__PURE__*/ _jsxs(_Fragment, {
101
+ children: [
102
+ /*#__PURE__*/ _jsx(Typography, {
103
+ variant: "body2",
104
+ color: "text.secondary",
105
+ children: `Charged to ${payCardLabel(quote.card)}. The receipt lands in Billing.`
106
+ }),
107
+ error ? /*#__PURE__*/ _jsx(PrerequisiteNotice, {
108
+ severity: "warning",
109
+ href: billingHref != null ? billingHref : undefined,
110
+ actionLabel: "Open Billing",
111
+ children: error
112
+ }) : null,
113
+ /*#__PURE__*/ _jsxs(Stack, {
114
+ direction: "row",
115
+ spacing: 1,
116
+ children: [
117
+ /*#__PURE__*/ _jsx(Button, {
118
+ variant: "contained",
119
+ size: "small",
120
+ disabled: busy,
121
+ onClick: onPay,
122
+ children: busy ? 'Paying…' : `Pay ${formatPayCents(quote.totalCents)}`
123
+ }),
124
+ /*#__PURE__*/ _jsx(Button, {
125
+ size: "small",
126
+ disabled: busy,
127
+ onClick: onCancel,
128
+ children: 'Cancel'
129
+ })
130
+ ]
131
+ })
132
+ ]
133
+ }) : /*#__PURE__*/ _jsxs(_Fragment, {
134
+ children: [
135
+ /*#__PURE__*/ _jsx(PrerequisiteNotice, {
136
+ severity: "warning",
137
+ children: `Buying this charges your workspace's card, which takes the "${orgPermissionLabel('billing.manage')}" permission. Ask someone who manages billing to buy it.`
138
+ }),
139
+ /*#__PURE__*/ _jsx(Stack, {
140
+ direction: "row",
141
+ children: /*#__PURE__*/ _jsx(Button, {
142
+ size: "small",
143
+ onClick: onCancel,
144
+ children: 'Close'
145
+ })
146
+ })
147
+ ]
148
+ })
149
+ ]
150
+ });
151
+ }
152
+ if (step.kind === 'card') {
153
+ return /*#__PURE__*/ _jsxs(Stack, {
154
+ spacing: 1.5,
155
+ "data-marketplace-pay": "card",
156
+ children: [
157
+ /*#__PURE__*/ _jsx(Typography, {
158
+ variant: "subtitle2",
159
+ children: `Add a card to buy ${listingName}`
160
+ }),
161
+ /*#__PURE__*/ _jsx(Typography, {
162
+ variant: "body2",
163
+ color: "text.secondary",
164
+ children: 'It stays on file for this workspace, in Billing, where you can change or remove it.'
165
+ }),
166
+ failure,
167
+ /*#__PURE__*/ _jsx(Suspense, {
168
+ fallback: /*#__PURE__*/ _jsx(FormLoading, {}),
169
+ children: step.clientSecret ? /*#__PURE__*/ _jsx(LazyBillingCardForm, {
170
+ clientSecret: step.clientSecret,
171
+ onConfirmed: onCardSaved,
172
+ onCancel: onCancel
173
+ }) : /*#__PURE__*/ _jsx(FormLoading, {})
174
+ })
175
+ ]
176
+ });
177
+ }
178
+ if (step.kind === 'address') {
179
+ return /*#__PURE__*/ _jsxs(Stack, {
180
+ spacing: 1.5,
181
+ "data-marketplace-pay": "address",
182
+ children: [
183
+ /*#__PURE__*/ _jsx(Typography, {
184
+ variant: "subtitle2",
185
+ children: 'Add a billing address'
186
+ }),
187
+ /*#__PURE__*/ _jsx(Typography, {
188
+ variant: "body2",
189
+ color: "text.secondary",
190
+ children: 'Sales tax is calculated from it. It stays on file for this workspace, in Billing.'
191
+ }),
192
+ failure,
193
+ /*#__PURE__*/ _jsx(Suspense, {
194
+ fallback: /*#__PURE__*/ _jsx(FormLoading, {}),
195
+ children: /*#__PURE__*/ _jsx(LazyBillingAddressForm, {
196
+ onConfirmed: onAddressSaved,
197
+ onCancel: onCancel
198
+ })
199
+ })
200
+ ]
201
+ });
202
+ }
203
+ return /*#__PURE__*/ _jsxs(Stack, {
204
+ spacing: 1.5,
205
+ "data-marketplace-pay": "ask-billing",
206
+ children: [
207
+ step.amountCents === null ? null : /*#__PURE__*/ _jsx(SummaryLine, {
208
+ label: "Price",
209
+ value: formatPayCents(step.amountCents)
210
+ }),
211
+ /*#__PURE__*/ _jsx(PrerequisiteNotice, {
212
+ severity: "warning",
213
+ children: `${step.need === 'card_required' ? 'This workspace needs a card on file to buy this.' : 'This workspace needs a billing address to buy this: sales tax is calculated from it.'} Someone with the "${orgPermissionLabel('billing.manage')}" permission can add it in Billing.`
214
+ }),
215
+ /*#__PURE__*/ _jsx(Stack, {
216
+ direction: "row",
217
+ children: /*#__PURE__*/ _jsx(Button, {
218
+ size: "small",
219
+ onClick: onCancel,
220
+ children: 'Close'
221
+ })
222
+ })
223
+ ]
224
+ });
225
+ }
226
+ export default MarketplacePayPanel;
227
+
228
+ //# sourceMappingURL=marketplace-pay-panel.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/components/marketplace-pay-panel.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\n'use client'\n\nimport { orgPermissionLabel } from '@aglyn/aglyn/app-utils/org-permissions'\nimport { PrerequisiteNotice } from '@aglyn/shared-ui-jsx/components/prerequisite-notice.component'\nimport type { BillingAddressValue } from '@aglyn/shared-ui-jsx/stripe/billing-address-form.component'\nimport { LazyBillingAddressForm, LazyBillingCardForm } from '@aglyn/shared-ui-jsx/stripe/lazy-stripe'\nimport { Alert, Button, CircularProgress, Divider, Stack, Typography } from '@mui/material'\nimport { Suspense } from 'react'\nimport {\n formatPayCents,\n payCardLabel,\n type PayPrerequisite,\n type PayQuote,\n} from '../model/marketplace-pay'\n\n/** Which part of paying for a listing is on screen. */\nexport type PayStep =\n | { kind: 'confirm'; quote: PayQuote }\n /** A card is needed, and this person can add one: `null` until its form has a secret. */\n | { kind: 'card'; clientSecret: string | null }\n | { kind: 'address' }\n /** Something is needed that this person cannot add. */\n | { kind: 'ask-billing'; need: PayPrerequisite; amountCents: number | null }\n\nexport interface MarketplacePayPanelProps {\n step: PayStep\n listingName: string\n busy: boolean\n /** Stripe's reason, or ours, for the last thing that did not go through. */\n error: string | null\n /** The workspace's Billing page, when its address is known. */\n billingHref?: string | null\n onPay: () => void\n onCardSaved: (setupIntentId: string) => Promise<void> | void\n onAddressSaved: (address: BillingAddressValue) => Promise<void> | void\n onCancel: () => void\n}\n\nconst SUMMARY_LINE_SX = { justifyContent: 'space-between' } as const\n\nfunction SummaryLine(props: { label: string; value: string; strong?: boolean }) {\n const variant = props.strong ? 'subtitle2' : 'body2'\n return (\n <Stack direction=\"row\" spacing={2} sx={SUMMARY_LINE_SX}>\n <Typography variant={variant}>{props.label}</Typography>\n <Typography variant={variant}>{props.value}</Typography>\n </Stack>\n )\n}\n\nconst FormLoading = () => <CircularProgress size={24} aria-label=\"Loading the card form\" />\n\n/**\n * Paying for a listing, in place (AGL-4049).\n *\n * Inline, under the button that asked for it, in the listing's sidebar and in\n * Create site alike, for the reason the billing card form is inline: a payment\n * surface that appears over the page and looks like a different product is a\n * reason to stop buying. Nothing here is a Dialog, and the card and address\n * fields are Stripe's own, so the card data guarantee is the billing page's.\n *\n * The total is on screen before the Pay button is: a saved card charged\n * without one is not a purchase anybody agreed to.\n *\n * Figma: \"Aglyn Console (web)\" → page \"Marketplace · Publish & review\" →\n * section \"✅ CURRENT · Paying in the console\", and page \"Sites · Create site\"\n * → frames \"Choose your starter · Buy (card on file)\" and \"· Buy (add a card)\".\n */\nexport function MarketplacePayPanel(props: MarketplacePayPanelProps) {\n const { step, listingName, busy, error, billingHref, onPay, onCardSaved, onAddressSaved, onCancel } =\n props\n const failure = error ? (\n <Alert severity=\"warning\" data-marketplace-pay-error>\n {error}\n </Alert>\n ) : null\n\n if (step.kind === 'confirm') {\n const { quote } = step\n return (\n <Stack spacing={1.5} data-marketplace-pay=\"confirm\">\n <Typography variant=\"subtitle2\">{`Buy ${quote.listingName}`}</Typography>\n <Stack spacing={0.5}>\n <SummaryLine label=\"Price\" value={formatPayCents(quote.amountCents)} />\n <SummaryLine label=\"Sales tax\" value={formatPayCents(quote.taxCents)} />\n <Divider />\n <SummaryLine label=\"Total\" value={formatPayCents(quote.totalCents)} strong />\n </Stack>\n {quote.canPay ? (\n <>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`Charged to ${payCardLabel(quote.card)}. The receipt lands in Billing.`}\n </Typography>\n {/* A card that will not pay is changed in Billing: the way there is beside the reason. */}\n {error ? (\n <PrerequisiteNotice severity=\"warning\" href={billingHref ?? undefined} actionLabel=\"Open Billing\">\n {error}\n </PrerequisiteNotice>\n ) : null}\n <Stack direction=\"row\" spacing={1}>\n <Button variant=\"contained\" size=\"small\" disabled={busy} onClick={onPay}>\n {busy ? 'Paying…' : `Pay ${formatPayCents(quote.totalCents)}`}\n </Button>\n <Button size=\"small\" disabled={busy} onClick={onCancel}>\n {'Cancel'}\n </Button>\n </Stack>\n </>\n ) : (\n <>\n <PrerequisiteNotice severity=\"warning\">\n {`Buying this charges your workspace's card, which takes the \"${orgPermissionLabel('billing.manage')}\" permission. Ask someone who manages billing to buy it.`}\n </PrerequisiteNotice>\n <Stack direction=\"row\">\n <Button size=\"small\" onClick={onCancel}>\n {'Close'}\n </Button>\n </Stack>\n </>\n )}\n </Stack>\n )\n }\n\n if (step.kind === 'card') {\n return (\n <Stack spacing={1.5} data-marketplace-pay=\"card\">\n <Typography variant=\"subtitle2\">{`Add a card to buy ${listingName}`}</Typography>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'It stays on file for this workspace, in Billing, where you can change or remove it.'}\n </Typography>\n {failure}\n <Suspense fallback={<FormLoading />}>\n {step.clientSecret ? (\n <LazyBillingCardForm\n clientSecret={step.clientSecret}\n onConfirmed={onCardSaved}\n onCancel={onCancel}\n />\n ) : (\n <FormLoading />\n )}\n </Suspense>\n </Stack>\n )\n }\n\n if (step.kind === 'address') {\n return (\n <Stack spacing={1.5} data-marketplace-pay=\"address\">\n <Typography variant=\"subtitle2\">{'Add a billing address'}</Typography>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Sales tax is calculated from it. It stays on file for this workspace, in Billing.'}\n </Typography>\n {failure}\n <Suspense fallback={<FormLoading />}>\n <LazyBillingAddressForm onConfirmed={onAddressSaved} onCancel={onCancel} />\n </Suspense>\n </Stack>\n )\n }\n\n return (\n <Stack spacing={1.5} data-marketplace-pay=\"ask-billing\">\n {step.amountCents === null ? null : (\n <SummaryLine label=\"Price\" value={formatPayCents(step.amountCents)} />\n )}\n <PrerequisiteNotice severity=\"warning\">\n {`${\n step.need === 'card_required'\n ? 'This workspace needs a card on file to buy this.'\n : 'This workspace needs a billing address to buy this: sales tax is calculated from it.'\n } Someone with the \"${orgPermissionLabel('billing.manage')}\" permission can add it in Billing.`}\n </PrerequisiteNotice>\n <Stack direction=\"row\">\n <Button size=\"small\" onClick={onCancel}>\n {'Close'}\n </Button>\n </Stack>\n </Stack>\n )\n}\n\nexport default MarketplacePayPanel\n"],"names":["orgPermissionLabel","PrerequisiteNotice","LazyBillingAddressForm","LazyBillingCardForm","Alert","Button","CircularProgress","Divider","Stack","Typography","Suspense","formatPayCents","payCardLabel","SUMMARY_LINE_SX","justifyContent","SummaryLine","props","variant","strong","direction","spacing","sx","label","value","FormLoading","size","aria-label","MarketplacePayPanel","step","listingName","busy","error","billingHref","onPay","onCardSaved","onAddressSaved","onCancel","failure","severity","data-marketplace-pay-error","kind","quote","data-marketplace-pay","amountCents","taxCents","totalCents","canPay","color","card","href","undefined","actionLabel","disabled","onClick","fallback","clientSecret","onConfirmed","need"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;AAEA,SAASA,kBAAkB,QAAQ,yCAAwC;AAC3E,SAASC,kBAAkB,QAAQ,gEAA+D;AAElG,SAASC,sBAAsB,EAAEC,mBAAmB,QAAQ,0CAAyC;AACrG,SAASC,KAAK,EAAEC,MAAM,EAAEC,gBAAgB,EAAEC,OAAO,EAAEC,KAAK,EAAEC,UAAU,QAAQ,gBAAe;AAC3F,SAASC,QAAQ,QAAQ,QAAO;AAChC,SACEC,cAAc,EACdC,YAAY,QAGP,8BAA0B;AAyBjC,MAAMC,kBAAkB;IAAEC,gBAAgB;AAAgB;AAE1D,SAASC,YAAYC,KAAyD;IAC5E,MAAMC,UAAUD,MAAME,MAAM,GAAG,cAAc;IAC7C,qBACE,MAACV;QAAMW,WAAU;QAAMC,SAAS;QAAGC,IAAIR;;0BACrC,KAACJ;gBAAWQ,SAASA;0BAAUD,MAAMM,KAAK;;0BAC1C,KAACb;gBAAWQ,SAASA;0BAAUD,MAAMO,KAAK;;;;AAGhD;AAEA,MAAMC,cAAc,kBAAM,KAAClB;QAAiBmB,MAAM;QAAIC,cAAW;;AAEjE;;;;;;;;;;;;;;;CAeC,GACD,OAAO,SAASC,oBAAoBX,KAA+B;IACjE,MAAM,EAAEY,IAAI,EAAEC,WAAW,EAAEC,IAAI,EAAEC,KAAK,EAAEC,WAAW,EAAEC,KAAK,EAAEC,WAAW,EAAEC,cAAc,EAAEC,QAAQ,EAAE,GACjGpB;IACF,MAAMqB,UAAUN,sBACd,KAAC3B;QAAMkC,UAAS;QAAUC,4BAA0B;kBACjDR;SAED;IAEJ,IAAIH,KAAKY,IAAI,KAAK,WAAW;QAC3B,MAAM,EAAEC,KAAK,EAAE,GAAGb;QAClB,qBACE,MAACpB;YAAMY,SAAS;YAAKsB,wBAAqB;;8BACxC,KAACjC;oBAAWQ,SAAQ;8BAAa,CAAC,IAAI,EAAEwB,MAAMZ,WAAW,EAAE;;8BAC3D,MAACrB;oBAAMY,SAAS;;sCACd,KAACL;4BAAYO,OAAM;4BAAQC,OAAOZ,eAAe8B,MAAME,WAAW;;sCAClE,KAAC5B;4BAAYO,OAAM;4BAAYC,OAAOZ,eAAe8B,MAAMG,QAAQ;;sCACnE,KAACrC;sCACD,KAACQ;4BAAYO,OAAM;4BAAQC,OAAOZ,eAAe8B,MAAMI,UAAU;4BAAG3B,MAAM;;;;gBAE3EuB,MAAMK,MAAM,iBACX;;sCACE,KAACrC;4BAAWQ,SAAQ;4BAAQ8B,OAAM;sCAC/B,CAAC,WAAW,EAAEnC,aAAa6B,MAAMO,IAAI,EAAE,+BAA+B,CAAC;;wBAGzEjB,sBACC,KAAC9B;4BAAmBqC,UAAS;4BAAUW,IAAI,EAAEjB,sBAAAA,cAAekB;4BAAWC,aAAY;sCAChFpB;6BAED;sCACJ,MAACvB;4BAAMW,WAAU;4BAAMC,SAAS;;8CAC9B,KAACf;oCAAOY,SAAQ;oCAAYQ,MAAK;oCAAQ2B,UAAUtB;oCAAMuB,SAASpB;8CAC/DH,OAAO,YAAY,CAAC,IAAI,EAAEnB,eAAe8B,MAAMI,UAAU,GAAG;;8CAE/D,KAACxC;oCAAOoB,MAAK;oCAAQ2B,UAAUtB;oCAAMuB,SAASjB;8CAC3C;;;;;mCAKP;;sCACE,KAACnC;4BAAmBqC,UAAS;sCAC1B,CAAC,4DAA4D,EAAEtC,mBAAmB,kBAAkB,wDAAwD,CAAC;;sCAEhK,KAACQ;4BAAMW,WAAU;sCACf,cAAA,KAACd;gCAAOoB,MAAK;gCAAQ4B,SAASjB;0CAC3B;;;;;;;IAOf;IAEA,IAAIR,KAAKY,IAAI,KAAK,QAAQ;QACxB,qBACE,MAAChC;YAAMY,SAAS;YAAKsB,wBAAqB;;8BACxC,KAACjC;oBAAWQ,SAAQ;8BAAa,CAAC,kBAAkB,EAAEY,aAAa;;8BACnE,KAACpB;oBAAWQ,SAAQ;oBAAQ8B,OAAM;8BAC/B;;gBAEFV;8BACD,KAAC3B;oBAAS4C,wBAAU,KAAC9B;8BAClBI,KAAK2B,YAAY,iBAChB,KAACpD;wBACCoD,cAAc3B,KAAK2B,YAAY;wBAC/BC,aAAatB;wBACbE,UAAUA;uCAGZ,KAACZ;;;;IAKX;IAEA,IAAII,KAAKY,IAAI,KAAK,WAAW;QAC3B,qBACE,MAAChC;YAAMY,SAAS;YAAKsB,wBAAqB;;8BACxC,KAACjC;oBAAWQ,SAAQ;8BAAa;;8BACjC,KAACR;oBAAWQ,SAAQ;oBAAQ8B,OAAM;8BAC/B;;gBAEFV;8BACD,KAAC3B;oBAAS4C,wBAAU,KAAC9B;8BACnB,cAAA,KAACtB;wBAAuBsD,aAAarB;wBAAgBC,UAAUA;;;;;IAIvE;IAEA,qBACE,MAAC5B;QAAMY,SAAS;QAAKsB,wBAAqB;;YACvCd,KAAKe,WAAW,KAAK,OAAO,qBAC3B,KAAC5B;gBAAYO,OAAM;gBAAQC,OAAOZ,eAAeiB,KAAKe,WAAW;;0BAEnE,KAAC1C;gBAAmBqC,UAAS;0BAC1B,GACCV,KAAK6B,IAAI,KAAK,kBACV,qDACA,uFACL,mBAAmB,EAAEzD,mBAAmB,kBAAkB,mCAAmC,CAAC;;0BAEjG,KAACQ;gBAAMW,WAAU;0BACf,cAAA,KAACd;oBAAOoB,MAAK;oBAAQ4B,SAASjB;8BAC3B;;;;;AAKX;AAEA,eAAeT,oBAAmB"}
@@ -14,7 +14,7 @@ import type { ConsoleArtifactPublishZoneProps } from '@aglyn/aglyn';
14
14
  * with no widget on that zone leaves the offer out entirely, which is why
15
15
  * this may safely draw nothing for a kind it does not sell.
16
16
  */
17
- export declare function PublishArtifactDialog({ artifact, onClose, }: ConsoleArtifactPublishZoneProps): import("react").JSX.Element;
17
+ export declare function PublishArtifactDialog(props: ConsoleArtifactPublishZoneProps): import("react").JSX.Element;
18
18
  export declare namespace PublishArtifactDialog {
19
19
  var displayName: string;
20
20
  }
@@ -18,11 +18,16 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
18
18
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
19
19
  import { isBelowMarketplacePriceFloor, marketplacePriceCostNote, marketplacePriceFloorHint } from "../model/listing-price-floor.js";
20
20
  import { useSnackbar } from "@aglyn/shared-ui-snackstack";
21
+ import { BlockedControl } from "@aglyn/shared-ui-jsx/components/blocked-control.component";
22
+ import { PrerequisiteNotice } from "@aglyn/shared-ui-jsx/components/prerequisite-notice.component";
21
23
  import { useUser } from "@aglyn/tenant-feature-instance";
22
24
  import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
23
- import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Stack, TextField, Typography } from "@mui/material";
25
+ import { Alert, Button, Dialog, DialogActions, DialogContent, DialogTitle, Stack, TextField, Typography } from "@mui/material";
24
26
  import { useCallback, useEffect, useMemo, useState } from "react";
27
+ import { useStarterPublishFacts } from "../hooks/use-starter-publish-facts.js";
28
+ import { starterPublishBody, starterPublishSteps, starterRefusalLink } from "../model/starter-publish.js";
25
29
  import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publisher-agreement-checkbox.component.js";
30
+ import { PublishStarterFields } from "./publish-starter-fields.component.js";
26
31
  /**
27
32
  * WHERE EACH KIND GOES, which is the knowledge that used to sit in the app
28
33
  * (AGL-3080).
@@ -114,6 +119,17 @@ import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publ
114
119
  },
115
120
  noun: 'email starter'
116
121
  };
122
+ // A whole site, as a site starter people create a new site from (AGL-4049).
123
+ case 'siteStarter':
124
+ return {
125
+ endpoint: 'marketplace/publish-starter',
126
+ payload: {
127
+ hostId
128
+ },
129
+ noun: 'starter',
130
+ categoryLabel: 'What kind of site is it?',
131
+ categoryPlaceholder: 'e.g. Bakery, Law firm, Wedding'
132
+ };
117
133
  default:
118
134
  return null;
119
135
  }
@@ -132,8 +148,30 @@ import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publ
132
148
  * publish keeps the control that opens it and never imports this. A page
133
149
  * with no widget on that zone leaves the offer out entirely, which is why
134
150
  * this may safely draw nothing for a kind it does not sell.
135
- */ export function PublishArtifactDialog({ artifact, onClose }) {
136
- var _ref, _ref1, _ref2, _marketplacePriceCostNote;
151
+ */ export function PublishArtifactDialog(props) {
152
+ var _props_artifact;
153
+ return ((_props_artifact = props.artifact) == null ? void 0 : _props_artifact.kind) === 'siteStarter' ? /*#__PURE__*/ _jsx(PublishStarterDialog, _extends({}, props)) : /*#__PURE__*/ _jsx(PublishArtifactForm, _extends({}, props, {
154
+ starterReads: null
155
+ }));
156
+ }
157
+ PublishArtifactDialog.displayName = 'PublishArtifactDialog';
158
+ /**
159
+ * The form for a site starter (AGL-4049), with what it reads before the
160
+ * click: the site's theme and pages, the org's publisher profile and plan.
161
+ * Its own component so no other kind ever issues those reads.
162
+ */ function PublishStarterDialog(props) {
163
+ var _props_artifact, _props_artifact1;
164
+ const reads = useStarterPublishFacts({
165
+ hostId: (_props_artifact = props.artifact) == null ? void 0 : _props_artifact.hostId,
166
+ orgId: (_props_artifact1 = props.artifact) == null ? void 0 : _props_artifact1.orgId
167
+ });
168
+ return /*#__PURE__*/ _jsx(PublishArtifactForm, _extends({}, props, {
169
+ starterReads: reads
170
+ }));
171
+ }
172
+ /** The listing form every kind shares, with a starter's half when it has one. */ function PublishArtifactForm({ artifact, onClose, starterReads }) {
173
+ var _ref, _ref1, _ref2, _ref3, _marketplacePriceCostNote, _starterRefusalLink_href, _ref4;
174
+ var _steps_;
137
175
  // Memoized because it is a dependency of the publish callback: rebuilt
138
176
  // every render, it would rebuild that callback every render too.
139
177
  const target = useMemo(()=>artifact ? publishRequestFor(artifact) : null, [
@@ -150,6 +188,27 @@ import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publ
150
188
  // above the button, unticked for every artifact the dialog opens on.
151
189
  const agreement = usePublisherAgreementConsent();
152
190
  const { reset: resetAgreement } = agreement;
191
+ /*
192
+ * A SITE STARTER'S OWN HALF (AGL-4049). Its theme shape is the
193
+ * publisher's choice and starts unchosen; what it captures and every setup
194
+ * step in its way are read before the click, so they are said with where
195
+ * each is fixed rather than refused after it. For any other kind the facts
196
+ * hook is handed no site and reads nothing.
197
+ */ const starter = !!starterReads && !!target;
198
+ const [themeChoice, setThemeChoice] = useState(null);
199
+ const [styleKind, setStyleKind] = useState('');
200
+ // What the door last refused, in its words, shown in the form to fix it.
201
+ const [refusal, setRefusal] = useState(null);
202
+ const starterFacts = starterReads ? _extends({}, starterReads.facts, {
203
+ priceUsd: Number(price) || 0
204
+ }) : null;
205
+ const steps = starter && starterFacts ? starterPublishSteps(starterFacts) : [];
206
+ const starterBody = starter && starterReads ? starterPublishBody({
207
+ choice: themeChoice,
208
+ builtin: starterReads.builtin,
209
+ kind: styleKind || null
210
+ }) : null;
211
+ const agreementRefused = refusal && (refusal.status === 428 || refusal.status === 409);
153
212
  useEffect(()=>{
154
213
  var _artifact_displayName, _artifact_description;
155
214
  if (!artifact) return;
@@ -157,6 +216,9 @@ import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publ
157
216
  setDescription((_artifact_description = artifact.description) != null ? _artifact_description : '');
158
217
  setCategory('');
159
218
  setPrice('');
219
+ setThemeChoice(null);
220
+ setStyleKind('');
221
+ setRefusal(null);
160
222
  resetAgreement();
161
223
  }, [
162
224
  artifact,
@@ -164,7 +226,9 @@ import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publ
164
226
  ]);
165
227
  const handlePublish = useCallback(async ()=>{
166
228
  if (!target || !name.trim() || busy || !agreement.consent) return;
229
+ if (starter && (!starterBody || steps.length)) return;
167
230
  setBusy(true);
231
+ setRefusal(null);
168
232
  try {
169
233
  const response = await authorizedFetch(user, `/api/${target.endpoint}`, {
170
234
  method: 'POST',
@@ -177,9 +241,24 @@ import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publ
177
241
  category: category.trim(),
178
242
  priceUsd: Number(price) || 0,
179
243
  agreement: agreement.consent
180
- }))
244
+ }, starterBody))
181
245
  });
182
246
  const payload = await response.json().catch(()=>({}));
247
+ if (!response.ok && starter) {
248
+ // In the form, in the door's words, so the publisher can fix it
249
+ // there: another theme, a page, a setup step. Every problem a
250
+ // theme check names is listed, not only the first.
251
+ const error = typeof (payload == null ? void 0 : payload.error) === 'string' && payload.error ? payload.error : 'Publish failed';
252
+ const more = Array.isArray(payload == null ? void 0 : payload.errors) ? payload.errors.map((entry)=>entry == null ? void 0 : entry.message).filter((message)=>typeof message === 'string' && message !== error) : [];
253
+ setRefusal({
254
+ status: response.status,
255
+ error,
256
+ more
257
+ });
258
+ // An agreement refused is asked for again, by a fresh tick.
259
+ if (response.status === 428 || response.status === 409) resetAgreement();
260
+ return;
261
+ }
183
262
  if (!response.ok) {
184
263
  var _ref;
185
264
  // 412 means a setup step is missing (publisher profile, payouts) —
@@ -189,7 +268,7 @@ import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publ
189
268
  allowDuplicate: true
190
269
  });
191
270
  }
192
- enqueueSnackbar(`Published v${payload.version} to the marketplace`, {
271
+ enqueueSnackbar(starter ? Number(payload.version) > 1 ? `Published v${payload.version} of your starter` : 'Sent your starter for review. It is listed once it has been reviewed.' : `Published v${payload.version} to the marketplace`, {
193
272
  variant: 'success',
194
273
  persist: false
195
274
  });
@@ -216,7 +295,10 @@ import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publ
216
295
  enqueueSnackbar,
217
296
  onClose,
218
297
  agreement.consent,
219
- resetAgreement
298
+ resetAgreement,
299
+ starter,
300
+ starterBody,
301
+ steps.length
220
302
  ]);
221
303
  if (artifact && !target) {
222
304
  return /*#__PURE__*/ _jsxs(Dialog, {
@@ -249,11 +331,11 @@ import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publ
249
331
  children: /*#__PURE__*/ _jsxs(Dialog, {
250
332
  open: !!target,
251
333
  onClose: busy ? undefined : onClose,
252
- maxWidth: "xs",
334
+ maxWidth: starter ? 'sm' : 'xs',
253
335
  fullWidth: true,
254
336
  children: [
255
337
  /*#__PURE__*/ _jsx(DialogTitle, {
256
- children: `Publish ${(_ref = target == null ? void 0 : target.noun) != null ? _ref : 'artifact'}`
338
+ children: starter ? 'Publish as a starter' : `Publish ${(_ref = target == null ? void 0 : target.noun) != null ? _ref : 'artifact'}`
257
339
  }),
258
340
  /*#__PURE__*/ _jsx(DialogContent, {
259
341
  children: /*#__PURE__*/ _jsxs(Stack, {
@@ -265,7 +347,7 @@ import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publ
265
347
  /*#__PURE__*/ _jsx(Typography, {
266
348
  variant: "body2",
267
349
  color: "text.secondary",
268
- children: `Publishes the current published version of this ` + `${(_ref1 = target == null ? void 0 : target.noun) != null ? _ref1 : 'artifact'} so other organizations can ` + 'install it. Your site is unaffected.'
350
+ children: starter ? 'Publishes this site as a site starter: a ready-made website ' + 'people create a new site from. A new starter is reviewed ' + 'before anyone else can see it. Your site is unaffected.' : `Publishes the current published version of this ` + `${(_ref1 = target == null ? void 0 : target.noun) != null ? _ref1 : 'artifact'} so other organizations can ` + 'install it. Your site is unaffected.'
269
351
  }),
270
352
  /*#__PURE__*/ _jsx(TextField, {
271
353
  autoFocus: true,
@@ -288,8 +370,8 @@ import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publ
288
370
  }),
289
371
  /*#__PURE__*/ _jsx(TextField, {
290
372
  size: "small",
291
- label: "Category",
292
- placeholder: (_ref2 = target == null ? void 0 : target.categoryPlaceholder) != null ? _ref2 : 'e.g. Marketing, Docs',
373
+ label: (_ref2 = target == null ? void 0 : target.categoryLabel) != null ? _ref2 : 'Category',
374
+ placeholder: (_ref3 = target == null ? void 0 : target.categoryPlaceholder) != null ? _ref3 : 'e.g. Marketing, Docs',
293
375
  value: category,
294
376
  onChange: (event)=>setCategory(event.target.value),
295
377
  disabled: busy,
@@ -312,10 +394,48 @@ import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publ
312
394
  disabled: busy,
313
395
  fullWidth: true
314
396
  }),
397
+ starter && starterReads ? /*#__PURE__*/ _jsx(PublishStarterFields, {
398
+ builtin: starterReads.builtin,
399
+ hostReady: starterReads.hostReady,
400
+ pages: starterReads.facts.pages,
401
+ steps: steps,
402
+ choice: themeChoice,
403
+ onChoiceChange: setThemeChoice,
404
+ styleKind: styleKind,
405
+ onStyleKindChange: setStyleKind,
406
+ disabled: busy
407
+ }) : null,
408
+ refusal && !agreementRefused ? refusal.status === 412 && starterFacts ? /*#__PURE__*/ _jsx(PrerequisiteNotice, {
409
+ severity: "warning",
410
+ href: (_starterRefusalLink_href = starterRefusalLink(starterFacts).href) != null ? _starterRefusalLink_href : undefined,
411
+ actionLabel: starterRefusalLink(starterFacts).actionLabel,
412
+ children: refusal.error
413
+ }) : /*#__PURE__*/ _jsxs(Alert, {
414
+ severity: "error",
415
+ "data-starter-publish": "refusal",
416
+ children: [
417
+ refusal.error,
418
+ refusal.more.length ? /*#__PURE__*/ _jsx(Stack, {
419
+ component: "ul",
420
+ spacing: 0.5,
421
+ sx: {
422
+ m: 0,
423
+ mt: 1,
424
+ pl: 2.5
425
+ },
426
+ children: refusal.more.map((message)=>/*#__PURE__*/ _jsx(Typography, {
427
+ component: "li",
428
+ variant: "body2",
429
+ children: message
430
+ }, message))
431
+ }) : null
432
+ ]
433
+ }) : null,
315
434
  /*#__PURE__*/ _jsx(PublisherAgreementCheckbox, {
316
435
  checked: agreement.agreed,
317
436
  onChange: agreement.setAgreed,
318
- disabled: busy
437
+ disabled: busy,
438
+ error: agreementRefused ? refusal.error : null
319
439
  })
320
440
  ]
321
441
  })
@@ -328,13 +448,17 @@ import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publ
328
448
  disabled: busy,
329
449
  children: 'Cancel'
330
450
  }),
331
- /*#__PURE__*/ _jsx(Button, {
332
- size: "small",
333
- variant: "contained",
334
- color: "primary",
335
- disabled: busy || !name.trim() || isBelowMarketplacePriceFloor(price) || !agreement.agreed,
336
- onClick: ()=>void handlePublish(),
337
- children: busy ? 'Publishing…' : 'Publish'
451
+ /*#__PURE__*/ _jsx(BlockedControl, {
452
+ blocked: steps.length > 0,
453
+ reason: (_ref4 = (_steps_ = steps[0]) == null ? void 0 : _steps_.text) != null ? _ref4 : '',
454
+ children: /*#__PURE__*/ _jsx(Button, {
455
+ size: "small",
456
+ variant: "contained",
457
+ color: "primary",
458
+ disabled: busy || !name.trim() || isBelowMarketplacePriceFloor(price) || !agreement.agreed || starter && !starterBody,
459
+ onClick: ()=>void handlePublish(),
460
+ children: busy ? 'Publishing…' : 'Publish'
461
+ })
338
462
  })
339
463
  ]
340
464
  })
@@ -342,7 +466,7 @@ import { PublisherAgreementCheckbox, usePublisherAgreementConsent } from "./publ
342
466
  })
343
467
  });
344
468
  }
345
- PublishArtifactDialog.displayName = 'PublishArtifactDialog';
469
+ PublishArtifactForm.displayName = 'PublishArtifactForm';
346
470
  export default PublishArtifactDialog;
347
471
 
348
472
  //# sourceMappingURL=publish-artifact-dialog.component.js.map