@burdenoff/fluidgrids-fe-sdk 2026.1112.8 → 2026.1112.9

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 (43) hide show
  1. package/dist/{AiStudioPage-CtgPSPyc.js → AiStudioPage-DfoV1Olc.js} +1 -1
  2. package/dist/ApprovalInboxPage-Bb8H9ruw.js +1317 -0
  3. package/dist/{DataTablesPage-2xTLe_jk.js → DataTablesPage-Zz23QZQp.js} +3 -1
  4. package/dist/Disclosure-DQiUKrqd.js +41 -0
  5. package/dist/{ExecutionDetailPage-CL-w9c3L.js → ExecutionDetailPage-CcUxFexZ.js} +3 -2
  6. package/dist/{ExecutionsListPage-Bf6Cvsnz.js → ExecutionsListPage-JpByw6nA.js} +3 -1
  7. package/dist/{MissingNodesInstallModal-BCbhddk4.js → MissingNodesInstallModal-olEc52p2.js} +1 -1
  8. package/dist/{OpenTemplateAsCodeButton-BgvgDaVe.js → OpenTemplateAsCodeButton-Dh3ee2OR.js} +1 -1
  9. package/dist/PaidTemplateConfirm-DjmVi_m-.js +28 -0
  10. package/dist/{RunActionsMenu-DmO14hEE.js → RunActionsMenu-BE_1r3bF.js} +1 -50
  11. package/dist/{RunnersPage-CvAPHdfU.js → RunnersPage-CAt4YDhB.js} +2 -1
  12. package/dist/TechnicalDetails-D4xGy201.js +19 -0
  13. package/dist/{TemplateCard-XBc0qEA4.js → TemplateCard--WYJZlA_.js} +81 -25
  14. package/dist/{TemplateConfigurationModal-Dl_7RaCt.js → TemplateConfigurationModal-cd0-QVMZ.js} +2 -2
  15. package/dist/{TemplateDetailPanel-0Cc6jguU.js → TemplateDetailPanel-C-2JuXg6.js} +1 -1
  16. package/dist/TemplatePreview-BCnGjMuN.js +646 -0
  17. package/dist/{TemplatesPage-wClKZLO4.js → TemplatesPage-u7bXJYfv.js} +375 -136
  18. package/dist/{VariablesPage-BtoLjmUA.js → VariablesPage-CPL34WBc.js} +2 -358
  19. package/dist/{WorkflowBuilder-qRGFtXJG.js → WorkflowBuilder-BWxBmBoP.js} +2 -2
  20. package/dist/{WorkflowBuilder-CK6c0eRp.js → WorkflowBuilder-DxAAPHsn.js} +3 -3
  21. package/dist/{agentTools-BkQsycAp.js → agentTools-JHtYGgd7.js} +2 -2
  22. package/dist/{canvasNoteTools-U7j1z7GR.js → canvasNoteTools-B2ouyIbj.js} +1 -1
  23. package/dist/{HumanRequestCard-lbWDpWd7.js → channel-CZ70oI81.js} +5 -228
  24. package/dist/executions.js +2 -2
  25. package/dist/{flow-builder-9jDNwkID.js → flow-builder-DzKPrW2r.js} +33 -24
  26. package/dist/{index-rj-TznII.d.ts → index-CGCAcRKo.d.ts} +3 -1
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.js +19 -19
  29. package/dist/{node-detail-view-C1yupyvL.js → node-detail-view-DNilUGcx.js} +2 -2
  30. package/dist/{node-editor-tab-body-BtxSQPtX.js → node-editor-tab-body-XBedxkpN.js} +1 -1
  31. package/dist/observability.d.ts +1 -1
  32. package/dist/{popover-BaYffpTw.js → popover-BC4r84K0.js} +1 -1
  33. package/dist/{quick-config-panel-BvlhLiQp.js → quick-config-panel-BPmrhIOb.js} +2 -2
  34. package/dist/{schedule-panel-D5VdzW2c.js → schedule-panel-DJN1TDQH.js} +2 -2
  35. package/dist/{sidebar-node-editor-BU4rJwvm.js → sidebar-node-editor-DKdfcd2r.js} +2 -2
  36. package/dist/templates.js +2 -2
  37. package/dist/useVariables-cI8uLwye.js +361 -0
  38. package/dist/workflow-builder.js +2 -2
  39. package/dist/workflow-pages.d.ts +1 -1
  40. package/dist/workflow-pages.js +10 -10
  41. package/package.json +1 -1
  42. package/dist/ApprovalInboxPage-QAJim81n.js +0 -559
  43. package/dist/TemplatePreview-CRLUX5yI.js +0 -240
