@wildo-ai/presets-components 1.1.5 → 1.1.7
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/dist/esm/.native.tsbuildinfo +1 -0
- package/dist/esm/components/actions/action-bar.d.ts.map +1 -1
- package/dist/esm/components/actions/action-bar.js +5 -2
- package/dist/esm/components/actions/action-bar.js.map +1 -1
- package/dist/esm/components/ai-elements/chat/suggestion.d.ts.map +1 -1
- package/dist/esm/components/ai-elements/chat/suggestion.js +8 -1
- package/dist/esm/components/ai-elements/chat/suggestion.js.map +1 -1
- package/dist/esm/components/ai-elements/decision/approval.d.ts +108 -13
- package/dist/esm/components/ai-elements/decision/approval.d.ts.map +1 -1
- package/dist/esm/components/ai-elements/decision/approval.js +60 -10
- package/dist/esm/components/ai-elements/decision/approval.js.map +1 -1
- package/dist/esm/components/ai-elements/graph/graph-runtime.d.ts +3 -1
- package/dist/esm/components/ai-elements/graph/graph-runtime.d.ts.map +1 -1
- package/dist/esm/components/ai-elements/graph/graph-runtime.js +3 -1
- package/dist/esm/components/ai-elements/graph/graph-runtime.js.map +1 -1
- package/dist/esm/components/app/app-layout-main-container.d.ts +9 -0
- package/dist/esm/components/app/app-layout-main-container.d.ts.map +1 -1
- package/dist/esm/components/app/app-layout-main-container.js +17 -23
- package/dist/esm/components/app/app-layout-main-container.js.map +1 -1
- package/dist/esm/components/app/app-layout-main-container.labels.d.ts.map +1 -1
- package/dist/esm/components/app/app-layout-main-container.labels.js +27 -0
- package/dist/esm/components/app/app-layout-main-container.labels.js.map +1 -1
- package/dist/esm/components/billing/billing-plan-change-preview.d.ts.map +1 -1
- package/dist/esm/components/billing/billing-plan-change-preview.js +5 -2
- package/dist/esm/components/billing/billing-plan-change-preview.js.map +1 -1
- package/dist/esm/components/billing/billing-plan-change-preview.labels.d.ts.map +1 -1
- package/dist/esm/components/billing/billing-plan-change-preview.labels.js +3 -0
- package/dist/esm/components/billing/billing-plan-change-preview.labels.js.map +1 -1
- package/dist/esm/components/billing/billing-pricing-table.d.ts +1 -1
- package/dist/esm/components/billing/billing-pricing-table.d.ts.map +1 -1
- package/dist/esm/components/billing/billing-pricing-table.js +8 -4
- package/dist/esm/components/billing/billing-pricing-table.js.map +1 -1
- package/dist/esm/components/billing/billing-pricing-table.labels.d.ts.map +1 -1
- package/dist/esm/components/billing/billing-pricing-table.labels.js +7 -1
- package/dist/esm/components/billing/billing-pricing-table.labels.js.map +1 -1
- package/dist/esm/components/billing/billing-usage-dashboard.d.ts.map +1 -1
- package/dist/esm/components/billing/billing-usage-dashboard.js +6 -3
- package/dist/esm/components/billing/billing-usage-dashboard.js.map +1 -1
- package/dist/esm/components/billing/billing-usage-dashboard.labels.d.ts.map +1 -1
- package/dist/esm/components/billing/billing-usage-dashboard.labels.js +2 -1
- package/dist/esm/components/billing/billing-usage-dashboard.labels.js.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-enum.d.ts.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-enum.js +18 -4
- package/dist/esm/components/data-display/formatters/display-field-enum.js.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-file.d.ts.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-file.js +13 -14
- package/dist/esm/components/data-display/formatters/display-field-file.js.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-file.labels.d.ts.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-file.labels.js +1 -0
- package/dist/esm/components/data-display/formatters/display-field-file.labels.js.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-number.d.ts.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-number.js +6 -1
- package/dist/esm/components/data-display/formatters/display-field-number.js.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-number.labels.d.ts.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-number.labels.js +5 -2
- package/dist/esm/components/data-display/formatters/display-field-number.labels.js.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-string.d.ts +1 -1
- package/dist/esm/components/data-display/formatters/display-field-string.d.ts.map +1 -1
- package/dist/esm/components/data-display/formatters/display-field-string.js +51 -12
- package/dist/esm/components/data-display/formatters/display-field-string.js.map +1 -1
- package/dist/esm/components/data-display/untrusted-html-content.d.ts +55 -0
- package/dist/esm/components/data-display/untrusted-html-content.d.ts.map +1 -0
- package/dist/esm/components/data-display/untrusted-html-content.js +67 -0
- package/dist/esm/components/data-display/untrusted-html-content.js.map +1 -0
- package/dist/esm/components/form/chromes/form-primitive.labels.d.ts.map +1 -1
- package/dist/esm/components/form/chromes/form-primitive.labels.js +9 -0
- package/dist/esm/components/form/chromes/form-primitive.labels.js.map +1 -1
- package/dist/esm/components/form/combobox.d.ts.map +1 -1
- package/dist/esm/components/form/combobox.js +10 -10
- package/dist/esm/components/form/combobox.js.map +1 -1
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.adapter.d.ts +42 -0
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.adapter.d.ts.map +1 -0
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.adapter.js +120 -0
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.adapter.js.map +1 -0
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.d.ts +16 -0
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.d.ts.map +1 -0
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.js +8 -0
- package/dist/esm/components/form/controls/address/providers/google-places-address-lookup.js.map +1 -0
- package/dist/esm/components/navigation/app-level/activity-bar.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/activity-bar.js +2 -2
- package/dist/esm/components/navigation/app-level/activity-bar.js.map +1 -1
- package/dist/esm/components/navigation/app-level/menu-user-org.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/menu-user-org.js +10 -4
- package/dist/esm/components/navigation/app-level/menu-user-org.js.map +1 -1
- package/dist/esm/components/navigation/app-level/menu-user-org.labels.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/menu-user-org.labels.js +7 -0
- package/dist/esm/components/navigation/app-level/menu-user-org.labels.js.map +1 -1
- package/dist/esm/components/navigation/app-level/menubar.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/menubar.js +6 -6
- package/dist/esm/components/navigation/app-level/menubar.js.map +1 -1
- package/dist/esm/components/navigation/app-level/navigation-back.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/navigation-back.js +27 -9
- package/dist/esm/components/navigation/app-level/navigation-back.js.map +1 -1
- package/dist/esm/components/navigation/app-level/sidebar.js +3 -3
- package/dist/esm/components/navigation/app-level/sidebar.js.map +1 -1
- package/dist/esm/components/navigation/app-level/status-bar.js +2 -2
- package/dist/esm/components/navigation/app-level/status-bar.js.map +1 -1
- package/dist/esm/components/navigation/app-level/toolbar.d.ts.map +1 -1
- package/dist/esm/components/navigation/app-level/toolbar.js +2 -2
- package/dist/esm/components/navigation/app-level/toolbar.js.map +1 -1
- package/dist/esm/components/navigation/app-level/utility-panel.js +2 -2
- package/dist/esm/components/navigation/app-level/utility-panel.js.map +1 -1
- package/dist/esm/components/navigation/breadcrumb.js +1 -1
- package/dist/esm/components/navigation/breadcrumb.js.map +1 -1
- package/dist/esm/components/sections/stepper.d.ts.map +1 -1
- package/dist/esm/components/sections/stepper.js +5 -3
- package/dist/esm/components/sections/stepper.js.map +1 -1
- package/dist/esm/config/preset-navigation.d.ts.map +1 -1
- package/dist/esm/config/preset-navigation.js +23 -2
- package/dist/esm/config/preset-navigation.js.map +1 -1
- package/dist/esm/config/resources/agent-work.resource-presets.d.ts +4 -0
- package/dist/esm/config/resources/agent-work.resource-presets.d.ts.map +1 -0
- package/dist/esm/config/resources/agent-work.resource-presets.js +115 -0
- package/dist/esm/config/resources/agent-work.resource-presets.js.map +1 -0
- package/dist/esm/config/resources/api-key-rotation-window.d.ts +22 -0
- package/dist/esm/config/resources/api-key-rotation-window.d.ts.map +1 -0
- package/dist/esm/config/resources/api-key-rotation-window.js +45 -0
- package/dist/esm/config/resources/api-key-rotation-window.js.map +1 -0
- package/dist/esm/config/resources/application.resource-presets.d.ts.map +1 -1
- package/dist/esm/config/resources/application.resource-presets.js +147 -61
- package/dist/esm/config/resources/application.resource-presets.js.map +1 -1
- package/dist/esm/config/resources/billing.resource-presets.d.ts +4 -3
- package/dist/esm/config/resources/billing.resource-presets.d.ts.map +1 -1
- package/dist/esm/config/resources/billing.resource-presets.js +240 -111
- package/dist/esm/config/resources/billing.resource-presets.js.map +1 -1
- package/dist/esm/config/resources/conversation-threads.resource-presets.d.ts +4 -0
- package/dist/esm/config/resources/conversation-threads.resource-presets.d.ts.map +1 -0
- package/dist/esm/config/resources/conversation-threads.resource-presets.js +105 -0
- package/dist/esm/config/resources/conversation-threads.resource-presets.js.map +1 -0
- package/dist/esm/config/resources/guidance.resource-presets.d.ts.map +1 -1
- package/dist/esm/config/resources/guidance.resource-presets.js +18 -11
- package/dist/esm/config/resources/guidance.resource-presets.js.map +1 -1
- package/dist/esm/config/resources/identity.resource-presets.d.ts +0 -13
- package/dist/esm/config/resources/identity.resource-presets.d.ts.map +1 -1
- package/dist/esm/config/resources/identity.resource-presets.js +48 -16
- package/dist/esm/config/resources/identity.resource-presets.js.map +1 -1
- package/dist/esm/config/resources/inbound-deliveries.resource-presets.d.ts +6 -0
- package/dist/esm/config/resources/inbound-deliveries.resource-presets.d.ts.map +1 -0
- package/dist/esm/config/resources/inbound-deliveries.resource-presets.js +112 -0
- package/dist/esm/config/resources/inbound-deliveries.resource-presets.js.map +1 -0
- package/dist/esm/config/resources/inbound-email.resource-presets.d.ts +4 -0
- package/dist/esm/config/resources/inbound-email.resource-presets.d.ts.map +1 -0
- package/dist/esm/config/resources/inbound-email.resource-presets.js +182 -0
- package/dist/esm/config/resources/inbound-email.resource-presets.js.map +1 -0
- package/dist/esm/config/resources/index.d.ts.map +1 -1
- package/dist/esm/config/resources/index.js +9 -2
- package/dist/esm/config/resources/index.js.map +1 -1
- package/dist/esm/config/resources/legal-holds.resource-presets.d.ts +4 -0
- package/dist/esm/config/resources/legal-holds.resource-presets.d.ts.map +1 -0
- package/dist/esm/config/resources/legal-holds.resource-presets.js +76 -0
- package/dist/esm/config/resources/legal-holds.resource-presets.js.map +1 -0
- package/dist/esm/config/resources/organizations.resource-presets.d.ts.map +1 -1
- package/dist/esm/config/resources/organizations.resource-presets.js +139 -36
- package/dist/esm/config/resources/organizations.resource-presets.js.map +1 -1
- package/dist/esm/config/resources/resource.config.utils.d.ts +20 -0
- package/dist/esm/config/resources/resource.config.utils.d.ts.map +1 -1
- package/dist/esm/config/resources/resource.config.utils.js +20 -0
- package/dist/esm/config/resources/resource.config.utils.js.map +1 -1
- package/dist/esm/config/resources/retention-enforcement.resource-presets.d.ts +5 -0
- package/dist/esm/config/resources/retention-enforcement.resource-presets.d.ts.map +1 -0
- package/dist/esm/config/resources/retention-enforcement.resource-presets.js +74 -0
- package/dist/esm/config/resources/retention-enforcement.resource-presets.js.map +1 -0
- package/dist/esm/config/resources/security.resource-presets.d.ts +3 -1
- package/dist/esm/config/resources/security.resource-presets.d.ts.map +1 -1
- package/dist/esm/config/resources/security.resource-presets.js +563 -133
- package/dist/esm/config/resources/security.resource-presets.js.map +1 -1
- package/dist/esm/config/resources/service-providers.resource-presets.d.ts +4 -0
- package/dist/esm/config/resources/service-providers.resource-presets.d.ts.map +1 -0
- package/dist/esm/config/resources/service-providers.resource-presets.js +321 -0
- package/dist/esm/config/resources/service-providers.resource-presets.js.map +1 -0
- package/dist/esm/config/resources/webhooks.resource-presets.d.ts +4 -3
- package/dist/esm/config/resources/webhooks.resource-presets.d.ts.map +1 -1
- package/dist/esm/config/resources/webhooks.resource-presets.js +76 -25
- package/dist/esm/config/resources/webhooks.resource-presets.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/registration/register-common-enums.d.ts.map +1 -1
- package/dist/esm/registration/register-common-enums.js +15 -0
- package/dist/esm/registration/register-common-enums.js.map +1 -1
- package/dist/esm/registration/register-provider-components.d.ts.map +1 -1
- package/dist/esm/registration/register-provider-components.js +6 -0
- package/dist/esm/registration/register-provider-components.js.map +1 -1
- package/dist/esm/themes/dense.theme.d.ts.map +1 -1
- package/dist/esm/themes/dense.theme.js +22 -2
- package/dist/esm/themes/dense.theme.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +8 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billing-plan-change-preview.js","sourceRoot":"","sources":["../../../../../src/components/billing/billing-plan-change-preview.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAC3H,OAAO,EAA+B,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,sBAAsB,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC1K,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,mGAAmG;AACnG,MAAM,UAAU,iBAAiB,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAA0B;IACpJ,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,CAAC;IAC9B,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,EAAE,SAAS,EAAE,qBAAqB,CAAC,qCAAqC,EAAE,CAAC,CAAC;IACnJ,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,qBAAqB,CAAC,qCAAqC,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;IACzH,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,SAAS,GAAG,KAAK,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,MAAM,CAAc,IAAI,CAAC,CAAC;IACxC,SAAS,CAAC,GAAG,EAAE,GAAG,IAAI,OAAO;QAAE,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,CAAC,UAAU,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC5E,MAAM,WAAW,GAAG,SAAS,CAAC,UAAU,CAAC,UAAU,EAAE,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACpF,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,CACL,KAAC,OAAO,IAAC,OAAO,QAAC,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,CAAC,IAAI,YAClE,mBAAS,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,qBAAmB,SAAS,eAAa,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,YAAY,EAAE,SAAS,EAAC,qBAAqB,aACtI,aAAI,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,YAAG,CAAC,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,GAAM,EAC9G,YAAG,SAAS,EAAE,WAAW,CAAC,IAAI,YAAG,CAAC,CAAC,qBAAqB,CAAC,GAAK,
|
|
1
|
+
{"version":3,"file":"billing-plan-change-preview.js","sourceRoot":"","sources":["../../../../../src/components/billing/billing-plan-change-preview.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useEffect, useId, useMemo, useRef } from 'react';\nimport { FrontendComponentType, SurfaceVariant, TypographyVariant, UIBehavior } from '@wildo-ai/presets-components-models';\nimport { BillingTiming } from '@wildo-ai/saas-models';\nimport { type PlanChangePreviewProps, Alert, AlertDescription, Button, ButtonVariants_Variant, cn, Skeleton, Surface, useI18n, useUI } from '@wildo-ai/saas-frontend-lib';\nimport { useFormatMoney } from './billing-format.utils';\n\n/** Provider invoice estimate; amount due is not presented as a promise of immediate collection. */\nexport function PlanChangePreview({ preview, targetPlanName, isLoading, isConfirming, hasError, onConfirm, onCancel, onRetry }: PlanChangePreviewProps): React.JSX.Element | null {\n const { getRecipe } = useUI();\n const { makeTrComponent, formatDate, formatNumber, isReady } = useI18n({ component: FrontendComponentType.LOW_LEVEL_BILLING_PLAN_CHANGE_PREVIEW });\n const t = useMemo(() => makeTrComponent(FrontendComponentType.LOW_LEVEL_BILLING_PLAN_CHANGE_PREVIEW), [makeTrComponent]);\n const formatMoney = useFormatMoney();\n const headingId = useId();\n const panel = useRef<HTMLElement>(null);\n useEffect(() => { if (isReady) panel.current?.focus(); }, [isReady]);\n const heading = getRecipe(UIBehavior.TYPOGRAPHY, TypographyVariant.HEADING);\n const description = getRecipe(UIBehavior.TYPOGRAPHY, TypographyVariant.DESCRIPTION);\n if (!isReady) return null;\n // A change at the end of the period charges nothing now: the estimate is the renewal invoice on the new plan (#1868).\n const deferred = preview?.timing === BillingTiming.AT_PERIOD_END;\n return (\n <Surface asChild emitPolicyVars={false} variant={SurfaceVariant.BASE}>\n <section ref={panel} tabIndex={-1} aria-labelledby={headingId} aria-busy={!!isLoading || !!isConfirming} className=\"p-card space-y-card\">\n <h3 id={headingId} className={cn(heading.base, heading.sizes?.md)}>{t('title', { plan: targetPlanName })}</h3>\n <p className={description.base}>{t(deferred ? 'deferredEstimateExplanation' : 'estimateExplanation')}</p>\n {hasError && <Alert variant=\"destructive\"><AlertDescription>{t(preview ? 'confirmationFailed' : 'previewFailed')}</AlertDescription></Alert>}\n {isLoading && <div role=\"status\"><span>{t('loading')}</span><Skeleton className=\"h-8 w-32\" /></div>}\n {preview && !isLoading && (\n <div className=\"space-y-element\">\n <dl>\n {deferred && <><dt className={description.base}>{t('effectiveAt')}</dt><dd className={heading.base}>{formatDate(preview.effectiveAt)}</dd></>}\n <dt className={description.base}>{t('amountDue')}</dt>\n <dd className={heading.base}>{formatMoney(preview.amount)}</dd>\n <dt className={description.base}>{t('invoicePeriod')}</dt>\n <dd>{formatDate(preview.periodStart)} — {formatDate(preview.periodEnd)}</dd>\n </dl>\n <ul className=\"space-y-element\" aria-label={t('lineItems')}>\n {preview.lineItems.map((item, index) => <li key={index} className=\"flex flex-wrap justify-between gap-element\"><span>{item.description} <span className={description.base}>{t('quantity', { quantity: formatNumber(item.quantity) })}</span></span><span>{formatMoney(item.amount)}</span></li>)}\n </ul>\n <p className={description.base}>{t(deferred ? 'deferredConfirmationExplanation' : 'confirmationExplanation')}</p>\n </div>\n )}\n <div className=\"flex flex-wrap gap-element\">\n <Button onClick={onCancel} disabled={isConfirming} variant={ButtonVariants_Variant.OUTLINE}>{t('cancel')}</Button>\n {onRetry && !isConfirming && <Button onClick={onRetry} disabled={isLoading} variant={ButtonVariants_Variant.OUTLINE}>{t('retryPreview')}</Button>}\n {preview && onConfirm && <Button onClick={onConfirm} disabled={isLoading || isConfirming}>{t(isConfirming ? 'confirming' : 'confirmChange')}</Button>}\n </div>\n </section>\n </Surface>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billing-plan-change-preview.labels.d.ts","sourceRoot":"","sources":["../../../../../src/components/billing/billing-plan-change-preview.labels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,mBAAmB,EAA2B,MAAM,qCAAqC,CAAC;AAE1I,eAAO,MAAM,sCAAsC,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"billing-plan-change-preview.labels.d.ts","sourceRoot":"","sources":["../../../../../src/components/billing/billing-plan-change-preview.labels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,mBAAmB,EAA2B,MAAM,qCAAqC,CAAC;AAE1I,eAAO,MAAM,sCAAsC,EAAE,mBAAmB,EAkBvE,CAAC"}
|
|
@@ -7,6 +7,9 @@ export const LowLevelBillingPlanChangePreviewLabels = [
|
|
|
7
7
|
{ ref: 'quantity', kind: LabelKind.LABEL, purpose: 'Quantity represented by one estimated invoice line', params: [{ key: 'quantity', meaning: 'formatted invoice line quantity' }] },
|
|
8
8
|
{ ref: 'lineItems', kind: LabelKind.ARIA, purpose: 'Invoice estimate line items' },
|
|
9
9
|
{ ref: 'confirmationExplanation', kind: LabelKind.LABEL, purpose: 'Confirmation applies this selected plan change; the server verifies that the preview still matches the subscription and price' },
|
|
10
|
+
{ ref: 'deferredEstimateExplanation', kind: LabelKind.LABEL, purpose: 'This change takes effect at the end of the current billing period; the estimate is the renewal invoice on the new plan, and nothing is charged when the change is confirmed' },
|
|
11
|
+
{ ref: 'effectiveAt', kind: LabelKind.LABEL, purpose: 'Date the plan change takes effect: the end of the current billing period' },
|
|
12
|
+
{ ref: 'deferredConfirmationExplanation', kind: LabelKind.LABEL, purpose: 'Confirmation schedules this plan change for the end of the current billing period; the current plan stays in place until then, and the change can be withdrawn before it takes effect' },
|
|
10
13
|
{ ref: 'previewFailed', kind: LabelKind.EMPTY_STATE, purpose: 'The estimate could not be retrieved; no plan change was submitted. Retry or cancel' },
|
|
11
14
|
{ ref: 'confirmationFailed', kind: LabelKind.EMPTY_STATE, purpose: 'The plan change could not be confirmed. Retry the same confirmation or cancel; do not imply a failed response proves no provider change occurred' },
|
|
12
15
|
{ ref: 'loading', kind: LabelKind.LABEL, purpose: 'Retrieving the provider invoice estimate' },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billing-plan-change-preview.labels.js","sourceRoot":"","sources":["../../../../../src/components/billing/billing-plan-change-preview.labels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,SAAS,EAA4B,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AAE1I,MAAM,CAAC,MAAM,sCAAsC,GAA0B;IAC3E,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,8CAA8C,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,mCAAmC,EAAE,CAAC,EAAE;IAC3K,EAAE,GAAG,EAAE,qBAAqB,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,+HAA+H,EAAE;IAC/L,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,0GAA0G,EAAE;IAChK,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,8EAA8E,EAAE;IACxI,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,oDAAoD,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,iCAAiC,EAAE,CAAC,EAAE;IACpL,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,6BAA6B,EAAE;IAClF,EAAE,GAAG,EAAE,yBAAyB,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,+HAA+H,EAAE;IACnM,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,oFAAoF,EAAE;IACpJ,EAAE,GAAG,EAAE,oBAAoB,EAAE,IAAI,EAAE,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,kJAAkJ,EAAE;IACvN,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,0CAA0C,EAAE;IAC9F,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,6CAA6C,EAAE;IACrG,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,yEAAyE,EAAE;IACpI,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,uDAAuD,EAAE;IAC3G,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,8DAA8D,EAAE;CACzH,CAAC;AACF,uBAAuB,CAAC,qBAAqB,CAAC,qCAAqC,EAAE,sCAAsC,CAAC,CAAC","sourcesContent":["import { FrontendComponentType, LabelKind, type LabellingUnitaryDef, registerComponentLabels } from '@wildo-ai/presets-components-models';\n\nexport const LowLevelBillingPlanChangePreviewLabels: LabellingUnitaryDef[] = [\n { ref: 'title', kind: LabelKind.HEADING, purpose: 'Review the proposed subscription plan change', params: [{ key: 'plan', meaning: 'selected target plan display name' }] },\n { ref: 'estimateExplanation', kind: LabelKind.LABEL, purpose: 'The provider estimates the upcoming invoice for this change; the amount is not a promise of immediate collection or final tax' },\n { ref: 'amountDue', kind: LabelKind.LABEL, purpose: 'Estimated invoice amount due, which can include other invoice lines; not merely the proration adjustment' },\n { ref: 'invoicePeriod', kind: LabelKind.LABEL, purpose: 'Start and end of the estimated invoice period, not the exact collection date' },\n { ref: 'quantity', kind: LabelKind.LABEL, purpose: 'Quantity represented by one estimated invoice line', params: [{ key: 'quantity', meaning: 'formatted invoice line quantity' }] },\n { ref: 'lineItems', kind: LabelKind.ARIA, purpose: 'Invoice estimate line items' },\n { ref: 'confirmationExplanation', kind: LabelKind.LABEL, purpose: 'Confirmation applies this selected plan change; the server verifies that the preview still matches the subscription and price' },\n { ref: 'previewFailed', kind: LabelKind.EMPTY_STATE, purpose: 'The estimate could not be retrieved; no plan change was submitted. Retry or cancel' },\n { ref: 'confirmationFailed', kind: LabelKind.EMPTY_STATE, purpose: 'The plan change could not be confirmed. Retry the same confirmation or cancel; do not imply a failed response proves no provider change occurred' },\n { ref: 'loading', kind: LabelKind.LABEL, purpose: 'Retrieving the provider invoice estimate' },\n { ref: 'confirming', kind: LabelKind.BUTTON, purpose: 'The plan change confirmation is in progress' },\n { ref: 'confirmChange', kind: LabelKind.BUTTON, purpose: 'Explicitly confirm the currently displayed and server-bound plan change' },\n { ref: 'cancel', kind: LabelKind.BUTTON, purpose: 'Dismiss the preview without submitting a confirmation' },\n { ref: 'retryPreview', kind: LabelKind.BUTTON, purpose: 'Retry retrieving the estimate after a preview request failed' },\n];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_BILLING_PLAN_CHANGE_PREVIEW, LowLevelBillingPlanChangePreviewLabels);\n"]}
|
|
1
|
+
{"version":3,"file":"billing-plan-change-preview.labels.js","sourceRoot":"","sources":["../../../../../src/components/billing/billing-plan-change-preview.labels.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,SAAS,EAA4B,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AAE1I,MAAM,CAAC,MAAM,sCAAsC,GAA0B;IAC3E,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,8CAA8C,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,mCAAmC,EAAE,CAAC,EAAE;IAC3K,EAAE,GAAG,EAAE,qBAAqB,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,+HAA+H,EAAE;IAC/L,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,0GAA0G,EAAE;IAChK,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,8EAA8E,EAAE;IACxI,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,oDAAoD,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,iCAAiC,EAAE,CAAC,EAAE;IACpL,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,6BAA6B,EAAE;IAClF,EAAE,GAAG,EAAE,yBAAyB,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,+HAA+H,EAAE;IACnM,EAAE,GAAG,EAAE,6BAA6B,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,6KAA6K,EAAE;IACrP,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,0EAA0E,EAAE;IAClI,EAAE,GAAG,EAAE,iCAAiC,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,uLAAuL,EAAE;IACnQ,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,oFAAoF,EAAE;IACpJ,EAAE,GAAG,EAAE,oBAAoB,EAAE,IAAI,EAAE,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,kJAAkJ,EAAE;IACvN,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,0CAA0C,EAAE;IAC9F,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,6CAA6C,EAAE;IACrG,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,yEAAyE,EAAE;IACpI,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,uDAAuD,EAAE;IAC3G,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,8DAA8D,EAAE;CACzH,CAAC;AACF,uBAAuB,CAAC,qBAAqB,CAAC,qCAAqC,EAAE,sCAAsC,CAAC,CAAC","sourcesContent":["import { FrontendComponentType, LabelKind, type LabellingUnitaryDef, registerComponentLabels } from '@wildo-ai/presets-components-models';\n\nexport const LowLevelBillingPlanChangePreviewLabels: LabellingUnitaryDef[] = [\n { ref: 'title', kind: LabelKind.HEADING, purpose: 'Review the proposed subscription plan change', params: [{ key: 'plan', meaning: 'selected target plan display name' }] },\n { ref: 'estimateExplanation', kind: LabelKind.LABEL, purpose: 'The provider estimates the upcoming invoice for this change; the amount is not a promise of immediate collection or final tax' },\n { ref: 'amountDue', kind: LabelKind.LABEL, purpose: 'Estimated invoice amount due, which can include other invoice lines; not merely the proration adjustment' },\n { ref: 'invoicePeriod', kind: LabelKind.LABEL, purpose: 'Start and end of the estimated invoice period, not the exact collection date' },\n { ref: 'quantity', kind: LabelKind.LABEL, purpose: 'Quantity represented by one estimated invoice line', params: [{ key: 'quantity', meaning: 'formatted invoice line quantity' }] },\n { ref: 'lineItems', kind: LabelKind.ARIA, purpose: 'Invoice estimate line items' },\n { ref: 'confirmationExplanation', kind: LabelKind.LABEL, purpose: 'Confirmation applies this selected plan change; the server verifies that the preview still matches the subscription and price' },\n { ref: 'deferredEstimateExplanation', kind: LabelKind.LABEL, purpose: 'This change takes effect at the end of the current billing period; the estimate is the renewal invoice on the new plan, and nothing is charged when the change is confirmed' },\n { ref: 'effectiveAt', kind: LabelKind.LABEL, purpose: 'Date the plan change takes effect: the end of the current billing period' },\n { ref: 'deferredConfirmationExplanation', kind: LabelKind.LABEL, purpose: 'Confirmation schedules this plan change for the end of the current billing period; the current plan stays in place until then, and the change can be withdrawn before it takes effect' },\n { ref: 'previewFailed', kind: LabelKind.EMPTY_STATE, purpose: 'The estimate could not be retrieved; no plan change was submitted. Retry or cancel' },\n { ref: 'confirmationFailed', kind: LabelKind.EMPTY_STATE, purpose: 'The plan change could not be confirmed. Retry the same confirmation or cancel; do not imply a failed response proves no provider change occurred' },\n { ref: 'loading', kind: LabelKind.LABEL, purpose: 'Retrieving the provider invoice estimate' },\n { ref: 'confirming', kind: LabelKind.BUTTON, purpose: 'The plan change confirmation is in progress' },\n { ref: 'confirmChange', kind: LabelKind.BUTTON, purpose: 'Explicitly confirm the currently displayed and server-bound plan change' },\n { ref: 'cancel', kind: LabelKind.BUTTON, purpose: 'Dismiss the preview without submitting a confirmation' },\n { ref: 'retryPreview', kind: LabelKind.BUTTON, purpose: 'Retry retrieving the estimate after a preview request failed' },\n];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_BILLING_PLAN_CHANGE_PREVIEW, LowLevelBillingPlanChangePreviewLabels);\n"]}
|
|
@@ -12,5 +12,5 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import React from 'react';
|
|
14
14
|
import { PricingTableProps } from '@wildo-ai/saas-frontend-lib';
|
|
15
|
-
export declare function PricingTable({ plans, currentPlanKey, onSelectPlan, showIntervalToggle, isLoading, error, unavailable, isSelectionDisabled, }: PricingTableProps): React.JSX.Element | null;
|
|
15
|
+
export declare function PricingTable({ plans, currentPlanKey, onSelectPlan, showIntervalToggle, isLoading, error, unavailable, isSelectionDisabled, contactSalesHref, pendingPlanChange, onKeepCurrentPlan, isKeepingCurrentPlan, }: PricingTableProps): React.JSX.Element | null;
|
|
16
16
|
//# sourceMappingURL=billing-pricing-table.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billing-pricing-table.d.ts","sourceRoot":"","sources":["../../../../../src/components/billing/billing-pricing-table.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAIL,iBAAiB,EAalB,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"billing-pricing-table.d.ts","sourceRoot":"","sources":["../../../../../src/components/billing/billing-pricing-table.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAA4B,MAAM,OAAO,CAAC;AAEjD,OAAO,EAIL,iBAAiB,EAalB,MAAM,6BAA6B,CAAC;AAQrC,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,cAAc,EACd,YAAY,EACZ,kBAAyB,EACzB,SAAS,EACT,KAAK,EACL,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,GACrB,EAAE,iBAAiB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CA+P9C"}
|
|
@@ -14,11 +14,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
14
14
|
import { useMemo, useState } from 'react';
|
|
15
15
|
import { ButtonSize, FrontendComponentType, IndicatorVariant, SurfaceVariant, TypographyVariant, UIBehavior } from '@wildo-ai/presets-components-models';
|
|
16
16
|
import { cn, useI18n, useIconRegistry, StandardIconReference, IconSize, useUI, Button, ButtonVariants_Variant, Skeleton, Alert, AlertDescription, Surface, } from '@wildo-ai/saas-frontend-lib';
|
|
17
|
+
import { ProductPriceDisclosure } from '@wildo-ai/saas-models';
|
|
17
18
|
import { useFormatMoney } from './billing-format.utils.js';
|
|
18
19
|
// ── Component ───────────────────────────────────────────────────────
|
|
19
|
-
export function PricingTable({ plans, currentPlanKey, onSelectPlan, showIntervalToggle = true, isLoading, error, unavailable, isSelectionDisabled, }) {
|
|
20
|
+
export function PricingTable({ plans, currentPlanKey, onSelectPlan, showIntervalToggle = true, isLoading, error, unavailable, isSelectionDisabled, contactSalesHref, pendingPlanChange, onKeepCurrentPlan, isKeepingCurrentPlan, }) {
|
|
20
21
|
const { getRecipe } = useUI();
|
|
21
|
-
const { makeTrComponent, isReady } = useI18n({
|
|
22
|
+
const { makeTrComponent, formatDate, isReady } = useI18n({
|
|
22
23
|
component: FrontendComponentType.LOW_LEVEL_BILLING_PRICING_TABLE,
|
|
23
24
|
keys: ['billing_products', 'billing_features', 'billing_limits'],
|
|
24
25
|
});
|
|
@@ -67,10 +68,13 @@ export function PricingTable({ plans, currentPlanKey, onSelectPlan, showInterval
|
|
|
67
68
|
return null;
|
|
68
69
|
if (unavailable)
|
|
69
70
|
return _jsx(Alert, { variant: "destructive", children: _jsx(AlertDescription, { children: t('unavailable') }) });
|
|
70
|
-
return (_jsxs("div", { className: "w-full", children: [_jsx("div", { className: "text-center mb-section", children: _jsx("h2", { className: cn(headingRecipe.base, "text-3xl mb-element"), children: t('title') }) }), showIntervalToggle && hasYearlyPrices && (_jsxs("div", { className: "flex items-center justify-center gap-element mb-section", role: "radiogroup", "aria-label": t('intervalToggleLabel'), children: [_jsx(Button, { variant: selectedInterval === 'month' ? ButtonVariants_Variant.DEFAULT : ButtonVariants_Variant.GHOST, size: ButtonSize.SM, role: "radio", "aria-checked": selectedInterval === 'month', onClick: () => setSelectedInterval('month'), children: t('monthlyToggle') }), _jsx(Button, { variant: selectedInterval === 'year' ? ButtonVariants_Variant.DEFAULT : ButtonVariants_Variant.GHOST, size: ButtonSize.SM, role: "radio", "aria-checked": selectedInterval === 'year', onClick: () => setSelectedInterval('year'), children: t('yearlyToggle') })] })), _jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-card max-w-7xl mx-auto", children: sortedPlans.map(plan => {
|
|
71
|
+
return (_jsxs("div", { className: "w-full", children: [_jsx("div", { className: "text-center mb-section", children: _jsx("h2", { className: cn(headingRecipe.base, "text-3xl mb-element"), children: t('title') }) }), pendingPlanChange && (_jsx(Alert, { className: "mb-section", children: _jsxs(AlertDescription, { className: "flex flex-wrap items-center justify-between gap-element", children: [_jsx("span", { children: t('pendingPlanChange', { plan: pendingPlanChange.targetPlanName, date: formatDate(pendingPlanChange.effectiveAt) }) }), onKeepCurrentPlan && (_jsx(Button, { variant: ButtonVariants_Variant.OUTLINE, size: ButtonSize.SM, onClick: onKeepCurrentPlan, disabled: isKeepingCurrentPlan, children: t(isKeepingCurrentPlan ? 'keepingCurrentPlan' : 'keepCurrentPlan') }))] }) })), showIntervalToggle && hasYearlyPrices && (_jsxs("div", { className: "flex items-center justify-center gap-element mb-section", role: "radiogroup", "aria-label": t('intervalToggleLabel'), children: [_jsx(Button, { variant: selectedInterval === 'month' ? ButtonVariants_Variant.DEFAULT : ButtonVariants_Variant.GHOST, size: ButtonSize.SM, role: "radio", "aria-checked": selectedInterval === 'month', onClick: () => setSelectedInterval('month'), children: t('monthlyToggle') }), _jsx(Button, { variant: selectedInterval === 'year' ? ButtonVariants_Variant.DEFAULT : ButtonVariants_Variant.GHOST, size: ButtonSize.SM, role: "radio", "aria-checked": selectedInterval === 'year', onClick: () => setSelectedInterval('year'), children: t('yearlyToggle') })] })), _jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-card max-w-7xl mx-auto", children: sortedPlans.map(plan => {
|
|
71
72
|
const priceEntry = getDisplayPrice(plan);
|
|
72
73
|
const isCurrent = plan.key === currentPlanKey;
|
|
73
|
-
|
|
74
|
+
const isOnRequest = plan.priceDisclosure === ProductPriceDisclosure.ON_REQUEST;
|
|
75
|
+
const isStartingAt = plan.priceDisclosure === ProductPriceDisclosure.STARTING_AT;
|
|
76
|
+
const isAcquirable = plan.isAcquirable !== false;
|
|
77
|
+
return (_jsx(Surface, { asChild: true, emitPolicyVars: false, variant: SurfaceVariant.BASE, children: _jsxs("div", { className: cn("relative p-card flex flex-col", surfaceRecipe.base, plan.isRecommended && "border-primary shadow-[var(--shadow-lg)] ring-1 ring-primary", isCurrent && "bg-primary/5"), children: [plan.isRecommended && (_jsx("div", { className: "absolute -top-3 inset-x-0 flex justify-center", children: _jsx("span", { className: cn("inline-flex items-center px-3 py-1", indicatorInfoRecipe.base, "rounded-full"), children: t('recommendedBadge') }) })), isCurrent && (_jsx("div", { className: "absolute -top-3 inset-x-0 flex justify-center", children: _jsxs("span", { className: cn("inline-flex items-center px-3 py-1", indicatorNeutralRecipe.base, "rounded-full"), children: [renderIcon(StandardIconReference.CHECK, { size: IconSize.SM, className: 'me-1' }), t('currentPlanBadge')] }) })), _jsx("h3", { className: cn(headingRecipe.base, headingRecipe.sizes?.md, "mt-element"), children: plan.name }), plan.description && (_jsx("p", { className: cn(descriptionRecipe.base, "mt-1"), children: plan.description })), _jsx("div", { className: "my-section", children: isOnRequest ? (_jsx("div", { className: cn(headingRecipe.base, "text-2xl"), children: t('priceOnRequest') })) : !isStartingAt && (plan.isFree || (priceEntry && isFreePrice(priceEntry.price))) ? (_jsx("div", { className: cn(headingRecipe.base, "text-4xl"), children: t('freePlanLabel') })) : priceEntry ? (_jsxs("div", { className: "flex items-baseline gap-item", children: [isStartingAt && _jsx("span", { className: cn(descriptionRecipe.base), children: t('startingAtPrefix') }), _jsx("span", { className: cn(headingRecipe.base, "text-4xl"), children: formatMoney(priceEntry.price) }), _jsx("span", { className: cn(descriptionRecipe.base), children: priceEntry.interval === 'year' ? t('perYear') : t('perMonth') })] })) : null }), plan.trialDays && plan.trialDays > 0 && !isCurrent && (_jsx("p", { className: "text-xs text-center text-primary font-medium mb-element", children: t('trialDays', { days: plan.trialDays }) })), isOnRequest && !isCurrent ? (contactSalesHref ? (_jsx(Button, { variant: plan.isRecommended ? ButtonVariants_Variant.ACCENT : ButtonVariants_Variant.SECONDARY, className: "w-full mb-section", asChild: true, children: _jsx("a", { href: contactSalesHref, children: t('contactSales') }) })) : null) : (_jsx(Button, { variant: isCurrent ? ButtonVariants_Variant.SECONDARY : plan.isRecommended ? ButtonVariants_Variant.ACCENT : ButtonVariants_Variant.SECONDARY, className: "w-full mb-section", disabled: isCurrent || isSelectionDisabled || !priceEntry || !isAcquirable, onClick: () => priceEntry && isAcquirable && onSelectPlan(plan.key, priceEntry.priceId), children: isCurrent || isAcquirable ? getButtonLabel(plan) : t('comingSoon') })), _jsxs("div", { className: "flex-1 space-y-element", children: [_jsx("p", { className: cn(descriptionRecipe.base, "font-medium"), children: t('featuresIncluded') }), _jsxs("ul", { className: "space-y-1.5", children: [plan.grantedFeatures.map(feature => (_jsxs("li", { className: cn("flex items-start gap-element", descriptionRecipe.base), children: [renderIcon(StandardIconReference.CHECK, { size: IconSize.SM, className: 'text-primary mt-0.5 shrink-0' }), _jsx("span", { children: feature.label })] }, feature.id))), plan.grantedLimits.map(limit => (_jsxs("li", { className: cn("flex items-start gap-element", descriptionRecipe.base), children: [renderIcon(StandardIconReference.CHECK, { size: IconSize.SM, className: 'text-primary mt-0.5 shrink-0' }), _jsxs("span", { children: [limit.label, ": ", limit.value === -1 ? t('unlimited') : t('limitDisplay', { value: limit.value })] })] }, limit.id)))] })] })] }) }, plan.key));
|
|
74
78
|
}) })] }));
|
|
75
79
|
}
|
|
76
80
|
//# sourceMappingURL=billing-pricing-table.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billing-pricing-table.js","sourceRoot":"","sources":["../../../../../src/components/billing/billing-pricing-table.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * PricingTable (Preset)\n *\n * Responsive plan comparison table. Reads product definitions to display\n * plan options with features, pricing, and CTAs.\n *\n * DELEGATION PRINCIPLE: Clicking a plan triggers `onSelectPlan` which\n * opens Stripe Checkout (hosted page) — no payment UI is rendered here.\n *\n * Formatting: Uses useI18n() for locale-aware formatting\n * of monetary amounts and numbers, respecting user/org regional preferences.\n */\n\nimport React, { useMemo, useState } from 'react';\nimport { ButtonSize, FrontendComponentType, IndicatorVariant, SurfaceVariant, TypographyVariant, UIBehavior } from '@wildo-ai/presets-components-models';\nimport {\n PricingTableFeature,\n PricingTableLimit,\n PricingTablePlan,\n PricingTableProps,\n cn,\n useI18n,\n useIconRegistry,\n StandardIconReference,\n IconSize,\n useUI,\n Button,\n ButtonVariants_Variant,\n Skeleton,\n Alert,\n AlertDescription,\n Surface,\n} from '@wildo-ai/saas-frontend-lib';\nimport type { MoneyValue } from '@wildo-ai/zod-decorators';\n\nimport { useFormatMoney } from './billing-format.utils';\n\n// ── Component ───────────────────────────────────────────────────────\n\nexport function PricingTable({\n plans,\n currentPlanKey,\n onSelectPlan,\n showIntervalToggle = true,\n isLoading,\n error,\n unavailable,\n isSelectionDisabled,\n}: PricingTableProps): React.JSX.Element | null {\n const { getRecipe } = useUI();\n const { makeTrComponent, isReady } = useI18n({\n component: FrontendComponentType.LOW_LEVEL_BILLING_PRICING_TABLE,\n keys: ['billing_products', 'billing_features', 'billing_limits'],\n });\n const { renderIcon } = useIconRegistry();\n const formatMoney = useFormatMoney();\n\n const surfaceRecipe = getRecipe(UIBehavior.SURFACE, SurfaceVariant.BASE);\n const indicatorInfoRecipe = getRecipe(UIBehavior.INDICATOR, IndicatorVariant.INFO);\n const indicatorNeutralRecipe = getRecipe(UIBehavior.INDICATOR, IndicatorVariant.NEUTRAL);\n const headingRecipe = getRecipe(UIBehavior.TYPOGRAPHY, TypographyVariant.HEADING);\n const descriptionRecipe = getRecipe(UIBehavior.TYPOGRAPHY, TypographyVariant.DESCRIPTION);\n\n const t = useMemo(\n () => makeTrComponent(FrontendComponentType.LOW_LEVEL_BILLING_PRICING_TABLE),\n [makeTrComponent],\n );\n\n const [selectedInterval, setSelectedInterval] = useState<'month' | 'year'>('month');\n\n // Sort plans by sortOrder\n const sortedPlans = useMemo(\n () => [...plans].sort((a, b) => a.sortOrder - b.sortOrder),\n [plans],\n );\n\n // Check if any plan has yearly prices\n const hasYearlyPrices = useMemo(\n () => plans.some(p => p.prices.some(pr => pr.interval === 'year')),\n [plans],\n );\n\n const getDisplayPrice = (plan: PricingTablePlan) => {\n // Find the price for the selected interval\n const matchingPrice = plan.prices.find(pr => pr.interval === selectedInterval);\n if (matchingPrice) return matchingPrice;\n // Fallback to default price\n const defaultPrice = plan.prices.find(pr => pr.isDefault);\n return defaultPrice ?? plan.prices[0];\n };\n\n const isFreePrice = (money: MoneyValue): boolean => money.amount === 0n;\n\n const getButtonLabel = (plan: PricingTablePlan): string => {\n if (plan.isCurrent) return t('currentPlan');\n if (currentPlanKey) {\n const currentPlan = plans.find(p => p.key === currentPlanKey);\n if (currentPlan && plan.sortOrder > currentPlan.sortOrder) return t('upgradePlan');\n if (currentPlan && plan.sortOrder < currentPlan.sortOrder) return t('downgradePlan');\n }\n return t('selectPlan');\n };\n\n if (error) {\n return (\n <Alert variant=\"destructive\">\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n );\n }\n\n if (isLoading) {\n return (\n <div className=\"w-full\">\n <div className=\"text-center mb-section\">\n <Skeleton className=\"h-8 w-48 mx-auto mb-element\" />\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-card max-w-7xl mx-auto\">\n {[0, 1, 2].map(i => (\n <Surface key={i} asChild emitPolicyVars={false} variant={SurfaceVariant.BASE}>\n <div className={cn(\"relative p-card flex flex-col\", surfaceRecipe.base)}>\n <Skeleton className=\"h-5 w-24 mb-element\" />\n <Skeleton className=\"h-10 w-32 my-section\" />\n <Skeleton className=\"h-10 w-full rounded-md mb-section\" />\n <div className=\"space-y-element flex-1\">\n <Skeleton className=\"h-4 w-28\" />\n {[0, 1, 2, 3].map(j => (\n <Skeleton key={j} className=\"h-4 w-full\" />\n ))}\n </div>\n </div>\n </Surface>\n ))}\n </div>\n </div>\n );\n }\n\n if (!isReady) return null;\n\n if (unavailable) return <Alert variant=\"destructive\"><AlertDescription>{t('unavailable')}</AlertDescription></Alert>;\n\n return (\n <div className=\"w-full\">\n {/* Title */}\n <div className=\"text-center mb-section\">\n <h2 className={cn(headingRecipe.base, \"text-3xl mb-element\")}>{t('title')}</h2>\n </div>\n\n {/* Interval toggle */}\n {showIntervalToggle && hasYearlyPrices && (\n <div className=\"flex items-center justify-center gap-element mb-section\" role=\"radiogroup\" aria-label={t('intervalToggleLabel')}>\n <Button\n variant={selectedInterval === 'month' ? ButtonVariants_Variant.DEFAULT : ButtonVariants_Variant.GHOST}\n size={ButtonSize.SM}\n role=\"radio\"\n aria-checked={selectedInterval === 'month'}\n onClick={() => setSelectedInterval('month')}\n >\n {t('monthlyToggle')}\n </Button>\n <Button\n variant={selectedInterval === 'year' ? ButtonVariants_Variant.DEFAULT : ButtonVariants_Variant.GHOST}\n size={ButtonSize.SM}\n role=\"radio\"\n aria-checked={selectedInterval === 'year'}\n onClick={() => setSelectedInterval('year')}\n >\n {t('yearlyToggle')}\n </Button>\n </div>\n )}\n\n {/* Plan cards grid */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-card max-w-7xl mx-auto\">\n {sortedPlans.map(plan => {\n const priceEntry = getDisplayPrice(plan);\n const isCurrent = plan.key === currentPlanKey;\n\n return (\n <Surface key={plan.key} asChild emitPolicyVars={false} variant={SurfaceVariant.BASE}>\n <div\n className={cn(\n \"relative p-card flex flex-col\",\n surfaceRecipe.base,\n plan.isPopular && \"border-primary shadow-[var(--shadow-lg)] ring-1 ring-primary\",\n isCurrent && \"bg-primary/5\",\n )}\n >\n {/* Popular badge */}\n {plan.isPopular && (\n <div className=\"absolute -top-3 inset-x-0 flex justify-center\">\n <span className={cn(\"inline-flex items-center px-3 py-1\", indicatorInfoRecipe.base, \"rounded-full\")}>\n {t('mostPopularBadge')}\n </span>\n </div>\n )}\n\n {/* Current plan badge */}\n {isCurrent && (\n <div className=\"absolute -top-3 inset-x-0 flex justify-center\">\n <span className={cn(\"inline-flex items-center px-3 py-1\", indicatorNeutralRecipe.base, \"rounded-full\")}>\n {renderIcon(StandardIconReference.CHECK, { size: IconSize.SM, className: 'me-1' })}\n {t('currentPlanBadge')}\n </span>\n </div>\n )}\n\n {/* Plan name + description */}\n <h3 className={cn(headingRecipe.base, headingRecipe.sizes?.md, \"mt-element\")}>{plan.name}</h3>\n {plan.description && (\n <p className={cn(descriptionRecipe.base, \"mt-1\")}>{plan.description}</p>\n )}\n\n {/* Price */}\n <div className=\"my-section\">\n {plan.isFree || (priceEntry && isFreePrice(priceEntry.price)) ? (\n <div className={cn(headingRecipe.base, \"text-4xl\")}>{t('freePlanLabel')}</div>\n ) : priceEntry ? (\n <div className=\"flex items-baseline gap-item\">\n <span className={cn(headingRecipe.base, \"text-4xl\")}>\n {formatMoney(priceEntry.price)}\n </span>\n <span className={cn(descriptionRecipe.base)}>\n {priceEntry.interval === 'year' ? t('perYear') : t('perMonth')}\n </span>\n </div>\n ) : null}\n </div>\n\n {/* Trial days badge */}\n {plan.trialDays && plan.trialDays > 0 && !isCurrent && (\n <p className=\"text-xs text-center text-primary font-medium mb-element\">\n {t('trialDays', { days: plan.trialDays })}\n </p>\n )}\n\n {/* CTA button */}\n <Button\n variant={isCurrent ? ButtonVariants_Variant.SECONDARY : plan.isPopular ? ButtonVariants_Variant.ACCENT : ButtonVariants_Variant.SECONDARY}\n className=\"w-full mb-section\"\n disabled={isCurrent || isSelectionDisabled || !priceEntry}\n onClick={() => priceEntry && onSelectPlan(plan.key, priceEntry.priceId)}\n >\n {getButtonLabel(plan)}\n </Button>\n\n {/* Features list */}\n <div className=\"flex-1 space-y-element\">\n <p className={cn(descriptionRecipe.base, \"font-medium\")}>{t('featuresIncluded')}</p>\n <ul className=\"space-y-1.5\">\n {plan.grantedFeatures.map(feature => (\n <li key={feature.id} className={cn(\"flex items-start gap-element\", descriptionRecipe.base)}>\n {renderIcon(StandardIconReference.CHECK, { size: IconSize.SM, className: 'text-primary mt-0.5 shrink-0' })}\n <span>{feature.label}</span>\n </li>\n ))}\n {plan.grantedLimits.map(limit => (\n <li key={limit.id} className={cn(\"flex items-start gap-element\", descriptionRecipe.base)}>\n {renderIcon(StandardIconReference.CHECK, { size: IconSize.SM, className: 'text-primary mt-0.5 shrink-0' })}\n <span>\n {limit.label}: {limit.value === -1 ? t('unlimited') : t('limitDisplay', { value: limit.value })}\n </span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n </Surface>\n );\n })}\n </div>\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"billing-pricing-table.js","sourceRoot":"","sources":["../../../../../src/components/billing/billing-pricing-table.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * PricingTable (Preset)\n *\n * Responsive plan comparison table. Reads product definitions to display\n * plan options with features, pricing, and CTAs.\n *\n * DELEGATION PRINCIPLE: Clicking a plan triggers `onSelectPlan` which\n * opens Stripe Checkout (hosted page) — no payment UI is rendered here.\n *\n * Formatting: Uses useI18n() for locale-aware formatting\n * of monetary amounts and numbers, respecting user/org regional preferences.\n */\n\nimport React, { useMemo, useState } from 'react';\nimport { ButtonSize, FrontendComponentType, IndicatorVariant, SurfaceVariant, TypographyVariant, UIBehavior } from '@wildo-ai/presets-components-models';\nimport {\n PricingTableFeature,\n PricingTableLimit,\n PricingTablePlan,\n PricingTableProps,\n cn,\n useI18n,\n useIconRegistry,\n StandardIconReference,\n IconSize,\n useUI,\n Button,\n ButtonVariants_Variant,\n Skeleton,\n Alert,\n AlertDescription,\n Surface,\n} from '@wildo-ai/saas-frontend-lib';\nimport type { MoneyValue } from '@wildo-ai/zod-decorators';\nimport { ProductPriceDisclosure } from '@wildo-ai/saas-models';\n\nimport { useFormatMoney } from './billing-format.utils';\n\n// ── Component ───────────────────────────────────────────────────────\n\nexport function PricingTable({\n plans,\n currentPlanKey,\n onSelectPlan,\n showIntervalToggle = true,\n isLoading,\n error,\n unavailable,\n isSelectionDisabled,\n contactSalesHref,\n pendingPlanChange,\n onKeepCurrentPlan,\n isKeepingCurrentPlan,\n}: PricingTableProps): React.JSX.Element | null {\n const { getRecipe } = useUI();\n const { makeTrComponent, formatDate, isReady } = useI18n({\n component: FrontendComponentType.LOW_LEVEL_BILLING_PRICING_TABLE,\n keys: ['billing_products', 'billing_features', 'billing_limits'],\n });\n const { renderIcon } = useIconRegistry();\n const formatMoney = useFormatMoney();\n\n const surfaceRecipe = getRecipe(UIBehavior.SURFACE, SurfaceVariant.BASE);\n const indicatorInfoRecipe = getRecipe(UIBehavior.INDICATOR, IndicatorVariant.INFO);\n const indicatorNeutralRecipe = getRecipe(UIBehavior.INDICATOR, IndicatorVariant.NEUTRAL);\n const headingRecipe = getRecipe(UIBehavior.TYPOGRAPHY, TypographyVariant.HEADING);\n const descriptionRecipe = getRecipe(UIBehavior.TYPOGRAPHY, TypographyVariant.DESCRIPTION);\n\n const t = useMemo(\n () => makeTrComponent(FrontendComponentType.LOW_LEVEL_BILLING_PRICING_TABLE),\n [makeTrComponent],\n );\n\n const [selectedInterval, setSelectedInterval] = useState<'month' | 'year'>('month');\n\n // Sort plans by sortOrder\n const sortedPlans = useMemo(\n () => [...plans].sort((a, b) => a.sortOrder - b.sortOrder),\n [plans],\n );\n\n // Check if any plan has yearly prices\n const hasYearlyPrices = useMemo(\n () => plans.some(p => p.prices.some(pr => pr.interval === 'year')),\n [plans],\n );\n\n const getDisplayPrice = (plan: PricingTablePlan) => {\n // Find the price for the selected interval\n const matchingPrice = plan.prices.find(pr => pr.interval === selectedInterval);\n if (matchingPrice) return matchingPrice;\n // Fallback to default price\n const defaultPrice = plan.prices.find(pr => pr.isDefault);\n return defaultPrice ?? plan.prices[0];\n };\n\n const isFreePrice = (money: MoneyValue): boolean => money.amount === 0n;\n\n const getButtonLabel = (plan: PricingTablePlan): string => {\n if (plan.isCurrent) return t('currentPlan');\n if (currentPlanKey) {\n const currentPlan = plans.find(p => p.key === currentPlanKey);\n if (currentPlan && plan.sortOrder > currentPlan.sortOrder) return t('upgradePlan');\n if (currentPlan && plan.sortOrder < currentPlan.sortOrder) return t('downgradePlan');\n }\n return t('selectPlan');\n };\n\n if (error) {\n return (\n <Alert variant=\"destructive\">\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n );\n }\n\n if (isLoading) {\n return (\n <div className=\"w-full\">\n <div className=\"text-center mb-section\">\n <Skeleton className=\"h-8 w-48 mx-auto mb-element\" />\n </div>\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-card max-w-7xl mx-auto\">\n {[0, 1, 2].map(i => (\n <Surface key={i} asChild emitPolicyVars={false} variant={SurfaceVariant.BASE}>\n <div className={cn(\"relative p-card flex flex-col\", surfaceRecipe.base)}>\n <Skeleton className=\"h-5 w-24 mb-element\" />\n <Skeleton className=\"h-10 w-32 my-section\" />\n <Skeleton className=\"h-10 w-full rounded-md mb-section\" />\n <div className=\"space-y-element flex-1\">\n <Skeleton className=\"h-4 w-28\" />\n {[0, 1, 2, 3].map(j => (\n <Skeleton key={j} className=\"h-4 w-full\" />\n ))}\n </div>\n </div>\n </Surface>\n ))}\n </div>\n </div>\n );\n }\n\n if (!isReady) return null;\n\n if (unavailable) return <Alert variant=\"destructive\"><AlertDescription>{t('unavailable')}</AlertDescription></Alert>;\n\n return (\n <div className=\"w-full\">\n {/* Title */}\n <div className=\"text-center mb-section\">\n <h2 className={cn(headingRecipe.base, \"text-3xl mb-element\")}>{t('title')}</h2>\n </div>\n\n {/* A plan change pending at the end of the period (#1868): another change is refused until it is withdrawn. */}\n {pendingPlanChange && (\n <Alert className=\"mb-section\">\n <AlertDescription className=\"flex flex-wrap items-center justify-between gap-element\">\n <span>{t('pendingPlanChange', { plan: pendingPlanChange.targetPlanName, date: formatDate(pendingPlanChange.effectiveAt) })}</span>\n {onKeepCurrentPlan && (\n <Button variant={ButtonVariants_Variant.OUTLINE} size={ButtonSize.SM} onClick={onKeepCurrentPlan} disabled={isKeepingCurrentPlan}>\n {t(isKeepingCurrentPlan ? 'keepingCurrentPlan' : 'keepCurrentPlan')}\n </Button>\n )}\n </AlertDescription>\n </Alert>\n )}\n\n {/* Interval toggle */}\n {showIntervalToggle && hasYearlyPrices && (\n <div className=\"flex items-center justify-center gap-element mb-section\" role=\"radiogroup\" aria-label={t('intervalToggleLabel')}>\n <Button\n variant={selectedInterval === 'month' ? ButtonVariants_Variant.DEFAULT : ButtonVariants_Variant.GHOST}\n size={ButtonSize.SM}\n role=\"radio\"\n aria-checked={selectedInterval === 'month'}\n onClick={() => setSelectedInterval('month')}\n >\n {t('monthlyToggle')}\n </Button>\n <Button\n variant={selectedInterval === 'year' ? ButtonVariants_Variant.DEFAULT : ButtonVariants_Variant.GHOST}\n size={ButtonSize.SM}\n role=\"radio\"\n aria-checked={selectedInterval === 'year'}\n onClick={() => setSelectedInterval('year')}\n >\n {t('yearlyToggle')}\n </Button>\n </div>\n )}\n\n {/* Plan cards grid */}\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-card max-w-7xl mx-auto\">\n {sortedPlans.map(plan => {\n const priceEntry = getDisplayPrice(plan);\n const isCurrent = plan.key === currentPlanKey;\n const isOnRequest = plan.priceDisclosure === ProductPriceDisclosure.ON_REQUEST;\n const isStartingAt = plan.priceDisclosure === ProductPriceDisclosure.STARTING_AT;\n const isAcquirable = plan.isAcquirable !== false;\n\n return (\n <Surface key={plan.key} asChild emitPolicyVars={false} variant={SurfaceVariant.BASE}>\n <div\n className={cn(\n \"relative p-card flex flex-col\",\n surfaceRecipe.base,\n plan.isRecommended && \"border-primary shadow-[var(--shadow-lg)] ring-1 ring-primary\",\n isCurrent && \"bg-primary/5\",\n )}\n >\n {/* Recommended badge — the catalogue's recommendation, never a popularity claim */}\n {plan.isRecommended && (\n <div className=\"absolute -top-3 inset-x-0 flex justify-center\">\n <span className={cn(\"inline-flex items-center px-3 py-1\", indicatorInfoRecipe.base, \"rounded-full\")}>\n {t('recommendedBadge')}\n </span>\n </div>\n )}\n\n {/* Current plan badge */}\n {isCurrent && (\n <div className=\"absolute -top-3 inset-x-0 flex justify-center\">\n <span className={cn(\"inline-flex items-center px-3 py-1\", indicatorNeutralRecipe.base, \"rounded-full\")}>\n {renderIcon(StandardIconReference.CHECK, { size: IconSize.SM, className: 'me-1' })}\n {t('currentPlanBadge')}\n </span>\n </div>\n )}\n\n {/* Plan name + description */}\n <h3 className={cn(headingRecipe.base, headingRecipe.sizes?.md, \"mt-element\")}>{plan.name}</h3>\n {plan.description && (\n <p className={cn(descriptionRecipe.base, \"mt-1\")}>{plan.description}</p>\n )}\n\n {/* Price */}\n <div className=\"my-section\">\n {isOnRequest ? (\n <div className={cn(headingRecipe.base, \"text-2xl\")}>{t('priceOnRequest')}</div>\n ) : !isStartingAt && (plan.isFree || (priceEntry && isFreePrice(priceEntry.price))) ? (\n <div className={cn(headingRecipe.base, \"text-4xl\")}>{t('freePlanLabel')}</div>\n ) : priceEntry ? (\n <div className=\"flex items-baseline gap-item\">\n {isStartingAt && <span className={cn(descriptionRecipe.base)}>{t('startingAtPrefix')}</span>}\n <span className={cn(headingRecipe.base, \"text-4xl\")}>\n {formatMoney(priceEntry.price)}\n </span>\n <span className={cn(descriptionRecipe.base)}>\n {priceEntry.interval === 'year' ? t('perYear') : t('perMonth')}\n </span>\n </div>\n ) : null}\n </div>\n\n {/* Trial days badge */}\n {plan.trialDays && plan.trialDays > 0 && !isCurrent && (\n <p className=\"text-xs text-center text-primary font-medium mb-element\">\n {t('trialDays', { days: plan.trialDays })}\n </p>\n )}\n\n {/* CTA — an on-request plan leads to sales (or nowhere, when no destination is configured);\n an upcoming plan is shown and cannot be selected, because the backend refuses it. */}\n {isOnRequest && !isCurrent ? (\n contactSalesHref ? (\n <Button variant={plan.isRecommended ? ButtonVariants_Variant.ACCENT : ButtonVariants_Variant.SECONDARY} className=\"w-full mb-section\" asChild>\n <a href={contactSalesHref}>{t('contactSales')}</a>\n </Button>\n ) : null\n ) : (\n <Button\n variant={isCurrent ? ButtonVariants_Variant.SECONDARY : plan.isRecommended ? ButtonVariants_Variant.ACCENT : ButtonVariants_Variant.SECONDARY}\n className=\"w-full mb-section\"\n disabled={isCurrent || isSelectionDisabled || !priceEntry || !isAcquirable}\n onClick={() => priceEntry && isAcquirable && onSelectPlan(plan.key, priceEntry.priceId)}\n >\n {isCurrent || isAcquirable ? getButtonLabel(plan) : t('comingSoon')}\n </Button>\n )}\n\n {/* Features list */}\n <div className=\"flex-1 space-y-element\">\n <p className={cn(descriptionRecipe.base, \"font-medium\")}>{t('featuresIncluded')}</p>\n <ul className=\"space-y-1.5\">\n {plan.grantedFeatures.map(feature => (\n <li key={feature.id} className={cn(\"flex items-start gap-element\", descriptionRecipe.base)}>\n {renderIcon(StandardIconReference.CHECK, { size: IconSize.SM, className: 'text-primary mt-0.5 shrink-0' })}\n <span>{feature.label}</span>\n </li>\n ))}\n {plan.grantedLimits.map(limit => (\n <li key={limit.id} className={cn(\"flex items-start gap-element\", descriptionRecipe.base)}>\n {renderIcon(StandardIconReference.CHECK, { size: IconSize.SM, className: 'text-primary mt-0.5 shrink-0' })}\n <span>\n {limit.label}: {limit.value === -1 ? t('unlimited') : t('limitDisplay', { value: limit.value })}\n </span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n </Surface>\n );\n })}\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billing-pricing-table.labels.d.ts","sourceRoot":"","sources":["../../../../../src/components/billing/billing-pricing-table.labels.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,mBAAmB,EAEzB,MAAM,qCAAqC,CAAC;AAM7C,eAAO,MAAM,iCAAiC,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"billing-pricing-table.labels.d.ts","sourceRoot":"","sources":["../../../../../src/components/billing/billing-pricing-table.labels.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,mBAAmB,EAEzB,MAAM,qCAAqC,CAAC;AAM7C,eAAO,MAAM,iCAAiC,EAAE,mBAAmB,EAmDlE,CAAC"}
|
|
@@ -5,8 +5,11 @@ import { FrontendComponentType, LabelKind, registerComponentLabels, } from '@wil
|
|
|
5
5
|
export const LowLevelBillingPricingTableLabels = [
|
|
6
6
|
{ ref: 'unavailable', kind: LabelKind.EMPTY_STATE, purpose: 'Billing information is temporarily unavailable; this is a failed read, not an empty account or a free plan' },
|
|
7
7
|
{ ref: 'title', kind: LabelKind.HEADING, purpose: 'Heading for the pricing-table plan grid' },
|
|
8
|
+
{ ref: 'pendingPlanChange', kind: LabelKind.LABEL, purpose: 'A plan change is already confirmed and takes effect at the end of the current billing period; until then the subscription stays on its current plan and another plan cannot be chosen', params: [{ key: 'plan', meaning: 'name of the plan the subscription moves to' }, { key: 'date', meaning: 'formatted date the change takes effect' }] },
|
|
9
|
+
{ ref: 'keepCurrentPlan', kind: LabelKind.BUTTON, purpose: 'Withdraw the pending plan change so the subscription renews on its current plan' },
|
|
10
|
+
{ ref: 'keepingCurrentPlan', kind: LabelKind.BUTTON, purpose: 'The pending plan change is being withdrawn' },
|
|
8
11
|
{ ref: 'currentPlanBadge', kind: LabelKind.LABEL, purpose: "Badge marking the customer's currently active plan" },
|
|
9
|
-
{ ref: '
|
|
12
|
+
{ ref: 'recommendedBadge', kind: LabelKind.LABEL, purpose: 'Badge on the plan the product recommends for the audience it is designed for. A recommendation, never a claim about what other customers chose: do not word it as "most popular".' },
|
|
10
13
|
{ ref: 'perMonth', kind: LabelKind.LABEL, purpose: 'Suffix denoting a per-month price' },
|
|
11
14
|
{ ref: 'perYear', kind: LabelKind.LABEL, purpose: 'Suffix denoting a per-year price' },
|
|
12
15
|
{ ref: 'monthlyToggle', kind: LabelKind.LABEL, purpose: 'Toggle option that shows monthly pricing' },
|
|
@@ -16,6 +19,9 @@ export const LowLevelBillingPricingTableLabels = [
|
|
|
16
19
|
{ ref: 'upgradePlan', kind: LabelKind.BUTTON, purpose: 'Call-to-action that moves the customer to a higher tier' },
|
|
17
20
|
{ ref: 'downgradePlan', kind: LabelKind.BUTTON, purpose: 'Call-to-action that moves the customer to a lower tier' },
|
|
18
21
|
{ ref: 'contactSales', kind: LabelKind.BUTTON, purpose: 'Call-to-action for enterprise/custom-quote plans' },
|
|
22
|
+
{ ref: 'priceOnRequest', kind: LabelKind.LABEL, purpose: 'Shown in place of a price for a plan whose price is quoted on request rather than listed' },
|
|
23
|
+
{ ref: 'startingAtPrefix', kind: LabelKind.LABEL, purpose: 'Word placed before a plan price that is only a starting price, because part of the total is quoted (for example "From")' },
|
|
24
|
+
{ ref: 'comingSoon', kind: LabelKind.BUTTON, purpose: 'Disabled action on a plan that is announced but cannot be bought yet' },
|
|
19
25
|
{ ref: 'freePlanLabel', kind: LabelKind.LABEL, purpose: 'Price label shown for a no-cost plan tier' },
|
|
20
26
|
{ ref: 'featuresIncluded', kind: LabelKind.HEADING, purpose: "Heading above a plan's list of included features" },
|
|
21
27
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billing-pricing-table.labels.js","sourceRoot":"","sources":["../../../../../src/components/billing/billing-pricing-table.labels.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,SAAS,EAET,uBAAuB,GACxB,MAAM,qCAAqC,CAAC;AAE7C,4EAA4E;AAC5E,8EAA8E;AAC9E,4DAA4D;AAE5D,MAAM,CAAC,MAAM,iCAAiC,GAA0B;IACtE,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,4GAA4G,EAAE;IAC1K,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,yCAAyC,EAAE;IAC7F,EAAE,GAAG,EAAE,kBAAkB,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,oDAAoD,EAAE;IACjH,EAAE,GAAG,EAAE,kBAAkB,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"billing-pricing-table.labels.js","sourceRoot":"","sources":["../../../../../src/components/billing/billing-pricing-table.labels.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n FrontendComponentType,\n LabelKind,\n type LabellingUnitaryDef,\n registerComponentLabels,\n} from '@wildo-ai/presets-components-models';\n\n// Companion-only label metadata for this component: keys + params + per-key\n// purpose / kind / variable meaning. Statically scanned by the dev companion;\n// NOT imported at runtime, so it never ships in the bundle.\n\nexport const LowLevelBillingPricingTableLabels: LabellingUnitaryDef[] = [\n { ref: 'unavailable', kind: LabelKind.EMPTY_STATE, purpose: 'Billing information is temporarily unavailable; this is a failed read, not an empty account or a free plan' },\n { ref: 'title', kind: LabelKind.HEADING, purpose: 'Heading for the pricing-table plan grid' },\n { ref: 'pendingPlanChange', kind: LabelKind.LABEL, purpose: 'A plan change is already confirmed and takes effect at the end of the current billing period; until then the subscription stays on its current plan and another plan cannot be chosen', params: [{ key: 'plan', meaning: 'name of the plan the subscription moves to' }, { key: 'date', meaning: 'formatted date the change takes effect' }] },\n { ref: 'keepCurrentPlan', kind: LabelKind.BUTTON, purpose: 'Withdraw the pending plan change so the subscription renews on its current plan' },\n { ref: 'keepingCurrentPlan', kind: LabelKind.BUTTON, purpose: 'The pending plan change is being withdrawn' },\n { ref: 'currentPlanBadge', kind: LabelKind.LABEL, purpose: \"Badge marking the customer's currently active plan\" },\n { ref: 'recommendedBadge', kind: LabelKind.LABEL, purpose: 'Badge on the plan the product recommends for the audience it is designed for. A recommendation, never a claim about what other customers chose: do not word it as \"most popular\".' },\n { ref: 'perMonth', kind: LabelKind.LABEL, purpose: 'Suffix denoting a per-month price' },\n { ref: 'perYear', kind: LabelKind.LABEL, purpose: 'Suffix denoting a per-year price' },\n { ref: 'monthlyToggle', kind: LabelKind.LABEL, purpose: 'Toggle option that shows monthly pricing' },\n { ref: 'yearlyToggle', kind: LabelKind.LABEL, purpose: 'Toggle option that shows yearly pricing' },\n { ref: 'selectPlan', kind: LabelKind.BUTTON, purpose: 'Call-to-action that selects a plan the customer is not yet on' },\n { ref: 'currentPlan', kind: LabelKind.LABEL, purpose: \"Label on the tile for the customer's current plan\" },\n { ref: 'upgradePlan', kind: LabelKind.BUTTON, purpose: 'Call-to-action that moves the customer to a higher tier' },\n { ref: 'downgradePlan', kind: LabelKind.BUTTON, purpose: 'Call-to-action that moves the customer to a lower tier' },\n { ref: 'contactSales', kind: LabelKind.BUTTON, purpose: 'Call-to-action for enterprise/custom-quote plans' },\n { ref: 'priceOnRequest', kind: LabelKind.LABEL, purpose: 'Shown in place of a price for a plan whose price is quoted on request rather than listed' },\n { ref: 'startingAtPrefix', kind: LabelKind.LABEL, purpose: 'Word placed before a plan price that is only a starting price, because part of the total is quoted (for example \"From\")' },\n { ref: 'comingSoon', kind: LabelKind.BUTTON, purpose: 'Disabled action on a plan that is announced but cannot be bought yet' },\n { ref: 'freePlanLabel', kind: LabelKind.LABEL, purpose: 'Price label shown for a no-cost plan tier' },\n { ref: 'featuresIncluded', kind: LabelKind.HEADING, purpose: \"Heading above a plan's list of included features\" },\n {\n ref: 'everythingInPlan',\n kind: LabelKind.LABEL,\n purpose: 'Lead-in noting a tier inherits all features of the plan below it',\n params: [{ key: 'plan', meaning: 'name of the lower plan whose features are inherited' }],\n },\n {\n ref: 'priceDisplay',\n kind: LabelKind.LABEL,\n purpose: 'Formats the headline price for a plan tier',\n params: [\n { key: 'amount', meaning: 'plan price amount' },\n { key: 'currency', meaning: 'ISO currency code of the price' },\n ],\n },\n {\n ref: 'limitDisplay',\n kind: LabelKind.LABEL,\n purpose: 'Formats a numeric quota/limit for a plan feature',\n params: [{ key: 'value', meaning: 'numeric limit for the feature' }],\n },\n { ref: 'unlimited', kind: LabelKind.LABEL, purpose: 'Shown in place of a number when a feature has no quota cap' },\n { ref: 'intervalToggleLabel', kind: LabelKind.LABEL, purpose: 'Accessible label for the monthly/yearly billing toggle' },\n {\n ref: 'trialDays',\n kind: LabelKind.LABEL,\n purpose: 'Notes the length of the free trial offered with a plan',\n params: [{ key: 'days', meaning: 'number of free trial days' }],\n },\n];\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_BILLING_PRICING_TABLE, LowLevelBillingPricingTableLabels);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billing-usage-dashboard.d.ts","sourceRoot":"","sources":["../../../../../src/components/billing/billing-usage-dashboard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,EAeL,mBAAmB,EACpB,MAAM,6BAA6B,CAAC;AASrC,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,WAAW,EACX,OAAO,EACP,SAAS,EACT,KAAK,EACL,gBAAgB,EAChB,sBAAsB,GACvB,EAAE,mBAAmB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"billing-usage-dashboard.d.ts","sourceRoot":"","sources":["../../../../../src/components/billing/billing-usage-dashboard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,EAeL,mBAAmB,EACpB,MAAM,6BAA6B,CAAC;AASrC,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,WAAW,EACX,OAAO,EACP,SAAS,EACT,KAAK,EACL,gBAAgB,EAChB,sBAAsB,GACvB,EAAE,mBAAmB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CAkMhD"}
|
|
@@ -44,10 +44,13 @@ export function UsageDashboard({ products, creditPools, onTopUp, isLoading, erro
|
|
|
44
44
|
? t('usageOf', { current: formatNumber(product.currentPeriodUsage), limit: formatNumber(product.limit) })
|
|
45
45
|
: formatNumber(product.currentPeriodUsage) }), usagePercentage !== null && (_jsx("div", { className: "h-2 bg-muted-foreground/20 rounded-full overflow-hidden", role: "progressbar", "aria-valuenow": product.currentPeriodUsage, "aria-valuemin": 0, "aria-valuemax": product.limit ?? 100, "aria-label": t('productUsageAriaLabel', { product: product.productName, current: formatNumber(product.currentPeriodUsage), limit: formatNumber(product.limit ?? 0) }), children: _jsx("div", { className: cn("h-full rounded-full duration-[var(--motion-duration-fast)] ease-[var(--motion-easing-default)] transition-[width] motion-reduce:transition-none", usagePercentage >= 100 ? 'bg-destructive' : usagePercentage >= 80 ? 'bg-warning' : 'bg-primary'), style: { width: `${usagePercentage}%` } }) }))] }) }, product.productKey));
|
|
46
46
|
}) })] })), !creditPoolsUnavailable && creditPools.length > 0 && (_jsxs("div", { className: "space-y-card", children: [_jsx("p", { className: cn(descriptionRecipe.base, "font-medium"), children: t('creditsTitle') }), _jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-card", children: creditPools.map(pool => {
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
// Everything the pool ever received: purchased and granted (#1802). Consumption is measured against
|
|
48
|
+
// both, or a pool topped up by a referral reward would read above 100%.
|
|
49
|
+
const totalReceived = pool.totalPurchased + (pool.totalGranted ?? 0);
|
|
50
|
+
const usagePercentage = totalReceived > 0
|
|
51
|
+
? Math.round((pool.totalConsumed / totalReceived) * 100)
|
|
49
52
|
: 0;
|
|
50
|
-
return (_jsx(Surface, { asChild: true, emitPolicyVars: false, variant: SurfaceVariant.BASE, children: _jsxs("div", { className: cn("p-card", surfaceRecipe.base), children: [_jsx("h4", { className: cn(descriptionRecipe.base, "font-medium text-foreground mb-section"), children: pool.poolName }), _jsxs("div", { className: "space-y-element", children: [_jsxs("div", { className: cn("flex justify-between", descriptionRecipe.base), children: [_jsx("span", { className: descriptionRecipe.base, children: t('availableCredits') }), _jsx("span", { className: cn("font-semibold text-foreground"), children: formatNumber(pool.available) })] }), _jsxs("div", { className: cn("flex justify-between", descriptionRecipe.base), children: [_jsx("span", { className: descriptionRecipe.base, children: t('totalPurchased') }), _jsx("span", { className: "text-foreground", children: formatNumber(pool.totalPurchased) })] }), _jsxs("div", { className: cn("flex justify-between", descriptionRecipe.base), children: [_jsx("span", { className: descriptionRecipe.base, children: t('totalConsumed') }), _jsx("span", { className: "text-foreground", children: formatNumber(pool.totalConsumed) })] })] }),
|
|
53
|
+
return (_jsx(Surface, { asChild: true, emitPolicyVars: false, variant: SurfaceVariant.BASE, children: _jsxs("div", { className: cn("p-card", surfaceRecipe.base), children: [_jsx("h4", { className: cn(descriptionRecipe.base, "font-medium text-foreground mb-section"), children: pool.poolName }), _jsxs("div", { className: "space-y-element", children: [_jsxs("div", { className: cn("flex justify-between", descriptionRecipe.base), children: [_jsx("span", { className: descriptionRecipe.base, children: t('availableCredits') }), _jsx("span", { className: cn("font-semibold text-foreground"), children: formatNumber(pool.available) })] }), _jsxs("div", { className: cn("flex justify-between", descriptionRecipe.base), children: [_jsx("span", { className: descriptionRecipe.base, children: t('totalPurchased') }), _jsx("span", { className: "text-foreground", children: formatNumber(pool.totalPurchased) })] }), (pool.totalGranted ?? 0) > 0 && (_jsxs("div", { className: cn("flex justify-between", descriptionRecipe.base), children: [_jsx("span", { className: descriptionRecipe.base, children: t('totalGranted') }), _jsx("span", { className: "text-foreground", children: formatNumber(pool.totalGranted) })] })), _jsxs("div", { className: cn("flex justify-between", descriptionRecipe.base), children: [_jsx("span", { className: descriptionRecipe.base, children: t('totalConsumed') }), _jsx("span", { className: "text-foreground", children: formatNumber(pool.totalConsumed) })] })] }), totalReceived > 0 && (_jsx("div", { className: "mt-element h-2 bg-muted-foreground/20 rounded-full overflow-hidden", role: "progressbar", "aria-valuenow": pool.totalConsumed, "aria-valuemin": 0, "aria-valuemax": totalReceived, "aria-label": t('creditPoolAriaLabel', { pool: pool.poolName, consumed: formatNumber(pool.totalConsumed), total: formatNumber(totalReceived) }), children: _jsx("div", { className: cn("h-full rounded-full duration-[var(--motion-duration-fast)] ease-[var(--motion-easing-default)] transition-[width] motion-reduce:transition-none", usagePercentage >= 90 ? 'bg-destructive' : usagePercentage >= 70 ? 'bg-warning' : 'bg-primary'), style: { width: `${usagePercentage}%` } }) })), onTopUp && (_jsxs(Button, { variant: ButtonVariants_Variant.SECONDARY, size: ButtonSize.SM, className: "mt-section w-full", onClick: () => onTopUp(pool.poolKey), children: [renderIcon(StandardIconReference.PLUS, { size: IconSize.SM }), t('topUpCredits')] }))] }) }, pool.poolKey));
|
|
51
54
|
}) })] }))] }));
|
|
52
55
|
}
|
|
53
56
|
//# sourceMappingURL=billing-usage-dashboard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billing-usage-dashboard.js","sourceRoot":"","sources":["../../../../../src/components/billing/billing-usage-dashboard.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * UsageDashboard (Preset)\n *\n * Displays usage/consumption overview for metered products and credit pool balances.\n * Reads from UsageSummary data provided by BillingContext.\n *\n * Formatting: Uses useI18n() for locale-aware formatting\n * of numbers, respecting user/org regional preferences.\n */\n\nimport React, { useMemo } from 'react';\nimport { ButtonSize, FrontendComponentType, SurfaceVariant, TypographyVariant, UIBehavior } from '@wildo-ai/presets-components-models';\nimport {\n cn,\n useI18n,\n useIconRegistry,\n StandardIconReference,\n IconSize,\n useUI,\n Button,\n ButtonVariants_Variant,\n Skeleton,\n Alert,\n AlertDescription,\n Surface,\n UsageDashboardCreditPool,\n UsageDashboardProduct,\n UsageDashboardProps,\n} from '@wildo-ai/saas-frontend-lib';\n\n// The label contract for this component (keys + params + per-key purpose / kind\n// / variable meaning) lives in the co-located, companion-only\n// `billing-usage-dashboard.labels.ts` — statically scanned by the dev companion,\n// never imported at runtime (so it stays out of the browser bundle).\n\n// ── Component ───────────────────────────────────────────────────────\n\nexport function UsageDashboard({\n products,\n creditPools,\n onTopUp,\n isLoading,\n error,\n usageUnavailable,\n creditPoolsUnavailable,\n}: UsageDashboardProps): React.JSX.Element | null {\n const { getRecipe } = useUI();\n const { makeTrComponent, formatNumber, isReady } = useI18n({ component: FrontendComponentType.LOW_LEVEL_BILLING_USAGE_DASHBOARD });\n const { renderIcon } = useIconRegistry();\n\n const surfaceRecipe = getRecipe(UIBehavior.SURFACE, SurfaceVariant.BASE);\n const headingRecipe = getRecipe(UIBehavior.TYPOGRAPHY, TypographyVariant.HEADING);\n const descriptionRecipe = getRecipe(UIBehavior.TYPOGRAPHY, TypographyVariant.DESCRIPTION);\n\n const t = useMemo(\n () => makeTrComponent(FrontendComponentType.LOW_LEVEL_BILLING_USAGE_DASHBOARD),\n [makeTrComponent],\n );\n\n if (error) {\n return (\n <Alert variant=\"destructive\">\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n );\n }\n\n if (isLoading) {\n return (\n <div className=\"space-y-section\">\n <Skeleton className=\"h-5 w-36\" />\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-card\">\n {[0, 1].map(i => (\n <Surface key={i} asChild emitPolicyVars={false} variant={SurfaceVariant.BASE}>\n <div className={cn(\"p-card\", surfaceRecipe.base)}>\n <Skeleton className=\"h-4 w-28 mb-element\" />\n <Skeleton className=\"h-7 w-20 mb-element\" />\n <Skeleton className=\"h-2 w-full rounded-full\" />\n </div>\n </Surface>\n ))}\n </div>\n </div>\n );\n }\n\n if (!isReady) return null;\n\n const isEmpty = !usageUnavailable && !creditPoolsUnavailable && products.length === 0 && creditPools.length === 0;\n\n return (\n <div className=\"space-y-section\">\n <h3 className={cn(headingRecipe.base, headingRecipe.sizes?.md)}>{t('title')}</h3>\n\n {usageUnavailable && <Alert variant=\"destructive\"><AlertDescription>{t('usageUnavailable')}</AlertDescription></Alert>}\n {creditPoolsUnavailable && <Alert variant=\"destructive\"><AlertDescription>{t('creditPoolsUnavailable')}</AlertDescription></Alert>}\n {isEmpty && (\n <Surface asChild emitPolicyVars={false} variant={SurfaceVariant.BASE}>\n <div className={cn(\"p-card text-center\", surfaceRecipe.base)}>\n <p className={descriptionRecipe.base}>{t('noUsageData')}</p>\n </div>\n </Surface>\n )}\n\n {/* Metered product usage */}\n {!usageUnavailable && products.length > 0 && (\n <div className=\"space-y-card\">\n <p className={cn(descriptionRecipe.base, \"font-medium\")}>{t('currentPeriod')}</p>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-card\">\n {products.map(product => {\n const usagePercentage = product.limit\n ? Math.min(100, Math.round((product.currentPeriodUsage / product.limit) * 100))\n : null;\n const trend = product.previousPeriodUsage != null && product.previousPeriodUsage > 0\n ? Math.round(((product.currentPeriodUsage - product.previousPeriodUsage) / product.previousPeriodUsage) * 100)\n : null;\n\n return (\n <Surface key={product.productKey} asChild emitPolicyVars={false} variant={SurfaceVariant.BASE}>\n <div className={cn(\"p-card\", surfaceRecipe.base)}>\n <div className=\"flex items-center justify-between mb-element\">\n <h4 className={cn(descriptionRecipe.base, \"font-medium text-foreground\")}>{product.productName}</h4>\n {trend !== null && (\n <span className={cn(\"text-xs font-medium\", trend >= 0 ? 'text-success' : 'text-destructive')}>\n {t('trendVsPrevious', { percentage: `${trend >= 0 ? '+' : ''}${trend}%` })}\n </span>\n )}\n </div>\n\n <div className={cn(headingRecipe.base, \"text-2xl mb-element\")}>\n {product.limit\n ? t('usageOf', { current: formatNumber(product.currentPeriodUsage), limit: formatNumber(product.limit) })\n : formatNumber(product.currentPeriodUsage)}\n </div>\n\n {usagePercentage !== null && (\n <div\n className=\"h-2 bg-muted-foreground/20 rounded-full overflow-hidden\"\n role=\"progressbar\"\n aria-valuenow={product.currentPeriodUsage}\n aria-valuemin={0}\n aria-valuemax={product.limit ?? 100}\n aria-label={t('productUsageAriaLabel', { product: product.productName, current: formatNumber(product.currentPeriodUsage), limit: formatNumber(product.limit ?? 0) })}\n >\n <div\n className={cn(\n \"h-full rounded-full duration-[var(--motion-duration-fast)] ease-[var(--motion-easing-default)] transition-[width] motion-reduce:transition-none\",\n usagePercentage >= 100 ? 'bg-destructive' : usagePercentage >= 80 ? 'bg-warning' : 'bg-primary',\n )}\n style={{ width: `${usagePercentage}%` }}\n />\n </div>\n )}\n </div>\n </Surface>\n );\n })}\n </div>\n </div>\n )}\n\n {/* Credit pools */}\n {!creditPoolsUnavailable && creditPools.length > 0 && (\n <div className=\"space-y-card\">\n <p className={cn(descriptionRecipe.base, \"font-medium\")}>{t('creditsTitle')}</p>\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-card\">\n {creditPools.map(pool => {\n const usagePercentage = pool.totalPurchased > 0\n ? Math.round((pool.totalConsumed / pool.totalPurchased) * 100)\n : 0;\n\n return (\n <Surface key={pool.poolKey} asChild emitPolicyVars={false} variant={SurfaceVariant.BASE}>\n <div className={cn(\"p-card\", surfaceRecipe.base)}>\n <h4 className={cn(descriptionRecipe.base, \"font-medium text-foreground mb-section\")}>{pool.poolName}</h4>\n\n <div className=\"space-y-element\">\n <div className={cn(\"flex justify-between\", descriptionRecipe.base)}>\n <span className={descriptionRecipe.base}>{t('availableCredits')}</span>\n <span className={cn(\"font-semibold text-foreground\")}>{formatNumber(pool.available)}</span>\n </div>\n <div className={cn(\"flex justify-between\", descriptionRecipe.base)}>\n <span className={descriptionRecipe.base}>{t('totalPurchased')}</span>\n <span className=\"text-foreground\">{formatNumber(pool.totalPurchased)}</span>\n </div>\n <div className={cn(\"flex justify-between\", descriptionRecipe.base)}>\n <span className={descriptionRecipe.base}>{t('totalConsumed')}</span>\n <span className=\"text-foreground\">{formatNumber(pool.totalConsumed)}</span>\n </div>\n </div>\n\n {pool.totalPurchased > 0 && (\n <div\n className=\"mt-element h-2 bg-muted-foreground/20 rounded-full overflow-hidden\"\n role=\"progressbar\"\n aria-valuenow={pool.totalConsumed}\n aria-valuemin={0}\n aria-valuemax={pool.totalPurchased}\n aria-label={t('creditPoolAriaLabel', { pool: pool.poolName, consumed: formatNumber(pool.totalConsumed), total: formatNumber(pool.totalPurchased) })}\n >\n <div\n className={cn(\n \"h-full rounded-full duration-[var(--motion-duration-fast)] ease-[var(--motion-easing-default)] transition-[width] motion-reduce:transition-none\",\n usagePercentage >= 90 ? 'bg-destructive' : usagePercentage >= 70 ? 'bg-warning' : 'bg-primary',\n )}\n style={{ width: `${usagePercentage}%` }}\n />\n </div>\n )}\n\n {onTopUp && (\n <Button\n variant={ButtonVariants_Variant.SECONDARY}\n size={ButtonSize.SM}\n className=\"mt-section w-full\"\n onClick={() => onTopUp(pool.poolKey)}\n >\n {renderIcon(StandardIconReference.PLUS, { size: IconSize.SM })}\n {t('topUpCredits')}\n </Button>\n )}\n </div>\n </Surface>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"billing-usage-dashboard.js","sourceRoot":"","sources":["../../../../../src/components/billing/billing-usage-dashboard.tsx"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;AAEH,OAAc,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,cAAc,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACvI,OAAO,EACL,EAAE,EACF,OAAO,EACP,eAAe,EACf,qBAAqB,EACrB,QAAQ,EACR,KAAK,EACL,MAAM,EACN,sBAAsB,EACtB,QAAQ,EACR,KAAK,EACL,gBAAgB,EAChB,OAAO,GAIR,MAAM,6BAA6B,CAAC;AAErC,gFAAgF;AAChF,8DAA8D;AAC9D,iFAAiF;AACjF,qEAAqE;AAErE,uEAAuE;AAEvE,MAAM,UAAU,cAAc,CAAC,EAC7B,QAAQ,EACR,WAAW,EACX,OAAO,EACP,SAAS,EACT,KAAK,EACL,gBAAgB,EAChB,sBAAsB,GACF;IACpB,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,CAAC;IAC9B,MAAM,EAAE,eAAe,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,EAAE,SAAS,EAAE,qBAAqB,CAAC,iCAAiC,EAAE,CAAC,CAAC;IACnI,MAAM,EAAE,UAAU,EAAE,GAAG,eAAe,EAAE,CAAC;IAEzC,MAAM,aAAa,GAAG,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC;IACzE,MAAM,aAAa,GAAG,SAAS,CAAC,UAAU,CAAC,UAAU,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAClF,MAAM,iBAAiB,GAAG,SAAS,CAAC,UAAU,CAAC,UAAU,EAAE,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAE1F,MAAM,CAAC,GAAG,OAAO,CACf,GAAG,EAAE,CAAC,eAAe,CAAC,qBAAqB,CAAC,iCAAiC,CAAC,EAC9E,CAAC,eAAe,CAAC,CAClB,CAAC;IAEF,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CACL,KAAC,KAAK,IAAC,OAAO,EAAC,aAAa,YAC1B,KAAC,gBAAgB,cAAE,KAAK,GAAoB,GACtC,CACT,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CACL,eAAK,SAAS,EAAC,iBAAiB,aAC9B,KAAC,QAAQ,IAAC,SAAS,EAAC,UAAU,GAAG,EACjC,cAAK,SAAS,EAAC,0CAA0C,YACtD,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CACf,KAAC,OAAO,IAAS,OAAO,QAAC,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,CAAC,IAAI,YAC1E,eAAK,SAAS,EAAE,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,aAC9C,KAAC,QAAQ,IAAC,SAAS,EAAC,qBAAqB,GAAG,EAC5C,KAAC,QAAQ,IAAC,SAAS,EAAC,qBAAqB,GAAG,EAC5C,KAAC,QAAQ,IAAC,SAAS,EAAC,yBAAyB,GAAG,IAC5C,IALM,CAAC,CAML,CACX,CAAC,GACE,IACF,CACP,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,MAAM,OAAO,GAAG,CAAC,gBAAgB,IAAI,CAAC,sBAAsB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC;IAElH,OAAO,CACL,eAAK,SAAS,EAAC,iBAAiB,aAC9B,aAAI,SAAS,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,aAAa,CAAC,KAAK,EAAE,EAAE,CAAC,YAAG,CAAC,CAAC,OAAO,CAAC,GAAM,EAEhF,gBAAgB,IAAI,KAAC,KAAK,IAAC,OAAO,EAAC,aAAa,YAAC,KAAC,gBAAgB,cAAE,CAAC,CAAC,kBAAkB,CAAC,GAAoB,GAAQ,EACrH,sBAAsB,IAAI,KAAC,KAAK,IAAC,OAAO,EAAC,aAAa,YAAC,KAAC,gBAAgB,cAAE,CAAC,CAAC,wBAAwB,CAAC,GAAoB,GAAQ,EACjI,OAAO,IAAI,CACV,KAAC,OAAO,IAAC,OAAO,QAAC,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,CAAC,IAAI,YAClE,cAAK,SAAS,EAAE,EAAE,CAAC,oBAAoB,EAAE,aAAa,CAAC,IAAI,CAAC,YAC1D,YAAG,SAAS,EAAE,iBAAiB,CAAC,IAAI,YAAG,CAAC,CAAC,aAAa,CAAC,GAAK,GACxD,GACE,CACX,EAGA,CAAC,gBAAgB,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAC3C,eAAK,SAAS,EAAC,cAAc,aAC3B,YAAG,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,aAAa,CAAC,YAAG,CAAC,CAAC,eAAe,CAAC,GAAK,EACjF,cAAK,SAAS,EAAC,0CAA0C,YACtD,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;4BACtB,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK;gCACnC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;gCAC/E,CAAC,CAAC,IAAI,CAAC;4BACT,MAAM,KAAK,GAAG,OAAO,CAAC,mBAAmB,IAAI,IAAI,IAAI,OAAO,CAAC,mBAAmB,GAAG,CAAC;gCAClF,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG,GAAG,CAAC;gCAC9G,CAAC,CAAC,IAAI,CAAC;4BAET,OAAO,CACL,KAAC,OAAO,IAA0B,OAAO,QAAC,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,CAAC,IAAI,YAC3F,eAAK,SAAS,EAAE,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,aAC9C,eAAK,SAAS,EAAC,8CAA8C,aAC3D,aAAI,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,6BAA6B,CAAC,YAAG,OAAO,CAAC,WAAW,GAAM,EACnG,KAAK,KAAK,IAAI,IAAI,CACjB,eAAM,SAAS,EAAE,EAAE,CAAC,qBAAqB,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,kBAAkB,CAAC,YACzF,CAAC,CAAC,iBAAiB,EAAE,EAAE,UAAU,EAAE,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,GAAG,EAAE,CAAC,GACrE,CACR,IACG,EAEN,cAAK,SAAS,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,qBAAqB,CAAC,YAC1D,OAAO,CAAC,KAAK;gDACZ,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gDACzG,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,kBAAkB,CAAC,GACxC,EAEL,eAAe,KAAK,IAAI,IAAI,CAC3B,cACE,SAAS,EAAC,yDAAyD,EACnE,IAAI,EAAC,aAAa,mBACH,OAAO,CAAC,kBAAkB,mBAC1B,CAAC,mBACD,OAAO,CAAC,KAAK,IAAI,GAAG,gBACvB,CAAC,CAAC,uBAAuB,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,YAEpK,cACE,SAAS,EAAE,EAAE,CACX,iJAAiJ,EACjJ,eAAe,IAAI,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAChG,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,eAAe,GAAG,EAAE,GACvC,GACE,CACP,IACG,IAnCM,OAAO,CAAC,UAAU,CAoCtB,CACX,CAAC;wBACJ,CAAC,CAAC,GACE,IACF,CACP,EAGA,CAAC,sBAAsB,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CACpD,eAAK,SAAS,EAAC,cAAc,aAC3B,YAAG,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,aAAa,CAAC,YAAG,CAAC,CAAC,cAAc,CAAC,GAAK,EAChF,cAAK,SAAS,EAAC,yDAAyD,YACrE,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;4BACtB,oGAAoG;4BACpG,wEAAwE;4BACxE,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC;4BACrE,MAAM,eAAe,GAAG,aAAa,GAAG,CAAC;gCACvC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC,GAAG,GAAG,CAAC;gCACxD,CAAC,CAAC,CAAC,CAAC;4BAEN,OAAO,CACL,KAAC,OAAO,IAAoB,OAAO,QAAC,cAAc,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,CAAC,IAAI,YACrF,eAAK,SAAS,EAAE,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,aAC9C,aAAI,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,wCAAwC,CAAC,YAAG,IAAI,CAAC,QAAQ,GAAM,EAEzG,eAAK,SAAS,EAAC,iBAAiB,aAC9B,eAAK,SAAS,EAAE,EAAE,CAAC,sBAAsB,EAAE,iBAAiB,CAAC,IAAI,CAAC,aAChE,eAAM,SAAS,EAAE,iBAAiB,CAAC,IAAI,YAAG,CAAC,CAAC,kBAAkB,CAAC,GAAQ,EACvE,eAAM,SAAS,EAAE,EAAE,CAAC,+BAA+B,CAAC,YAAG,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,GAAQ,IACvF,EACN,eAAK,SAAS,EAAE,EAAE,CAAC,sBAAsB,EAAE,iBAAiB,CAAC,IAAI,CAAC,aAChE,eAAM,SAAS,EAAE,iBAAiB,CAAC,IAAI,YAAG,CAAC,CAAC,gBAAgB,CAAC,GAAQ,EACrE,eAAM,SAAS,EAAC,iBAAiB,YAAE,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,GAAQ,IACxE,EACL,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAC/B,eAAK,SAAS,EAAE,EAAE,CAAC,sBAAsB,EAAE,iBAAiB,CAAC,IAAI,CAAC,aAChE,eAAM,SAAS,EAAE,iBAAiB,CAAC,IAAI,YAAG,CAAC,CAAC,cAAc,CAAC,GAAQ,EACnE,eAAM,SAAS,EAAC,iBAAiB,YAAE,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,GAAQ,IACtE,CACP,EACD,eAAK,SAAS,EAAE,EAAE,CAAC,sBAAsB,EAAE,iBAAiB,CAAC,IAAI,CAAC,aAChE,eAAM,SAAS,EAAE,iBAAiB,CAAC,IAAI,YAAG,CAAC,CAAC,eAAe,CAAC,GAAQ,EACpE,eAAM,SAAS,EAAC,iBAAiB,YAAE,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,GAAQ,IACvE,IACF,EAEL,aAAa,GAAG,CAAC,IAAI,CACpB,cACE,SAAS,EAAC,oEAAoE,EAC9E,IAAI,EAAC,aAAa,mBACH,IAAI,CAAC,aAAa,mBAClB,CAAC,mBACD,aAAa,gBAChB,CAAC,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,aAAa,CAAC,EAAE,CAAC,YAE7I,cACE,SAAS,EAAE,EAAE,CACX,iJAAiJ,EACjJ,eAAe,IAAI,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAC/F,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,eAAe,GAAG,EAAE,GACvC,GACE,CACP,EAEA,OAAO,IAAI,CACV,MAAC,MAAM,IACL,OAAO,EAAE,sBAAsB,CAAC,SAAS,EACzC,IAAI,EAAE,UAAU,CAAC,EAAE,EACnB,SAAS,EAAC,mBAAmB,EAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAEnC,UAAU,CAAC,qBAAqB,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,EAC7D,CAAC,CAAC,cAAc,CAAC,IACX,CACV,IACG,IAvDM,IAAI,CAAC,OAAO,CAwDhB,CACX,CAAC;wBACJ,CAAC,CAAC,GACE,IACF,CACP,IACG,CACP,CAAC;AACJ,CAAC","sourcesContent":["/**\n * UsageDashboard (Preset)\n *\n * Displays usage/consumption overview for metered products and credit pool balances.\n * Reads from UsageSummary data provided by BillingContext.\n *\n * Formatting: Uses useI18n() for locale-aware formatting\n * of numbers, respecting user/org regional preferences.\n */\n\nimport React, { useMemo } from 'react';\nimport { ButtonSize, FrontendComponentType, SurfaceVariant, TypographyVariant, UIBehavior } from '@wildo-ai/presets-components-models';\nimport {\n cn,\n useI18n,\n useIconRegistry,\n StandardIconReference,\n IconSize,\n useUI,\n Button,\n ButtonVariants_Variant,\n Skeleton,\n Alert,\n AlertDescription,\n Surface,\n UsageDashboardCreditPool,\n UsageDashboardProduct,\n UsageDashboardProps,\n} from '@wildo-ai/saas-frontend-lib';\n\n// The label contract for this component (keys + params + per-key purpose / kind\n// / variable meaning) lives in the co-located, companion-only\n// `billing-usage-dashboard.labels.ts` — statically scanned by the dev companion,\n// never imported at runtime (so it stays out of the browser bundle).\n\n// ── Component ───────────────────────────────────────────────────────\n\nexport function UsageDashboard({\n products,\n creditPools,\n onTopUp,\n isLoading,\n error,\n usageUnavailable,\n creditPoolsUnavailable,\n}: UsageDashboardProps): React.JSX.Element | null {\n const { getRecipe } = useUI();\n const { makeTrComponent, formatNumber, isReady } = useI18n({ component: FrontendComponentType.LOW_LEVEL_BILLING_USAGE_DASHBOARD });\n const { renderIcon } = useIconRegistry();\n\n const surfaceRecipe = getRecipe(UIBehavior.SURFACE, SurfaceVariant.BASE);\n const headingRecipe = getRecipe(UIBehavior.TYPOGRAPHY, TypographyVariant.HEADING);\n const descriptionRecipe = getRecipe(UIBehavior.TYPOGRAPHY, TypographyVariant.DESCRIPTION);\n\n const t = useMemo(\n () => makeTrComponent(FrontendComponentType.LOW_LEVEL_BILLING_USAGE_DASHBOARD),\n [makeTrComponent],\n );\n\n if (error) {\n return (\n <Alert variant=\"destructive\">\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n );\n }\n\n if (isLoading) {\n return (\n <div className=\"space-y-section\">\n <Skeleton className=\"h-5 w-36\" />\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-card\">\n {[0, 1].map(i => (\n <Surface key={i} asChild emitPolicyVars={false} variant={SurfaceVariant.BASE}>\n <div className={cn(\"p-card\", surfaceRecipe.base)}>\n <Skeleton className=\"h-4 w-28 mb-element\" />\n <Skeleton className=\"h-7 w-20 mb-element\" />\n <Skeleton className=\"h-2 w-full rounded-full\" />\n </div>\n </Surface>\n ))}\n </div>\n </div>\n );\n }\n\n if (!isReady) return null;\n\n const isEmpty = !usageUnavailable && !creditPoolsUnavailable && products.length === 0 && creditPools.length === 0;\n\n return (\n <div className=\"space-y-section\">\n <h3 className={cn(headingRecipe.base, headingRecipe.sizes?.md)}>{t('title')}</h3>\n\n {usageUnavailable && <Alert variant=\"destructive\"><AlertDescription>{t('usageUnavailable')}</AlertDescription></Alert>}\n {creditPoolsUnavailable && <Alert variant=\"destructive\"><AlertDescription>{t('creditPoolsUnavailable')}</AlertDescription></Alert>}\n {isEmpty && (\n <Surface asChild emitPolicyVars={false} variant={SurfaceVariant.BASE}>\n <div className={cn(\"p-card text-center\", surfaceRecipe.base)}>\n <p className={descriptionRecipe.base}>{t('noUsageData')}</p>\n </div>\n </Surface>\n )}\n\n {/* Metered product usage */}\n {!usageUnavailable && products.length > 0 && (\n <div className=\"space-y-card\">\n <p className={cn(descriptionRecipe.base, \"font-medium\")}>{t('currentPeriod')}</p>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-card\">\n {products.map(product => {\n const usagePercentage = product.limit\n ? Math.min(100, Math.round((product.currentPeriodUsage / product.limit) * 100))\n : null;\n const trend = product.previousPeriodUsage != null && product.previousPeriodUsage > 0\n ? Math.round(((product.currentPeriodUsage - product.previousPeriodUsage) / product.previousPeriodUsage) * 100)\n : null;\n\n return (\n <Surface key={product.productKey} asChild emitPolicyVars={false} variant={SurfaceVariant.BASE}>\n <div className={cn(\"p-card\", surfaceRecipe.base)}>\n <div className=\"flex items-center justify-between mb-element\">\n <h4 className={cn(descriptionRecipe.base, \"font-medium text-foreground\")}>{product.productName}</h4>\n {trend !== null && (\n <span className={cn(\"text-xs font-medium\", trend >= 0 ? 'text-success' : 'text-destructive')}>\n {t('trendVsPrevious', { percentage: `${trend >= 0 ? '+' : ''}${trend}%` })}\n </span>\n )}\n </div>\n\n <div className={cn(headingRecipe.base, \"text-2xl mb-element\")}>\n {product.limit\n ? t('usageOf', { current: formatNumber(product.currentPeriodUsage), limit: formatNumber(product.limit) })\n : formatNumber(product.currentPeriodUsage)}\n </div>\n\n {usagePercentage !== null && (\n <div\n className=\"h-2 bg-muted-foreground/20 rounded-full overflow-hidden\"\n role=\"progressbar\"\n aria-valuenow={product.currentPeriodUsage}\n aria-valuemin={0}\n aria-valuemax={product.limit ?? 100}\n aria-label={t('productUsageAriaLabel', { product: product.productName, current: formatNumber(product.currentPeriodUsage), limit: formatNumber(product.limit ?? 0) })}\n >\n <div\n className={cn(\n \"h-full rounded-full duration-[var(--motion-duration-fast)] ease-[var(--motion-easing-default)] transition-[width] motion-reduce:transition-none\",\n usagePercentage >= 100 ? 'bg-destructive' : usagePercentage >= 80 ? 'bg-warning' : 'bg-primary',\n )}\n style={{ width: `${usagePercentage}%` }}\n />\n </div>\n )}\n </div>\n </Surface>\n );\n })}\n </div>\n </div>\n )}\n\n {/* Credit pools */}\n {!creditPoolsUnavailable && creditPools.length > 0 && (\n <div className=\"space-y-card\">\n <p className={cn(descriptionRecipe.base, \"font-medium\")}>{t('creditsTitle')}</p>\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-card\">\n {creditPools.map(pool => {\n // Everything the pool ever received: purchased and granted (#1802). Consumption is measured against\n // both, or a pool topped up by a referral reward would read above 100%.\n const totalReceived = pool.totalPurchased + (pool.totalGranted ?? 0);\n const usagePercentage = totalReceived > 0\n ? Math.round((pool.totalConsumed / totalReceived) * 100)\n : 0;\n\n return (\n <Surface key={pool.poolKey} asChild emitPolicyVars={false} variant={SurfaceVariant.BASE}>\n <div className={cn(\"p-card\", surfaceRecipe.base)}>\n <h4 className={cn(descriptionRecipe.base, \"font-medium text-foreground mb-section\")}>{pool.poolName}</h4>\n\n <div className=\"space-y-element\">\n <div className={cn(\"flex justify-between\", descriptionRecipe.base)}>\n <span className={descriptionRecipe.base}>{t('availableCredits')}</span>\n <span className={cn(\"font-semibold text-foreground\")}>{formatNumber(pool.available)}</span>\n </div>\n <div className={cn(\"flex justify-between\", descriptionRecipe.base)}>\n <span className={descriptionRecipe.base}>{t('totalPurchased')}</span>\n <span className=\"text-foreground\">{formatNumber(pool.totalPurchased)}</span>\n </div>\n {(pool.totalGranted ?? 0) > 0 && (\n <div className={cn(\"flex justify-between\", descriptionRecipe.base)}>\n <span className={descriptionRecipe.base}>{t('totalGranted')}</span>\n <span className=\"text-foreground\">{formatNumber(pool.totalGranted)}</span>\n </div>\n )}\n <div className={cn(\"flex justify-between\", descriptionRecipe.base)}>\n <span className={descriptionRecipe.base}>{t('totalConsumed')}</span>\n <span className=\"text-foreground\">{formatNumber(pool.totalConsumed)}</span>\n </div>\n </div>\n\n {totalReceived > 0 && (\n <div\n className=\"mt-element h-2 bg-muted-foreground/20 rounded-full overflow-hidden\"\n role=\"progressbar\"\n aria-valuenow={pool.totalConsumed}\n aria-valuemin={0}\n aria-valuemax={totalReceived}\n aria-label={t('creditPoolAriaLabel', { pool: pool.poolName, consumed: formatNumber(pool.totalConsumed), total: formatNumber(totalReceived) })}\n >\n <div\n className={cn(\n \"h-full rounded-full duration-[var(--motion-duration-fast)] ease-[var(--motion-easing-default)] transition-[width] motion-reduce:transition-none\",\n usagePercentage >= 90 ? 'bg-destructive' : usagePercentage >= 70 ? 'bg-warning' : 'bg-primary',\n )}\n style={{ width: `${usagePercentage}%` }}\n />\n </div>\n )}\n\n {onTopUp && (\n <Button\n variant={ButtonVariants_Variant.SECONDARY}\n size={ButtonSize.SM}\n className=\"mt-section w-full\"\n onClick={() => onTopUp(pool.poolKey)}\n >\n {renderIcon(StandardIconReference.PLUS, { size: IconSize.SM })}\n {t('topUpCredits')}\n </Button>\n )}\n </div>\n </Surface>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billing-usage-dashboard.labels.d.ts","sourceRoot":"","sources":["../../../../../src/components/billing/billing-usage-dashboard.labels.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,mBAAmB,EAEzB,MAAM,qCAAqC,CAAC;AAa7C,eAAO,MAAM,mCAAmC,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"billing-usage-dashboard.labels.d.ts","sourceRoot":"","sources":["../../../../../src/components/billing/billing-usage-dashboard.labels.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,mBAAmB,EAEzB,MAAM,qCAAqC,CAAC;AAa7C,eAAO,MAAM,mCAAmC,EAAE,mBAAmB,EAgDpE,CAAC"}
|
|
@@ -19,6 +19,7 @@ export const LowLevelBillingUsageDashboardLabels = [
|
|
|
19
19
|
{ ref: 'creditsTitle', kind: LabelKind.HEADING, purpose: 'Heading for the credits overview section' },
|
|
20
20
|
{ ref: 'availableCredits', kind: LabelKind.LABEL, purpose: 'Credits the customer can still spend' },
|
|
21
21
|
{ ref: 'totalPurchased', kind: LabelKind.LABEL, purpose: 'Total credits the customer has purchased' },
|
|
22
|
+
{ ref: 'totalGranted', kind: LabelKind.LABEL, purpose: 'Total credits the customer was given without buying them, such as referral rewards' },
|
|
22
23
|
{ ref: 'totalConsumed', kind: LabelKind.LABEL, purpose: 'Total credits the customer has consumed' },
|
|
23
24
|
{
|
|
24
25
|
ref: 'usageOf',
|
|
@@ -54,7 +55,7 @@ export const LowLevelBillingUsageDashboardLabels = [
|
|
|
54
55
|
params: [
|
|
55
56
|
{ key: 'pool', meaning: 'credit-pool name' },
|
|
56
57
|
{ key: 'consumed', meaning: 'credits used from the pool' },
|
|
57
|
-
{ key: 'total', meaning: '
|
|
58
|
+
{ key: 'total', meaning: 'credits the pool received in total, bought and given' },
|
|
58
59
|
],
|
|
59
60
|
},
|
|
60
61
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billing-usage-dashboard.labels.js","sourceRoot":"","sources":["../../../../../src/components/billing/billing-usage-dashboard.labels.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,SAAS,EAET,uBAAuB,GACxB,MAAM,qCAAqC,CAAC;AAE7C,gFAAgF;AAChF,qDAAqD;AACrD,gFAAgF;AAChF,EAAE;AACF,0EAA0E;AAC1E,2EAA2E;AAC3E,4EAA4E;AAC5E,wEAAwE;AACxE,+EAA+E;AAC/E,8EAA8E;AAC9E,kCAAkC;AAClC,MAAM,CAAC,MAAM,mCAAmC,GAA0B;IACxE,EAAE,GAAG,EAAE,kBAAkB,EAAE,IAAI,EAAE,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,yEAAyE,EAAE;IAC5I,EAAE,GAAG,EAAE,wBAAwB,EAAE,IAAI,EAAE,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,uEAAuE,EAAE;IAChJ,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,uCAAuC,EAAE;IAC3F,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,+CAA+C,EAAE;IACzG,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,CAAC,WAAW,EAAE,OAAO,EAAE,sDAAsD,EAAE;IACpH,EAAE,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,0CAA0C,EAAE;IACrG,EAAE,GAAG,EAAE,kBAAkB,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,sCAAsC,EAAE;IACnG,EAAE,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,0CAA0C,EAAE;IACrG,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,yCAAyC,EAAE;IACnG;QACE,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS,CAAC,KAAK;QACrB,OAAO,EAAE,yCAAyC;QAClD,MAAM,EAAE;YACN,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,gCAAgC,EAAE;YAC7D,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,kCAAkC,EAAE;SAC9D;KACF;IACD;QACE,GAAG,EAAE,iBAAiB;QACtB,IAAI,EAAE,SAAS,CAAC,KAAK;QACrB,OAAO,EAAE,mDAAmD;QAC5D,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,iDAAiD,EAAE,CAAC;KAC5F;IACD;QACE,GAAG,EAAE,uBAAuB;QAC5B,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,OAAO,EAAE,sDAAsD;QAC/D,KAAK,EAAE,CAAC,6CAA6C,CAAC;QACtD,MAAM,EAAE;YACN,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,wBAAwB,EAAE;YACrD,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,oBAAoB,EAAE;YACjD,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,wBAAwB,EAAE;SACpD;KACF;IACD;QACE,GAAG,EAAE,qBAAqB;QAC1B,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,OAAO,EAAE,wDAAwD;QACjE,KAAK,EAAE,CAAC,6CAA6C,CAAC;QACtD,MAAM,EAAE;YACN,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE;YAC5C,EAAE,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,4BAA4B,EAAE;YAC1D,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"billing-usage-dashboard.labels.js","sourceRoot":"","sources":["../../../../../src/components/billing/billing-usage-dashboard.labels.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n FrontendComponentType,\n LabelKind,\n type LabellingUnitaryDef,\n registerComponentLabels,\n} from '@wildo-ai/presets-components-models';\n\n// =============================================================================\n// LABEL CONTRACT — LOW_LEVEL_BILLING_USAGE_DASHBOARD\n// =============================================================================\n//\n// Companion-only metadata: the keys this component renders, each with its\n// purpose, UI kind, and per-variable meaning. The dev companion STATICALLY\n// SCANS this file to generate labels + translations — it is NOT imported at\n// runtime, so it never ships in the browser bundle. Co-located with the\n// component on purpose: the author who declares `usageOf` is the one who knows\n// what it means, so the meaning lives here (single source of truth), not in a\n// separate spec that would drift.\nexport const LowLevelBillingUsageDashboardLabels: LabellingUnitaryDef[] = [\n { ref: 'usageUnavailable', kind: LabelKind.EMPTY_STATE, purpose: 'Metered usage is temporarily unavailable; do not imply zero consumption' },\n { ref: 'creditPoolsUnavailable', kind: LabelKind.EMPTY_STATE, purpose: 'Credit balances are temporarily unavailable; do not imply zero credit' },\n { ref: 'title', kind: LabelKind.HEADING, purpose: 'Heading for the usage dashboard panel' },\n { ref: 'currentPeriod', kind: LabelKind.LABEL, purpose: 'Label for the active billing-period indicator' },\n { ref: 'noUsageData', kind: LabelKind.EMPTY_STATE, purpose: 'Shown before any usage has been recorded this period' },\n { ref: 'creditsTitle', kind: LabelKind.HEADING, purpose: 'Heading for the credits overview section' },\n { ref: 'availableCredits', kind: LabelKind.LABEL, purpose: 'Credits the customer can still spend' },\n { ref: 'totalPurchased', kind: LabelKind.LABEL, purpose: 'Total credits the customer has purchased' },\n { ref: 'totalGranted', kind: LabelKind.LABEL, purpose: 'Total credits the customer was given without buying them, such as referral rewards' },\n { ref: 'totalConsumed', kind: LabelKind.LABEL, purpose: 'Total credits the customer has consumed' },\n {\n ref: 'usageOf',\n kind: LabelKind.LABEL,\n purpose: 'How much of a metered quota is consumed',\n params: [\n { key: 'current', meaning: 'amount used so far this period' },\n { key: 'limit', meaning: \"the plan's quota for this metric\" },\n ],\n },\n {\n ref: 'trendVsPrevious',\n kind: LabelKind.LABEL,\n purpose: 'Change in usage compared with the previous period',\n params: [{ key: 'percentage', meaning: 'signed percentage change vs the previous period' }],\n },\n {\n ref: 'productUsageAriaLabel',\n kind: LabelKind.ARIA,\n purpose: \"Screen-reader summary of one product's metered usage\",\n notes: ['Self-contained; read aloud as a full phrase'],\n params: [\n { key: 'product', meaning: 'product / feature name' },\n { key: 'current', meaning: 'amount used so far' },\n { key: 'limit', meaning: 'quota for that product' },\n ],\n },\n {\n ref: 'creditPoolAriaLabel',\n kind: LabelKind.ARIA,\n purpose: \"Screen-reader summary of one credit pool's consumption\",\n notes: ['Self-contained; read aloud as a full phrase'],\n params: [\n { key: 'pool', meaning: 'credit-pool name' },\n { key: 'consumed', meaning: 'credits used from the pool' },\n { key: 'total', meaning: 'credits the pool received in total, bought and given' },\n ],\n },\n];\n\nregisterComponentLabels(FrontendComponentType.LOW_LEVEL_BILLING_USAGE_DASHBOARD, LowLevelBillingUsageDashboardLabels);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"display-field-enum.d.ts","sourceRoot":"","sources":["../../../../../../src/components/data-display/formatters/display-field-enum.tsx"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;AAGxE;;;;GAIG;AACH,iBAAS,gBAAgB,CAAC,EACxB,MAAM,EACN,KAAK,EACL,SAAS,EACT,MAAM,GACP,EAAE,qBAAqB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"display-field-enum.d.ts","sourceRoot":"","sources":["../../../../../../src/components/data-display/formatters/display-field-enum.tsx"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;AAGxE;;;;GAIG;AACH,iBAAS,gBAAgB,CAAC,EACxB,MAAM,EACN,KAAK,EACL,SAAS,EACT,MAAM,GACP,EAAE,qBAAqB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CAoIlD;AAID,OAAO,EAAE,gBAAgB,EAAE,CAAA"}
|
|
@@ -8,15 +8,15 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
8
8
|
*/
|
|
9
9
|
import * as React from "react";
|
|
10
10
|
import { useI18n, useIconRegistry, IconSize, ICON_SIZE_MAP, Text, Badge, Card, useContextualDisplayParams, resolveEnumDisplayConfig } from "@wildo-ai/saas-frontend-lib";
|
|
11
|
-
import { FrontendComponentType } from "@wildo-ai/presets-components-models";
|
|
12
|
-
import { EnumDisplayMode } from "@wildo-ai/zod-decorators";
|
|
11
|
+
import { FrontendComponentType, resolveVocabularyWordKey } from "@wildo-ai/presets-components-models";
|
|
12
|
+
import { EnumDisplayMode, getSystemEnumName } from "@wildo-ai/zod-decorators";
|
|
13
13
|
/**
|
|
14
14
|
* DisplayFieldEnum component
|
|
15
15
|
*
|
|
16
16
|
* Renders an enum value according to the display policy
|
|
17
17
|
*/
|
|
18
18
|
function DisplayFieldEnum({ schema, value, className, labels, }) {
|
|
19
|
-
const { tComponent, isReady } = useI18n({ component: FrontendComponentType.LOW_LEVEL_FORM_FIELD });
|
|
19
|
+
const { tComponent, t, isReady } = useI18n({ component: FrontendComponentType.LOW_LEVEL_FORM_FIELD });
|
|
20
20
|
const { renderIcon } = useIconRegistry();
|
|
21
21
|
// The field's own metadata over the registered vocabulary's (#1321) — see `resolveEnumDisplayConfig`.
|
|
22
22
|
const enumUI = resolveEnumDisplayConfig(schema);
|
|
@@ -35,8 +35,22 @@ function DisplayFieldEnum({ schema, value, className, labels, }) {
|
|
|
35
35
|
return (enumUI?.values?.[enumValue]?.icon
|
|
36
36
|
?? enumUI?.defaultIcon);
|
|
37
37
|
};
|
|
38
|
+
/*
|
|
39
|
+
* A value the resolved `labels` do not cover, on a field that names its vocabulary (#1851). The labels are built from
|
|
40
|
+
* the enum's own MEMBERS, so a union such as a feature list (`z.enum(CoreFeature) | z.string()`) carries values no
|
|
41
|
+
* member names — an application's own feature ids — and those read their word straight from the vocabulary, where
|
|
42
|
+
* it keeps it (`resolveVocabularyWordKey`). A value with no word shows itself: a missing label that looks missing.
|
|
43
|
+
*/
|
|
44
|
+
const vocabulary = schema ? getSystemEnumName(schema) : undefined;
|
|
45
|
+
const vocabularyWord = (enumValue) => {
|
|
46
|
+
if (!vocabulary)
|
|
47
|
+
return undefined;
|
|
48
|
+
const key = resolveVocabularyWordKey(vocabulary, enumValue);
|
|
49
|
+
const word = t(key);
|
|
50
|
+
return word === key ? undefined : word;
|
|
51
|
+
};
|
|
38
52
|
// Get display label for the value
|
|
39
|
-
const displayLabel = value ? (labels?.[value] ?? value) : null;
|
|
53
|
+
const displayLabel = value ? (labels?.[value] ?? vocabularyWord(value) ?? value) : null;
|
|
40
54
|
/**
|
|
41
55
|
* Render an `IconLike` — dispatches between string refs (via icon registry)
|
|
42
56
|
* and direct React component refs (via createElement).
|