@@ -10,7 +10,9 @@ import { i as SdkPermissionButton, s as useFluidGridsPermission, t as FLUIDGRIDS
10
10
  import { t as FluidGridsDocsLink } from "./FluidGridsDocsLink-JxkBpOeb.js";
11
11
  import { n as useNavigationV2 } from "./useNavigationV2-C2WeqN7d.js";
12
12
  import { t as ConfirmActionDialog } from "./ConfirmActionDialog-D9Pir3bc.js";
13
- import { n as TechnicalDetails, r as Disclosure, t as RunActionsMenu } from "./RunActionsMenu-DmO14hEE.js";
13
+ import { t as Disclosure } from "./Disclosure-DQiUKrqd.js";
14
+ import { t as RunActionsMenu } from "./RunActionsMenu-BE_1r3bF.js";
15
+ import { t as TechnicalDetails } from "./TechnicalDetails-D4xGy201.js";
14
16
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
15
17
  import { useNavigate } from "react-router";
16
18
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -0,0 +1,41 @@
1
+ "use client";
2
+ import { useId, useState } from "react";
3
+ import { Icon } from "@iconify/react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+
6
+ // src/modules/executions/components/Disclosure.tsx
7
+ /**
8
+ * A one-button disclosure for the Runs pages (BOFF-11846): "More filters",
9
+ * "Show technical details". Local stand-in for BOFF-11841's shared "More
10
+ * options" / "Show technical details" pieces; `TechnicalDetails` and the Runs
11
+ * filters build on it.
12
+ *
13
+ * The content is rendered only while open (closed inputs are not focusable).
14
+ * Whatever the content edits lives in the Runs store, so closing never loses a
15
+ * value, and callers open it from the start when a value inside is set.
16
+ */
17
+ function Disclosure({ closedLabel, openLabel, children, defaultOpen = false, className, "data-testid": testId }) {
18
+ const [open, setOpen] = useState(defaultOpen);
19
+ const panelId = useId();
20
+ return /* @__PURE__ */ jsxs("div", {
21
+ className,
22
+ "data-testid": testId,
23
+ children: [/* @__PURE__ */ jsxs("button", {
24
+ type: "button",
25
+ onClick: () => setOpen((current) => !current),
26
+ "aria-expanded": open,
27
+ "aria-controls": panelId,
28
+ className: "inline-flex items-center gap-1 text-sm text-text-secondary hover:text-text-primary",
29
+ children: [/* @__PURE__ */ jsx(Icon, {
30
+ icon: open ? "mdi:chevron-down" : "mdi:chevron-right",
31
+ width: 16
32
+ }), open ? openLabel : closedLabel]
33
+ }), open && /* @__PURE__ */ jsx("div", {
34
+ id: panelId,
35
+ className: "mt-2",
36
+ children
37
+ })]
38
+ });
39
+ }
40
+
41
+ export { Disclosure as t };
@@ -7,13 +7,14 @@ import { s as isAgentNodeType } from "./agent-form-Bfvm32j1.js";
7
7
  import { An as runSignalTargets, Dn as durableInterfaceOf, I as describeRunError, L as describeRunStep, Tn as canSignalRun, dn as runDurationMs, ln as formatElapsedMs, un as nodeStateDurationMs } from "./FluidGridsProvider-TQ-aDPtn.js";
8
8
  import { n as useFgAskable, r as useFgAskableSelection } from "./askAboutBridge-BV8m95kk.js";
9
9
  import { n as useNavigationV2 } from "./useNavigationV2-C2WeqN7d.js";
10
- import { n as TechnicalDetails, t as RunActionsMenu } from "./RunActionsMenu-DmO14hEE.js";
10
+ import { t as TechnicalDetails } from "./TechnicalDetails-D4xGy201.js";
11
11
  import { _ as shortRunId, g as runChainLinks, h as parseMetadataDefinition, m as overrideRequestOf, n as useExecution, p as callbackTone, r as useExecutionActions, s as buildRetryTriggerInput, t as useAutoRefresh } from "./useExecutions-BbkBSYpS.js";
12
+ import { t as RunActionsMenu } from "./RunActionsMenu-BE_1r3bF.js";
12
13
  import { _ as throwIfResultError, m as describeOperationError, n as getFluidGridsClient, r as getFluidGridsClientSafe, x as getFluidGridsConfig } from "./client-C9XSzSXr.js";
13
14
  import { Cn as RunLogsDocument, Qr as WorkflowRunHierarchyDocument, ft as ExplainRunDocument, o as AgentStepUpdatedDocument, pn as RunAiUsageDocument, s as AgentTraceDocument, xn as RunLogAppendedDocument } from "./graphql-operation-types-DZVhCBEi.js";
14
15
  import { i as SdkPermissionButton, s as useFluidGridsPermission, t as FLUIDGRIDS_PERMISSIONS } from "./constants-dcxg6zG6.js";
15
16
  import { t as EntityTagPicker } from "./EntityTagPicker-CuZAMby_.js";
16
- import { i as useRecipientLabel, n as channelLabel, r as ApprovalApprovers } from "./HumanRequestCard-lbWDpWd7.js";
17
+ import { a as useRecipientLabel, n as ApprovalApprovers, t as channelLabel } from "./channel-CZ70oI81.js";
17
18
  import { r as useRunHumanRequests } from "./useHumanRequests-ZiR0sSzS.js";
18
19
  import { a as encodedPayloadBytes, f as EffectBadge, h as useRunPolicyDecisions, i as decodePayloads, l as formatBudgetUsd, n as checkCodecServerUrl, o as isEncodedPayload, r as containsEncodedPayload, t as CodecServerError } from "./codec-client-CJ95Rmqo.js";
19
20
  import { n as useWorkflowProposal, o as canSaveRunAsTestCase, r as saveRunAsTestCase, t as WorkflowProposalCard } from "./WorkflowProposalCard-BvmJ5ea8.js";
@@ -9,11 +9,13 @@ import { t as executionsControls } from "./pageControlSpecs-DZJ9K37m.js";
9
9
  import { t as TagFilterSelect } from "./TagFilterSelect-DcusTt1p.js";
10
10
  import { n as useNavigationV2 } from "./useNavigationV2-C2WeqN7d.js";
11
11
  import { a as useRunStatusCounts, c as errorAdvice, f as runStatusLabels, o as ConfirmStopRunDialog, p as RUN_STATUS_CONFIG, s as ADVICE_ERROR_TYPES, u as ExecutionStatusBadge } from "./useDurableParity-B3h8jqP0.js";
12
- import { n as TechnicalDetails, r as Disclosure, t as RunActionsMenu } from "./RunActionsMenu-DmO14hEE.js";
12
+ import { t as Disclosure } from "./Disclosure-DQiUKrqd.js";
13
13
  import { n as formatRunVersion } from "./run-display-BycKYSU0.js";
14
14
  import { dn as runDurationMs, ln as formatElapsedMs } from "./FluidGridsProvider-TQ-aDPtn.js";
15
15
  import { r as useRunHumanRequests } from "./useHumanRequests-ZiR0sSzS.js";
16
16
  import { n as runListLinkKey, t as runListFilterFromSearch } from "./run-list-links-eUhZB1ju.js";
17
+ import { t as TechnicalDetails } from "./TechnicalDetails-D4xGy201.js";
18
+ import { t as RunActionsMenu } from "./RunActionsMenu-BE_1r3bF.js";
17
19
  import { h as useWorkflowDefinitions } from "./useWorkflows-CRUlQBd3.js";
18
20
  import { t as FluidGridsDocsLink } from "./FluidGridsDocsLink-JxkBpOeb.js";
19
21
  import { s as useFluidGridsPermission, t as FLUIDGRIDS_PERMISSIONS } from "./constants-dcxg6zG6.js";
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { a as DialogFooter, i as DialogDescription, l as DialogTitle, o as DialogHeader, r as DialogContent, t as Dialog } from "./dialog-Cjb4lB4D.js";
3
3
  import { t as Button } from "./button-DG7y_FVJ.js";
4
- import { r as Badge } from "./TemplateCard-XBc0qEA4.js";
4
+ import { a as Badge } from "./TemplateCard--WYJZlA_.js";
5
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
6
  import { AlertTriangle, CheckCircle2, Download, ExternalLink, Loader2, Puzzle, ShoppingCart } from "lucide-react";
7
7
 
@@ -3,7 +3,7 @@ import { h as usePhaseDFlags } from "./feature-flags-B_b8PJ6Z.js";
3
3
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
4
4
  import { m as describeOperationError } from "./client-C9XSzSXr.js";
5
5
  import { t as downloadBlob } from "./workflow-transfer-CQnQC-ke.js";
6
- import { d as readTemplateCode, u as buildTemplateCodeDownload } from "./TemplateCard-XBc0qEA4.js";
6
+ import { f as buildTemplateCodeDownload, p as readTemplateCode } from "./TemplateCard--WYJZlA_.js";
7
7
  import { useState } from "react";
8
8
  import { Icon } from "@iconify/react";
9
9
  import { cn } from "@burdenoff/fe-libs/utils";
@@ -0,0 +1,28 @@
1
+ "use client";
2
+ import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
3
+ import { n as formatTemplatePrice } from "./TemplateCard--WYJZlA_.js";
4
+ import { t as ConfirmActionDialog } from "./ConfirmActionDialog-D9Pir3bc.js";
5
+ import { jsx } from "react/jsx-runtime";
6
+
7
+ // src/modules/templates/components/PaidTemplateConfirm.tsx
8
+ function PaidTemplateConfirm({ template, onConfirm, onCancel }) {
9
+ const tr = useTr();
10
+ const price = template ? formatTemplatePrice(template.price, template.currency) : "";
11
+ return /* @__PURE__ */ jsx(ConfirmActionDialog, {
12
+ open: template !== null,
13
+ title: tr("fluidgrids.templates.templatesPage.paidConfirmTitle", "Use a paid template?"),
14
+ description: tr("fluidgrids.templates.templatesPage.paidConfirmDescription", "\"{{name}}\" costs {{price}}. Using it adds a copy to your workspace that you can change.", {
15
+ name: template?.name ?? "",
16
+ price
17
+ }),
18
+ confirmLabel: tr("fluidgrids.templates.templatesPage.paidConfirmAction", "Use for {{price}}", { price }),
19
+ cancelLabel: tr("fluidgrids.templates.templatesPage.paidConfirmCancel", "Not now"),
20
+ onConfirm,
21
+ onOpenChange: (open) => {
22
+ if (!open) onCancel();
23
+ },
24
+ "data-testid": "paid-template-confirm"
25
+ });
26
+ }
27
+
28
+ export { PaidTemplateConfirm as t };
@@ -1,59 +1,10 @@
1
1
  "use client";
2
2
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
3
- import { useId, useState } from "react";
4
3
  import { Icon } from "@iconify/react";
5
4
  import { jsx, jsxs } from "react/jsx-runtime";
6
5
  import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@burdenoff/fe-libs/ui";
7
6
  import { Button as Button$1 } from "@burdenoff/fe-libs/button";
8
7
 
9
- // src/modules/executions/components/Disclosure.tsx
10
- /**
11
- * A one-button disclosure for the Runs pages (BOFF-11846): "More filters",
12
- * "Show technical details". Local stand-in for BOFF-11841's shared "More
13
- * options" / "Show technical details" pieces; `TechnicalDetails` and the Runs
14
- * filters build on it.
15
- *
16
- * The content is rendered only while open (closed inputs are not focusable).
17
- * Whatever the content edits lives in the Runs store, so closing never loses a
18
- * value, and callers open it from the start when a value inside is set.
19
- */
20
- function Disclosure({ closedLabel, openLabel, children, defaultOpen = false, className, "data-testid": testId }) {
21
- const [open, setOpen] = useState(defaultOpen);
22
- const panelId = useId();
23
- return /* @__PURE__ */ jsxs("div", {
24
- className,
25
- "data-testid": testId,
26
- children: [/* @__PURE__ */ jsxs("button", {
27
- type: "button",
28
- onClick: () => setOpen((current) => !current),
29
- "aria-expanded": open,
30
- "aria-controls": panelId,
31
- className: "inline-flex items-center gap-1 text-sm text-text-secondary hover:text-text-primary",
32
- children: [/* @__PURE__ */ jsx(Icon, {
33
- icon: open ? "mdi:chevron-down" : "mdi:chevron-right",
34
- width: 16
35
- }), open ? openLabel : closedLabel]
36
- }), open && /* @__PURE__ */ jsx("div", {
37
- id: panelId,
38
- className: "mt-2",
39
- children
40
- })]
41
- });
42
- }
43
-
44
- // src/modules/executions/components/TechnicalDetails.tsx
45
- function TechnicalDetails({ children, defaultOpen, className, "data-testid": testId }) {
46
- const tr = useTr();
47
- return /* @__PURE__ */ jsx(Disclosure, {
48
- closedLabel: tr("fluidgrids.executions.technicalDetails.show", "Show technical details"),
49
- openLabel: tr("fluidgrids.executions.technicalDetails.hide", "Hide technical details"),
50
- defaultOpen,
51
- className,
52
- "data-testid": testId,
53
- children
54
- });
55
- }
56
-
57
8
  // src/modules/executions/components/RunActionsMenu.tsx
58
9
  /**
59
10
  * The "⋯" menu of a run's or row's extra actions (BOFF-11846): Pause,
@@ -103,4 +54,4 @@ function RunActionsMenu({ items, toggles = [], label, "data-testid": testId = "r
103
54
  })] });
104
55
  }
105
56
 
106
- export { TechnicalDetails as n, Disclosure as r, RunActionsMenu as t };
57
+ export { RunActionsMenu as t };
@@ -7,7 +7,8 @@ import { a as useRunners, i as useRunnerActions, r as runnerInstallCommand, t as
7
7
  import { t as FluidGridsDocsLink } from "./FluidGridsDocsLink-JxkBpOeb.js";
8
8
  import { t as ConfirmActionDialog } from "./ConfirmActionDialog-D9Pir3bc.js";
9
9
  import { n as useNavigationV2 } from "./useNavigationV2-C2WeqN7d.js";
10
- import { n as TechnicalDetails, t as RunActionsMenu } from "./RunActionsMenu-DmO14hEE.js";
10
+ import { t as RunActionsMenu } from "./RunActionsMenu-BE_1r3bF.js";
11
+ import { t as TechnicalDetails } from "./TechnicalDetails-D4xGy201.js";
11
12
  import { useCallback, useRef, useState } from "react";
12
13
  import { Icon } from "@iconify/react";
13
14
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -0,0 +1,19 @@
1
+ "use client";
2
+ import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
3
+ import { t as Disclosure } from "./Disclosure-DQiUKrqd.js";
4
+ import { jsx } from "react/jsx-runtime";
5
+
6
+ // src/modules/executions/components/TechnicalDetails.tsx
7
+ function TechnicalDetails({ children, defaultOpen, className, "data-testid": testId }) {
8
+ const tr = useTr();
9
+ return /* @__PURE__ */ jsx(Disclosure, {
10
+ closedLabel: tr("fluidgrids.executions.technicalDetails.show", "Show technical details"),
11
+ openLabel: tr("fluidgrids.executions.technicalDetails.hide", "Hide technical details"),
12
+ defaultOpen,
13
+ className,
14
+ "data-testid": testId,
15
+ children
16
+ });
17
+ }
18
+
19
+ export { TechnicalDetails as t };
@@ -10,6 +10,7 @@ import { t as cn } from "./cn-QqidFIgr.js";
10
10
  import { t as Button } from "./button-DG7y_FVJ.js";
11
11
  import { b as utf8Length } from "./workflow-code-transfer-Cshsgf2H.js";
12
12
  import { i as SdkPermissionButton, t as FLUIDGRIDS_PERMISSIONS } from "./constants-dcxg6zG6.js";
13
+ import { n as useNavigationV2 } from "./useNavigationV2-C2WeqN7d.js";
13
14
  import React, { Suspense, forwardRef, lazy, useCallback, useContext, useMemo, useState } from "react";
14
15
  import { useQuery } from "@apollo/client/react";
15
16
  import { gql } from "@apollo/client/core";
@@ -1281,7 +1282,7 @@ async function dismissToastWhenShown(id) {
1281
1282
  }
1282
1283
 
1283
1284
  // src/hooks/store/useTemplateImportFlow.tsx
1284
- const LazyTemplateConfigurationModal = lazy(() => import("./TemplateConfigurationModal-Dl_7RaCt.js").then((m) => ({ default: m.TemplateConfigurationModal })));
1285
+ const LazyTemplateConfigurationModal = lazy(() => import("./TemplateConfigurationModal-cd0-QVMZ.js").then((m) => ({ default: m.TemplateConfigurationModal })));
1285
1286
  /**
1286
1287
  * "Use this template", the same everywhere it is offered: the builder's
1287
1288
  * template panel, the Templates page and the template preview page
@@ -1340,10 +1341,10 @@ function useTemplateImportFlow({ onImported, onQuotaExhausted }) {
1340
1341
  if (result.success && result.workflow) {
1341
1342
  toast.success(tr("fluidgrids.builder.desktopSidebar.workflowCreatedToast", "Workflow created from template!"), {
1342
1343
  id: "template-import",
1343
- description: `"${result.workflow.name}" is ready to edit`
1344
+ description: tr("fluidgrids.pages.templatePreview.importSuccessDescription", "\"{{name}}\" is ready to edit", { name: result.workflow.name })
1344
1345
  });
1345
1346
  if ((content.requiredCredentialTypes?.length ?? 0) > 0) toast.info(tr("fluidgrids.builder.desktopSidebar.credentialsNeededToast", "Credentials needed"), {
1346
- description: `Configure ${content.requiredCredentialTypes?.join(", ")} in the Credentials page`,
1347
+ description: tr("fluidgrids.builder.desktopSidebar.credentialsNeededDescription", "Configure {{types}} in the Credentials page", { types: (content.requiredCredentialTypes ?? []).join(", ") }),
1347
1348
  duration: 6e3
1348
1349
  });
1349
1350
  onImported(result.workflow);
@@ -1487,12 +1488,78 @@ function templatePreview(template) {
1487
1488
  };
1488
1489
  }
1489
1490
 
1491
+ // src/utils/template-price.ts
1492
+ /**
1493
+ * The price shown on a store template card and in the preview.
1494
+ *
1495
+ * USD (and a template with no currency) keeps the plain "$12" form the cards
1496
+ * have always shown; any other currency is written with its own symbol, so a
1497
+ * template priced in rupees or euros is not shown with a dollar sign.
1498
+ */
1499
+ const formatters = /* @__PURE__ */ new Map();
1500
+ function formatterFor(currency) {
1501
+ const cached = formatters.get(currency);
1502
+ if (cached) return cached;
1503
+ try {
1504
+ const created = new Intl.NumberFormat(void 0, {
1505
+ style: "currency",
1506
+ currency,
1507
+ maximumFractionDigits: 2
1508
+ });
1509
+ formatters.set(currency, created);
1510
+ return created;
1511
+ } catch {
1512
+ return null;
1513
+ }
1514
+ }
1515
+ function formatTemplatePrice(price, currency) {
1516
+ const code = currency?.trim().toUpperCase() || "USD";
1517
+ if (code === "USD") return `$${price?.toString() || "0"}`;
1518
+ const formatter = formatterFor(code);
1519
+ return formatter ? formatter.format(price ?? 0) : `${price?.toString() || "0"} ${code}`;
1520
+ }
1521
+ /**
1522
+ * A template that costs money and has not been bought yet: "Use this
1523
+ * template" asks first, naming the price (Navigation v2, BOFF-11848).
1524
+ */
1525
+ function isPaidTemplate(template) {
1526
+ return !!template.pricingModel && template.pricingModel !== "FREE" && (template.price ?? 0) > 0 && template.isPurchased !== true;
1527
+ }
1528
+
1490
1529
  // src/builder/components/flow-builder/components/templates/TemplateCard.tsx
1491
1530
  function formatNumber(count) {
1492
1531
  if (count >= 1e6) return `${(count / 1e6).toFixed(1)}M`;
1493
1532
  if (count >= 1e3) return `${(count / 1e3).toFixed(1)}k`;
1494
1533
  return count.toString();
1495
1534
  }
1535
+ function PriceBadge({ template }) {
1536
+ const tr = useTr();
1537
+ return template.pricingModel === "FREE" ? /* @__PURE__ */ jsx(Badge, {
1538
+ variant: "secondary",
1539
+ className: "bg-status-success-bg text-action-primary-text border-0",
1540
+ children: tr("fluidgrids.builder.templateCard.freeBadge", "Free")
1541
+ }) : /* @__PURE__ */ jsx(Badge, {
1542
+ variant: "default",
1543
+ className: "bg-status-info-bg text-action-primary-text border-0",
1544
+ children: formatTemplatePrice(template.price, template.currency)
1545
+ });
1546
+ }
1547
+ /** Downloads and views (today's card; Navigation v2 shows them on the preview). */
1548
+ function UsageCounts({ template }) {
1549
+ const tr = useTr();
1550
+ return /* @__PURE__ */ jsxs("div", {
1551
+ className: "flex items-center gap-3",
1552
+ children: [/* @__PURE__ */ jsxs("div", {
1553
+ className: "flex items-center gap-1",
1554
+ title: tr("fluidgrids.builder.templateCard.downloadsTooltip", "Downloads"),
1555
+ children: [/* @__PURE__ */ jsx(Download, { className: "size-3" }), /* @__PURE__ */ jsx("span", { children: formatNumber(template.downloads || 0) })]
1556
+ }), /* @__PURE__ */ jsxs("div", {
1557
+ className: "flex items-center gap-1",
1558
+ title: tr("fluidgrids.builder.templateCard.viewsTooltip", "Views"),
1559
+ children: [/* @__PURE__ */ jsx(Eye, { className: "size-3" }), /* @__PURE__ */ jsx("span", { children: formatNumber(template.viewCount || 0) })]
1560
+ })]
1561
+ });
1562
+ }
1496
1563
  /**
1497
1564
  * Template card component inspired by ComfyUI's template showcase
1498
1565
  * Features:
@@ -1502,9 +1569,14 @@ function formatNumber(count) {
1502
1569
  * - Stats (downloads, views, rating)
1503
1570
  * - Featured badge
1504
1571
  * - Category/tags
1572
+ *
1573
+ * Navigation v2 (BOFF-11848, the Templates gallery only): the download and
1574
+ * view counts move to the template preview. The builder's template picker
1575
+ * turns the switch off for its cards (see TemplatesGrid), so it stays as is.
1505
1576
  */
1506
1577
  function TemplateCard({ template, onClick, onUseTemplate }) {
1507
1578
  const tr = useTr();
1579
+ const v2 = useNavigationV2();
1508
1580
  const [imageError, setImageError] = React.useState(false);
1509
1581
  const preview = templatePreview(template);
1510
1582
  const previewImage = preview.kind === "image" ? preview.src : void 0;
@@ -1547,15 +1619,7 @@ function TemplateCard({ template, onClick, onUseTemplate }) {
1547
1619
  }),
1548
1620
  /* @__PURE__ */ jsx("div", {
1549
1621
  className: "absolute top-2 left-2",
1550
- children: template.pricingModel === "FREE" ? /* @__PURE__ */ jsx(Badge, {
1551
- variant: "secondary",
1552
- className: "bg-status-success-bg text-action-primary-text border-0",
1553
- children: tr("fluidgrids.builder.templateCard.freeBadge", "Free")
1554
- }) : /* @__PURE__ */ jsxs(Badge, {
1555
- variant: "default",
1556
- className: "bg-status-info-bg text-action-primary-text border-0",
1557
- children: ["$", template.price?.toString() || "0"]
1558
- })
1622
+ children: /* @__PURE__ */ jsx(PriceBadge, { template })
1559
1623
  }),
1560
1624
  /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-bg-overlay via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300" })
1561
1625
  ]
@@ -1578,6 +1642,9 @@ function TemplateCard({ template, onClick, onUseTemplate }) {
1578
1642
  }), template.publisher?.isVerified && /* @__PURE__ */ jsx(Badge, {
1579
1643
  variant: "secondary",
1580
1644
  className: "text-xs px-1.5 py-0",
1645
+ role: "img",
1646
+ "aria-label": tr("fluidgrids.builder.templateCard.verifiedLabel", "Verified publisher"),
1647
+ title: tr("fluidgrids.builder.templateCard.verifiedLabel", "Verified publisher"),
1581
1648
  children: "✓"
1582
1649
  })]
1583
1650
  }),
@@ -1603,18 +1670,7 @@ function TemplateCard({ template, onClick, onUseTemplate }) {
1603
1670
  })
1604
1671
  ]
1605
1672
  })
1606
- }), /* @__PURE__ */ jsxs("div", {
1607
- className: "flex items-center gap-3",
1608
- children: [/* @__PURE__ */ jsxs("div", {
1609
- className: "flex items-center gap-1",
1610
- title: tr("fluidgrids.builder.templateCard.downloadsTooltip", "Downloads"),
1611
- children: [/* @__PURE__ */ jsx(Download, { className: "size-3" }), /* @__PURE__ */ jsx("span", { children: formatNumber(template.downloads || 0) })]
1612
- }), /* @__PURE__ */ jsxs("div", {
1613
- className: "flex items-center gap-1",
1614
- title: tr("fluidgrids.builder.templateCard.viewsTooltip", "Views"),
1615
- children: [/* @__PURE__ */ jsx(Eye, { className: "size-3" }), /* @__PURE__ */ jsx("span", { children: formatNumber(template.viewCount || 0) })]
1616
- })]
1617
- })]
1673
+ }), !v2 && /* @__PURE__ */ jsx(UsageCounts, { template })]
1618
1674
  }),
1619
1675
  (template.category || template.tags?.length > 0) && /* @__PURE__ */ jsxs("div", {
1620
1676
  className: "flex flex-wrap gap-1",
@@ -1651,4 +1707,4 @@ function TemplateCard({ template, onClick, onUseTemplate }) {
1651
1707
  });
1652
1708
  }
1653
1709
 
1654
- export { WORKFLOW_TEST_NODE_TYPES as A, CardContent as C, CardTitle as D, CardHeader as E, isDurableFunctionNodeType as M, isNodeTypeHiddenFromPalette as N, DURABLE_FUNCTION_NODE_TYPES as O, isRunControlNodeType as P, Card as S, CardFooter as T, isStoreNodeUpdateAvailable as _, useTemplateImportFlow as a, useInstalledNodes as b, getWorkflowNodeTypes as c, readTemplateCode as d, useWorkflowTemplates as f, getStoreNodeType as g, getStoreNodeIcon as h, badgeVariants as i, filterPaletteNodes as j, RUN_CONTROL_NODE_TYPES as k, useImportWorkflowTemplate as l, getStoreNodeAvailability as m, templatePreview as n, buildNodeCheck as o, filterStoreNodesForPalette as p, Badge as r, buildRequiredNodeTypes as s, TemplateCard as t, buildTemplateCodeDownload as u, storeNodeDisplayVersion as v, CardDescription as w, useGlobalStoreClient as x, storeNodeInstallVersion as y };
1710
+ export { DURABLE_FUNCTION_NODE_TYPES as A, useGlobalStoreClient as C, CardFooter as D, CardDescription as E, isNodeTypeHiddenFromPalette as F, isRunControlNodeType as I, WORKFLOW_TEST_NODE_TYPES as M, filterPaletteNodes as N, CardHeader as O, isDurableFunctionNodeType as P, useInstalledNodes as S, CardContent as T, getStoreNodeIcon as _, Badge as a, storeNodeDisplayVersion as b, buildNodeCheck as c, useImportWorkflowTemplate as d, buildTemplateCodeDownload as f, getStoreNodeAvailability as g, filterStoreNodesForPalette as h, templatePreview as i, RUN_CONTROL_NODE_TYPES as j, CardTitle as k, buildRequiredNodeTypes as l, useWorkflowTemplates as m, formatTemplatePrice as n, badgeVariants as o, readTemplateCode as p, isPaidTemplate as r, useTemplateImportFlow as s, TemplateCard as t, getWorkflowNodeTypes as u, getStoreNodeType as v, Card as w, storeNodeInstallVersion as x, isStoreNodeUpdateAvailable as y };
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import { a as DialogFooter, d as Input, i as DialogDescription, l as DialogTitle, o as DialogHeader, r as DialogContent, t as Dialog } from "./dialog-Cjb4lB4D.js";
3
3
  import { t as Button } from "./button-DG7y_FVJ.js";
4
- import { r as Badge } from "./TemplateCard-XBc0qEA4.js";
4
+ import { a as Badge } from "./TemplateCard--WYJZlA_.js";
5
5
  import { t as Label } from "./label-CDy86rIZ.js";
6
6
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
7
- import { t as OpenTemplateAsCodeButton } from "./OpenTemplateAsCodeButton-BgvgDaVe.js";
7
+ import { t as OpenTemplateAsCodeButton } from "./OpenTemplateAsCodeButton-Dh3ee2OR.js";
8
8
  import { useEffect, useMemo, useState } from "react";
9
9
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
10
  import { AlertTriangle, CheckCircle2, Download, ExternalLink, KeyRound, Loader2, ShoppingCart, Sparkles } from "lucide-react";
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { t as Button } from "./button-DG7y_FVJ.js";
3
- import { n as templatePreview, r as Badge } from "./TemplateCard-XBc0qEA4.js";
3
+ import { a as Badge, i as templatePreview } from "./TemplateCard--WYJZlA_.js";
4
4
  import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
5
5
  import { i as SdkPermissionButton, t as FLUIDGRIDS_PERMISSIONS } from "./constants-dcxg6zG6.js";
6
6
  import { Icon } from "@iconify/react";