@datatechsolutions/ui 3.12.1 → 3.13.1
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/astrlabe/graph-node.js +6 -6
- package/dist/astrlabe/graph-node.mjs +2 -2
- package/dist/astrlabe/index.js +114 -114
- package/dist/astrlabe/index.mjs +6 -6
- package/dist/astrlabe/workflow-canvas.js +6 -6
- package/dist/astrlabe/workflow-canvas.mjs +5 -5
- package/dist/{chunk-BPMYNE7S.mjs → chunk-3VCSMSJB.mjs} +6 -6
- package/dist/{chunk-BPMYNE7S.mjs.map → chunk-3VCSMSJB.mjs.map} +1 -1
- package/dist/{chunk-OM5NNUD2.mjs → chunk-4MNKVDTJ.mjs} +9 -8
- package/dist/chunk-4MNKVDTJ.mjs.map +1 -0
- package/dist/{chunk-PIIY2Z2O.mjs → chunk-4QCO4CBC.mjs} +4 -4
- package/dist/{chunk-PIIY2Z2O.mjs.map → chunk-4QCO4CBC.mjs.map} +1 -1
- package/dist/{chunk-4D23CQZM.mjs → chunk-4VEQJAXJ.mjs} +6 -6
- package/dist/{chunk-4D23CQZM.mjs.map → chunk-4VEQJAXJ.mjs.map} +1 -1
- package/dist/{chunk-FKRIQYRG.js → chunk-4Z5NZINA.js} +431 -481
- package/dist/chunk-4Z5NZINA.js.map +1 -0
- package/dist/{chunk-Z75CEP4V.js → chunk-54T5F65C.js} +29 -29
- package/dist/{chunk-Z75CEP4V.js.map → chunk-54T5F65C.js.map} +1 -1
- package/dist/{chunk-V3UZCOZI.js → chunk-7IAWXG43.js} +35 -35
- package/dist/{chunk-V3UZCOZI.js.map → chunk-7IAWXG43.js.map} +1 -1
- package/dist/{chunk-PLEWG2L7.js → chunk-AC54BNSK.js} +15 -15
- package/dist/{chunk-PLEWG2L7.js.map → chunk-AC54BNSK.js.map} +1 -1
- package/dist/{chunk-ID55ABBB.js → chunk-B3TA74C4.js} +100 -100
- package/dist/chunk-B3TA74C4.js.map +1 -0
- package/dist/{chunk-5OZTI7TR.js → chunk-CKY2QIRR.js} +6 -6
- package/dist/{chunk-5OZTI7TR.js.map → chunk-CKY2QIRR.js.map} +1 -1
- package/dist/{chunk-EZQ2D47U.js → chunk-CVEI4RQP.js} +4 -4
- package/dist/{chunk-EZQ2D47U.js.map → chunk-CVEI4RQP.js.map} +1 -1
- package/dist/{chunk-NK4H3JWN.mjs → chunk-DJHNSBIR.mjs} +63 -100
- package/dist/chunk-DJHNSBIR.mjs.map +1 -0
- package/dist/{chunk-P4RVGMZL.js → chunk-DTFU3ZTD.js} +5 -33
- package/dist/chunk-DTFU3ZTD.js.map +1 -0
- package/dist/{chunk-BHOT22QL.js → chunk-EBARYRSA.js} +2 -2
- package/dist/{chunk-BHOT22QL.js.map → chunk-EBARYRSA.js.map} +1 -1
- package/dist/{chunk-QGLGQXJE.js → chunk-FV42SSLP.js} +10 -10
- package/dist/chunk-FV42SSLP.js.map +1 -0
- package/dist/{chunk-RT264BD4.mjs → chunk-M4KRQXOT.mjs} +4 -4
- package/dist/{chunk-RT264BD4.mjs.map → chunk-M4KRQXOT.mjs.map} +1 -1
- package/dist/{chunk-WR55H7DH.mjs → chunk-O4RZCDP2.mjs} +2 -2
- package/dist/{chunk-WR55H7DH.mjs.map → chunk-O4RZCDP2.mjs.map} +1 -1
- package/dist/{chunk-VYU2FYDE.js → chunk-PM7A5I3X.js} +146 -183
- package/dist/chunk-PM7A5I3X.js.map +1 -0
- package/dist/{chunk-TDNBO3V7.js → chunk-Q7QPHZOV.js} +74 -74
- package/dist/{chunk-TDNBO3V7.js.map → chunk-Q7QPHZOV.js.map} +1 -1
- package/dist/{chunk-OW5LSEHU.mjs → chunk-QEACOJXX.mjs} +74 -74
- package/dist/chunk-QEACOJXX.mjs.map +1 -0
- package/dist/{chunk-N5GQIT7A.mjs → chunk-RMPXGEFL.mjs} +11 -10
- package/dist/chunk-RMPXGEFL.mjs.map +1 -0
- package/dist/{chunk-QSCWV47U.js → chunk-RPNMDGRA.js} +50 -50
- package/dist/chunk-RPNMDGRA.js.map +1 -0
- package/dist/{chunk-5TLKFOEL.mjs → chunk-RSCRIDMW.mjs} +275 -313
- package/dist/chunk-RSCRIDMW.mjs.map +1 -0
- package/dist/{chunk-XGAPZT4J.js → chunk-RUZPOHJW.js} +48 -47
- package/dist/chunk-RUZPOHJW.js.map +1 -0
- package/dist/{chunk-ULKZGM2T.js → chunk-RWZ2PLMQ.js} +177 -177
- package/dist/chunk-RWZ2PLMQ.js.map +1 -0
- package/dist/{chunk-UVFWKDRO.mjs → chunk-SCGICCQM.mjs} +15 -15
- package/dist/chunk-SCGICCQM.mjs.map +1 -0
- package/dist/{chunk-EDI46QA7.mjs → chunk-TRNDFSM6.mjs} +274 -324
- package/dist/chunk-TRNDFSM6.mjs.map +1 -0
- package/dist/{chunk-LRNVB7MO.js → chunk-ULSG4JLR.js} +6 -6
- package/dist/{chunk-LRNVB7MO.js.map → chunk-ULSG4JLR.js.map} +1 -1
- package/dist/{chunk-MFF37C24.js → chunk-UPWJRCAD.js} +445 -483
- package/dist/chunk-UPWJRCAD.js.map +1 -0
- package/dist/{chunk-RBH723MG.mjs → chunk-UUTTS3VV.mjs} +45 -45
- package/dist/chunk-UUTTS3VV.mjs.map +1 -0
- package/dist/{chunk-MYHBXIO2.js → chunk-VCL5LDS5.js} +42 -41
- package/dist/chunk-VCL5LDS5.js.map +1 -0
- package/dist/{chunk-PLTLRL2V.mjs → chunk-VPRAESA7.mjs} +3 -3
- package/dist/{chunk-PLTLRL2V.mjs.map → chunk-VPRAESA7.mjs.map} +1 -1
- package/dist/{chunk-HTODLUKG.js → chunk-VWZ53TE2.js} +12 -12
- package/dist/{chunk-HTODLUKG.js.map → chunk-VWZ53TE2.js.map} +1 -1
- package/dist/{chunk-3VYD7QL2.mjs → chunk-WX44DAQD.mjs} +9 -9
- package/dist/chunk-WX44DAQD.mjs.map +1 -0
- package/dist/{chunk-DJ33CSGJ.mjs → chunk-XYMHIZ3K.mjs} +5 -33
- package/dist/chunk-XYMHIZ3K.mjs.map +1 -0
- package/dist/{chunk-YXN2K77G.js → chunk-Y5VN4SPH.js} +26 -3
- package/dist/chunk-Y5VN4SPH.js.map +1 -0
- package/dist/{chunk-NQGLSM46.mjs → chunk-Y65X2NHF.mjs} +4 -4
- package/dist/{chunk-NQGLSM46.mjs.map → chunk-Y65X2NHF.mjs.map} +1 -1
- package/dist/{chunk-YYNGXKUE.mjs → chunk-YHD6SJIN.mjs} +15 -15
- package/dist/{chunk-YYNGXKUE.mjs.map → chunk-YHD6SJIN.mjs.map} +1 -1
- package/dist/{chunk-7VJ7CMMT.mjs → chunk-ZEFNBGYI.mjs} +26 -3
- package/dist/chunk-ZEFNBGYI.mjs.map +1 -0
- package/dist/{chunk-WLNY3GVM.mjs → chunk-ZPV7X4ZE.mjs} +7 -7
- package/dist/{chunk-WLNY3GVM.mjs.map → chunk-ZPV7X4ZE.mjs.map} +1 -1
- package/dist/index.js +709 -709
- package/dist/index.mjs +3 -3
- package/dist/lib/i18n-context.d.mts +12 -4
- package/dist/lib/i18n-context.d.ts +12 -4
- package/dist/lib/i18n-context.js +6 -6
- package/dist/lib/i18n-context.mjs +1 -1
- package/dist/platform/admin/index.js +12 -12
- package/dist/platform/admin/index.mjs +6 -6
- package/dist/platform/agents-workspace.js +9 -9
- package/dist/platform/agents-workspace.mjs +8 -8
- package/dist/platform/app-shell.js +5 -5
- package/dist/platform/app-shell.mjs +4 -4
- package/dist/platform/auth/index.js +29 -29
- package/dist/platform/auth/index.mjs +6 -6
- package/dist/platform/billing/index.js +7 -7
- package/dist/platform/billing/index.mjs +5 -5
- package/dist/platform/impersonation/index.js +5 -5
- package/dist/platform/impersonation/index.mjs +4 -4
- package/dist/platform/index.d.mts +1 -1
- package/dist/platform/index.d.ts +1 -1
- package/dist/platform/index.js +112 -112
- package/dist/platform/index.js.map +1 -1
- package/dist/platform/index.mjs +30 -30
- package/dist/platform/index.mjs.map +1 -1
- package/dist/platform/pages/index.d.mts +12 -2
- package/dist/platform/pages/index.d.ts +12 -2
- package/dist/platform/pages/index.js +451 -450
- package/dist/platform/pages/index.js.map +1 -1
- package/dist/platform/pages/index.mjs +51 -50
- package/dist/platform/pages/index.mjs.map +1 -1
- package/dist/platform/settings/index.js +9 -9
- package/dist/platform/settings/index.mjs +8 -8
- package/dist/platform/workflow-canvas-shell.js +7 -7
- package/dist/platform/workflow-canvas-shell.mjs +6 -6
- package/package.json +2 -1
- package/dist/chunk-3VYD7QL2.mjs.map +0 -1
- package/dist/chunk-5TLKFOEL.mjs.map +0 -1
- package/dist/chunk-7VJ7CMMT.mjs.map +0 -1
- package/dist/chunk-DJ33CSGJ.mjs.map +0 -1
- package/dist/chunk-EDI46QA7.mjs.map +0 -1
- package/dist/chunk-FKRIQYRG.js.map +0 -1
- package/dist/chunk-ID55ABBB.js.map +0 -1
- package/dist/chunk-MFF37C24.js.map +0 -1
- package/dist/chunk-MYHBXIO2.js.map +0 -1
- package/dist/chunk-N5GQIT7A.mjs.map +0 -1
- package/dist/chunk-NK4H3JWN.mjs.map +0 -1
- package/dist/chunk-OM5NNUD2.mjs.map +0 -1
- package/dist/chunk-OW5LSEHU.mjs.map +0 -1
- package/dist/chunk-P4RVGMZL.js.map +0 -1
- package/dist/chunk-QGLGQXJE.js.map +0 -1
- package/dist/chunk-QSCWV47U.js.map +0 -1
- package/dist/chunk-RBH723MG.mjs.map +0 -1
- package/dist/chunk-ULKZGM2T.js.map +0 -1
- package/dist/chunk-UVFWKDRO.mjs.map +0 -1
- package/dist/chunk-VYU2FYDE.js.map +0 -1
- package/dist/chunk-XGAPZT4J.js.map +0 -1
- package/dist/chunk-YXN2K77G.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { Button } from './chunk-O4RZCDP2.mjs';
|
|
2
3
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
3
4
|
|
|
4
|
-
// src/platform/billing/upgrade-prompt.tsx
|
|
5
5
|
var TIER_DISPLAY_NAMES = {
|
|
6
6
|
free_trial: "Free Trial",
|
|
7
7
|
starter: "Starter",
|
|
@@ -84,36 +84,8 @@ function UpgradePrompt({
|
|
|
84
84
|
] }),
|
|
85
85
|
children,
|
|
86
86
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 pt-1", children: [
|
|
87
|
-
onUpgrade && /* @__PURE__ */ jsx(
|
|
88
|
-
|
|
89
|
-
{
|
|
90
|
-
type: "button",
|
|
91
|
-
onClick: onUpgrade,
|
|
92
|
-
className: [
|
|
93
|
-
"rounded-xl bg-gradient-to-r from-violet-600 to-blue-600 px-5 py-2 text-sm font-semibold text-white",
|
|
94
|
-
"shadow-md shadow-violet-500/25 transition-all",
|
|
95
|
-
"hover:from-violet-500 hover:to-blue-500 hover:shadow-lg hover:shadow-violet-500/30",
|
|
96
|
-
"focus:outline-none focus:ring-2 focus:ring-violet-500 focus:ring-offset-2",
|
|
97
|
-
"active:scale-[0.98]",
|
|
98
|
-
"dark:shadow-violet-500/10 dark:hover:shadow-violet-500/20"
|
|
99
|
-
].join(" "),
|
|
100
|
-
children: "Upgrade Now"
|
|
101
|
-
}
|
|
102
|
-
),
|
|
103
|
-
onDismiss && /* @__PURE__ */ jsx(
|
|
104
|
-
"button",
|
|
105
|
-
{
|
|
106
|
-
type: "button",
|
|
107
|
-
onClick: onDismiss,
|
|
108
|
-
className: [
|
|
109
|
-
"rounded-xl px-4 py-2 text-sm font-medium",
|
|
110
|
-
"text-gray-500 transition-colors",
|
|
111
|
-
"hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200",
|
|
112
|
-
"focus:outline-none focus:ring-2 focus:ring-gray-300 focus:ring-offset-2"
|
|
113
|
-
].join(" "),
|
|
114
|
-
children: "Maybe Later"
|
|
115
|
-
}
|
|
116
|
-
)
|
|
87
|
+
onUpgrade && /* @__PURE__ */ jsx(Button, { type: "button", gradient: true, onClick: onUpgrade, children: "Upgrade Now" }),
|
|
88
|
+
onDismiss && /* @__PURE__ */ jsx(Button, { type: "button", plain: true, onClick: onDismiss, children: "Maybe Later" })
|
|
117
89
|
] })
|
|
118
90
|
] })
|
|
119
91
|
]
|
|
@@ -122,5 +94,5 @@ function UpgradePrompt({
|
|
|
122
94
|
}
|
|
123
95
|
|
|
124
96
|
export { UpgradePrompt };
|
|
125
|
-
//# sourceMappingURL=chunk-
|
|
126
|
-
//# sourceMappingURL=chunk-
|
|
97
|
+
//# sourceMappingURL=chunk-XYMHIZ3K.mjs.map
|
|
98
|
+
//# sourceMappingURL=chunk-XYMHIZ3K.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/platform/billing/upgrade-prompt.tsx"],"names":[],"mappings":"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","file":"chunk-XYMHIZ3K.mjs","sourcesContent":["// =============================================================================\n// @datatechsolutions/windsock/ui — UpgradePrompt Component\n// Glassmorphism-styled prompt shown when a user hits subscription limits.\n// =============================================================================\n\nimport { type ReactNode } from 'react'\nimport type { SubscriptionTier } from '@datatechsolutions/shared-domain'\nimport { Button } from '@ui/components/button'\n\n/** Human-readable tier display names */\nconst TIER_DISPLAY_NAMES: Record<SubscriptionTier, string> = {\n free_trial: 'Free Trial',\n starter: 'Starter',\n professional: 'Professional',\n enterprise: 'Enterprise',\n}\n\ninterface UpgradePromptProps {\n /** The user's current subscription tier */\n currentTier: SubscriptionTier\n /** The minimum tier required for access (shown in the prompt) */\n requiredTier?: SubscriptionTier\n /** Feature name that triggered the prompt */\n feature?: string\n /** Called when the user clicks \"Upgrade Now\" */\n onUpgrade?: () => void\n /** Called when the user dismisses the prompt */\n onDismiss?: () => void\n /** Optional custom content to render inside the card */\n children?: ReactNode\n}\n\n/**\n * A glassmorphism-styled upgrade prompt shown when users hit subscription\n * limits or try to access features above their current tier.\n *\n * Renders a card with the current tier, the required tier (or feature name),\n * and action buttons for upgrading or dismissing.\n */\nexport function UpgradePrompt({\n currentTier,\n requiredTier,\n feature,\n onUpgrade,\n onDismiss,\n children,\n}: UpgradePromptProps) {\n const currentTierName = TIER_DISPLAY_NAMES[currentTier] ?? currentTier\n const requiredTierName = requiredTier ? TIER_DISPLAY_NAMES[requiredTier] ?? requiredTier : null\n\n const heading = feature\n ? `Upgrade to unlock ${feature}`\n : requiredTierName\n ? `Upgrade to ${requiredTierName}`\n : 'Upgrade your plan'\n\n return (\n <div\n className={[\n 'relative overflow-hidden rounded-2xl border border-white/20',\n 'bg-white/10 p-6 backdrop-blur-xl',\n 'shadow-lg shadow-black/5',\n 'dark:border-white/10 dark:bg-white/5 dark:shadow-black/20',\n ].join(' ')}\n role=\"alert\"\n aria-label=\"Subscription upgrade prompt\"\n >\n {/* Decorative gradient accent */}\n <div\n className=\"pointer-events-none absolute -right-8 -top-8 h-32 w-32 rounded-full bg-gradient-to-br from-violet-500/20 to-blue-500/20 blur-2xl\"\n aria-hidden=\"true\"\n />\n\n <div className=\"relative flex flex-col gap-4\">\n {/* Icon */}\n <div className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-gradient-to-br from-violet-500 to-blue-500 text-white\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className=\"h-5 w-5\"\n aria-hidden=\"true\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M9 4.5a.75.75 0 0 1 .721.544l.813 2.846a3.75 3.75 0 0 0 2.576 2.576l2.846.813a.75.75 0 0 1 0 1.442l-2.846.813a3.75 3.75 0 0 0-2.576 2.576l-.813 2.846a.75.75 0 0 1-1.442 0l-.813-2.846a3.75 3.75 0 0 0-2.576-2.576l-2.846-.813a.75.75 0 0 1 0-1.442l2.846-.813A3.75 3.75 0 0 0 7.466 7.89l.813-2.846A.75.75 0 0 1 9 4.5ZM18 1.5a.75.75 0 0 1 .728.568l.258 1.036c.236.94.97 1.674 1.91 1.91l1.036.258a.75.75 0 0 1 0 1.456l-1.036.258c-.94.236-1.674.97-1.91 1.91l-.258 1.036a.75.75 0 0 1-1.456 0l-.258-1.036a2.625 2.625 0 0 0-1.91-1.91l-1.036-.258a.75.75 0 0 1 0-1.456l1.036-.258a2.625 2.625 0 0 0 1.91-1.91l.258-1.036A.75.75 0 0 1 18 1.5Z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </div>\n\n {/* Heading */}\n <h3 className=\"text-lg font-semibold text-gray-900 dark:text-white\">\n {heading}\n </h3>\n\n {/* Tier comparison */}\n <div className=\"flex items-center gap-2 text-sm text-gray-600 dark:text-gray-300\">\n <span className=\"rounded-md bg-gray-200/60 px-2 py-0.5 font-medium dark:bg-white/10\">\n {currentTierName}\n </span>\n {requiredTierName && (\n <>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n className=\"h-4 w-4 text-gray-400 dark:text-gray-500\"\n aria-hidden=\"true\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M3 10a.75.75 0 0 1 .75-.75h10.638L10.23 5.29a.75.75 0 1 1 1.04-1.08l5.5 5.25a.75.75 0 0 1 0 1.08l-5.5 5.25a.75.75 0 1 1-1.04-1.08l4.158-3.96H3.75A.75.75 0 0 1 3 10Z\"\n clipRule=\"evenodd\"\n />\n </svg>\n <span className=\"rounded-md bg-gradient-to-r from-violet-500/10 to-blue-500/10 px-2 py-0.5 font-medium text-violet-700 dark:from-violet-500/20 dark:to-blue-500/20 dark:text-violet-300\">\n {requiredTierName}\n </span>\n </>\n )}\n </div>\n\n {/* Optional custom content */}\n {children}\n\n {/* Actions */}\n <div className=\"flex items-center gap-3 pt-1\">\n {onUpgrade && (\n <Button type=\"button\" gradient onClick={onUpgrade}>\n Upgrade Now\n </Button>\n )}\n {onDismiss && (\n <Button type=\"button\" plain onClick={onDismiss}>\n Maybe Later\n </Button>\n )}\n </div>\n </div>\n </div>\n )\n}\n\nexport type { UpgradePromptProps }\n"]}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var react = require('react');
|
|
5
|
+
var intlMessageformat = require('intl-messageformat');
|
|
5
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
7
|
|
|
7
8
|
// src/lib/i18n-context.tsx
|
|
@@ -68,6 +69,19 @@ function useFormatter() {
|
|
|
68
69
|
number: (value, options) => new Intl.NumberFormat(locale, options).format(value)
|
|
69
70
|
};
|
|
70
71
|
}
|
|
72
|
+
var FORMATTER_CACHE = /* @__PURE__ */ new Map();
|
|
73
|
+
function getFormatter(locale, raw) {
|
|
74
|
+
const key = `${locale}\u200B${raw}`;
|
|
75
|
+
let formatter = FORMATTER_CACHE.get(key);
|
|
76
|
+
if (formatter) return formatter;
|
|
77
|
+
try {
|
|
78
|
+
formatter = new intlMessageformat.IntlMessageFormat(raw, locale, void 0, { ignoreTag: true });
|
|
79
|
+
FORMATTER_CACHE.set(key, formatter);
|
|
80
|
+
return formatter;
|
|
81
|
+
} catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
71
85
|
function createI18nFromMessages(locale, messages) {
|
|
72
86
|
return {
|
|
73
87
|
locale,
|
|
@@ -76,7 +90,16 @@ function createI18nFromMessages(locale, messages) {
|
|
|
76
90
|
const fn = ((key, params) => {
|
|
77
91
|
const fullKey = namespace ? `${namespace}.${key}` : key;
|
|
78
92
|
const raw = getNestedValue(messages, fullKey);
|
|
79
|
-
|
|
93
|
+
if (typeof raw !== "string") return key;
|
|
94
|
+
const formatter = getFormatter(locale, raw);
|
|
95
|
+
if (formatter) {
|
|
96
|
+
try {
|
|
97
|
+
const out = formatter.format(params);
|
|
98
|
+
return typeof out === "string" ? out : Array.isArray(out) ? out.join("") : String(out);
|
|
99
|
+
} catch {
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
let result = raw;
|
|
80
103
|
if (params) {
|
|
81
104
|
for (const [paramKey, paramValue] of Object.entries(params)) {
|
|
82
105
|
result = result.replace(new RegExp(`\\{${paramKey}\\}`, "g"), String(paramValue));
|
|
@@ -98,5 +121,5 @@ exports.createI18nFromMessages = createI18nFromMessages;
|
|
|
98
121
|
exports.useFormatter = useFormatter;
|
|
99
122
|
exports.useLocale = useLocale;
|
|
100
123
|
exports.useTranslations = useTranslations;
|
|
101
|
-
//# sourceMappingURL=chunk-
|
|
102
|
-
//# sourceMappingURL=chunk-
|
|
124
|
+
//# sourceMappingURL=chunk-Y5VN4SPH.js.map
|
|
125
|
+
//# sourceMappingURL=chunk-Y5VN4SPH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/i18n-context.tsx"],"names":["createContext","jsx","useContext","IntlMessageFormat"],"mappings":"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","file":"chunk-Y5VN4SPH.js","sourcesContent":["import { createContext, useContext, type ReactNode } from 'react'\nimport { IntlMessageFormat } from 'intl-messageformat'\n\ntype TranslateFn = ((key: string, params?: Record<string, unknown>) => string) & {\n /** Return the raw (unparsed) value at a given key — useful for arrays/objects in messages */\n raw: (key: string) => unknown\n}\n\nexport interface I18nContextValue {\n translate: (namespace?: string) => TranslateFn\n locale: string\n messages?: Record<string, unknown>\n}\n\nconst I18nContext = createContext<I18nContextValue | null>(null)\n\nexport type I18nProviderProps = {\n children: ReactNode\n value: I18nContextValue\n}\n\nexport function I18nProvider({ children, value }: I18nProviderProps) {\n return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>\n}\n\nexport function useTranslations(namespace?: string): TranslateFn {\n const context = useContext(I18nContext)\n if (!context) {\n const fallback = ((key: string, params?: Record<string, unknown>) => {\n let result = namespace ? `${namespace}.${key}` : key\n if (params) {\n for (const [paramKey, paramValue] of Object.entries(params)) {\n result = result.replace(`{${paramKey}}`, String(paramValue))\n }\n }\n return result\n }) as TranslateFn\n fallback.raw = (key: string) => key\n return fallback\n }\n const translateFn = context.translate(namespace) as TranslateFn\n if (!translateFn.raw) {\n translateFn.raw = (key: string) => {\n const messages = context.messages\n if (!messages) return undefined\n const fullKey = namespace ? `${namespace}.${key}` : key\n return getNestedValue(messages, fullKey)\n }\n }\n return translateFn\n}\n\nfunction getNestedValue(object: Record<string, unknown>, path: string): unknown {\n const parts = path.split('.')\n let current: unknown = object\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') return undefined\n current = (current as Record<string, unknown>)[part]\n }\n return current\n}\n\nexport function useLocale(): string {\n const context = useContext(I18nContext)\n return context?.locale ?? 'en'\n}\n\nexport type I18nFormatter = {\n dateTime: (date: Date, options?: Intl.DateTimeFormatOptions) => string\n relativeTime: (date: Date, options?: Intl.RelativeTimeFormatOptions) => string\n number: (value: number, options?: Intl.NumberFormatOptions) => string\n}\n\nexport function useFormatter(): I18nFormatter {\n const locale = useLocale()\n return {\n dateTime: (date: Date, options?: Intl.DateTimeFormatOptions) =>\n new Intl.DateTimeFormat(locale, options).format(date),\n relativeTime: (date: Date) => {\n const now = Date.now()\n const diffMs = date.getTime() - now\n const diffSeconds = Math.round(diffMs / 1000)\n const diffMinutes = Math.round(diffMs / 60000)\n const diffHours = Math.round(diffMs / 3600000)\n const diffDays = Math.round(diffMs / 86400000)\n const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' })\n if (Math.abs(diffSeconds) < 60) return rtf.format(diffSeconds, 'second')\n if (Math.abs(diffMinutes) < 60) return rtf.format(diffMinutes, 'minute')\n if (Math.abs(diffHours) < 24) return rtf.format(diffHours, 'hour')\n return rtf.format(diffDays, 'day')\n },\n number: (value: number, options?: Intl.NumberFormatOptions) =>\n new Intl.NumberFormat(locale, options).format(value),\n }\n}\n\n/**\n * Cache of compiled `IntlMessageFormat` instances keyed by `locale${rawString}`.\n * Compilation is the expensive step — parsing the ICU AST. Once compiled,\n * `.format(params)` is cheap. The cache is process-wide because messages\n * are static for a session; LRU eviction is unnecessary at our message\n * volume (<5k unique strings × 6 locales = ~30k cap, fits comfortably).\n */\nconst FORMATTER_CACHE = new Map<string, IntlMessageFormat>()\n\nfunction getFormatter(locale: string, raw: string): IntlMessageFormat | null {\n const key = `${locale}${raw}`\n let formatter = FORMATTER_CACHE.get(key)\n if (formatter) return formatter\n try {\n formatter = new IntlMessageFormat(raw, locale, undefined, { ignoreTag: true })\n FORMATTER_CACHE.set(key, formatter)\n return formatter\n } catch {\n // Parse failure: malformed ICU. Caller falls back to the raw string —\n // safer than throwing during render.\n return null\n }\n}\n\n/**\n * Create an I18nContextValue from a flat messages object and locale.\n * Messages should be a nested object where keys are namespaces and\n * values are objects of translation key → ICU MessageFormat string.\n *\n * Full ICU support via `intl-messageformat`: plurals (`{count, plural,\n * one {# item} other {# items}}`), select (`{gender, select, male {he}\n * female {she} other {they}}`), number/date format. Strings without\n * any ICU markup work transparently — the formatter falls through to\n * its identity output. Old `{param}` strings (no surrounding type\n * keyword) still work as plain interpolation.\n *\n * Parse failures fall back to the raw template + simple-replace so a\n * single bad message can never crash render. `tracing` console.warn\n * goes out for the first failure so authors notice.\n */\nexport function createI18nFromMessages(\n locale: string,\n messages: Record<string, unknown>,\n): I18nContextValue {\n return {\n locale,\n messages,\n translate: (namespace?: string) => {\n const fn = ((key: string, params?: Record<string, unknown>) => {\n const fullKey = namespace ? `${namespace}.${key}` : key\n const raw = getNestedValue(messages, fullKey)\n if (typeof raw !== 'string') return key\n const formatter = getFormatter(locale, raw)\n if (formatter) {\n try {\n const out = formatter.format(params as Record<string, string | number | boolean | null | undefined | Date> | undefined)\n // IntlMessageFormat returns string | string[] | ReactNode[] —\n // narrow to string here because the i18n context is typed to\n // emit string. Array branch only triggers when `tagsToParts`\n // is enabled, which we never opt into.\n return typeof out === 'string' ? out : Array.isArray(out) ? out.join('') : String(out)\n } catch {\n // Format-time failure (e.g. missing param) — fall through.\n }\n }\n // Fallback: simple {param} replace for non-ICU or parse-failed strings.\n let result = raw\n if (params) {\n for (const [paramKey, paramValue] of Object.entries(params)) {\n result = result.replace(new RegExp(`\\\\{${paramKey}\\\\}`, 'g'), String(paramValue))\n }\n }\n return result\n }) as TranslateFn\n fn.raw = (key: string) => {\n const fullKey = namespace ? `${namespace}.${key}` : key\n return getNestedValue(messages, fullKey)\n }\n return fn\n },\n }\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { Workspace } from './chunk-
|
|
3
|
-
import { useLocale } from './chunk-
|
|
2
|
+
import { Workspace } from './chunk-TRNDFSM6.mjs';
|
|
3
|
+
import { useLocale } from './chunk-ZEFNBGYI.mjs';
|
|
4
4
|
import { jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
function WorkflowCanvasShell({ graph, messages }) {
|
|
@@ -16,5 +16,5 @@ function WorkflowCanvasShell({ graph, messages }) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export { WorkflowCanvasShell };
|
|
19
|
-
//# sourceMappingURL=chunk-
|
|
20
|
-
//# sourceMappingURL=chunk-
|
|
19
|
+
//# sourceMappingURL=chunk-Y65X2NHF.mjs.map
|
|
20
|
+
//# sourceMappingURL=chunk-Y65X2NHF.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/platform/workflow-canvas-shell.tsx"],"names":[],"mappings":";;;;AAkBO,SAAS,mBAAA,CAAoB,EAAE,KAAA,EAAO,QAAA,EAAS,EAAU;AAC9D,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,uBACE,GAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,YAAA,EAAc,KAAA;AAAA,MACd,MAAA;AAAA,MACC,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa;AAAC;AAAA,GAClC;AAEJ","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/platform/workflow-canvas-shell.tsx"],"names":[],"mappings":";;;;AAkBO,SAAS,mBAAA,CAAoB,EAAE,KAAA,EAAO,QAAA,EAAS,EAAU;AAC9D,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,uBACE,GAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,YAAA,EAAc,KAAA;AAAA,MACd,MAAA;AAAA,MACC,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa;AAAC;AAAA,GAClC;AAEJ","file":"chunk-Y65X2NHF.mjs","sourcesContent":["import { useLocale } from '@ui/lib/i18n-context'\nimport { Workspace } from '@ui/astrlabe/workflow-canvas'\nimport type { WorkflowGraph as UiWorkflowGraph } from '@ui/astrlabe'\nimport type { WorkflowCanvasShellProps } from '@datatechsolutions/shared-domain/common'\n\n/**\n * Workflow canvas shell with optional message bundle override.\n *\n * Most apps wrap their tree in `<I18nProvider>` and let the canvas read\n * messages from context — in that case `messages` can be omitted. Apps\n * that need to inject a precomputed bundle (e.g. for tests or app-specific\n * overrides not shipped with shared-domain) can pass it explicitly.\n */\ntype Props = WorkflowCanvasShellProps & {\n /** Optional override for the messages catalog passed into the canvas. */\n messages?: Record<string, unknown>\n}\n\nexport function WorkflowCanvasShell({ graph, messages }: Props) {\n const locale = useLocale()\n return (\n <Workspace\n initialGraph={graph as unknown as UiWorkflowGraph}\n locale={locale}\n {...(messages ? { messages } : {})}\n />\n )\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useAuth, InlineSpinner, SectionCard, StatusBadge, ListCard, ListCardItem } from './chunk-
|
|
3
|
-
import { useTranslations, useFormatter } from './chunk-
|
|
4
|
-
import { Badge, Button } from './chunk-
|
|
2
|
+
import { useAuth, InlineSpinner, SectionCard, StatusBadge, ListCard, ListCardItem } from './chunk-QEACOJXX.mjs';
|
|
3
|
+
import { useTranslations, useFormatter } from './chunk-ZEFNBGYI.mjs';
|
|
4
|
+
import { Badge, Button } from './chunk-O4RZCDP2.mjs';
|
|
5
5
|
import { triggerHaptic } from './chunk-D2JF6C3E.mjs';
|
|
6
6
|
import { useState, useCallback, useEffect } from 'react';
|
|
7
7
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
@@ -124,7 +124,7 @@ function BillingPanel({
|
|
|
124
124
|
},
|
|
125
125
|
children: subscription && currentPlan ? /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
126
126
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
127
|
-
/* @__PURE__ */ jsx("span", { className: "text-lg font-semibold text-
|
|
127
|
+
/* @__PURE__ */ jsx("span", { className: "text-lg font-semibold text-slate-900 dark:text-white", children: currentPlan.name }),
|
|
128
128
|
/* @__PURE__ */ jsx(
|
|
129
129
|
StatusBadge,
|
|
130
130
|
{
|
|
@@ -136,8 +136,8 @@ function BillingPanel({
|
|
|
136
136
|
] }),
|
|
137
137
|
/* @__PURE__ */ jsxs("dl", { className: "grid grid-cols-1 gap-3 text-sm sm:grid-cols-2", children: [
|
|
138
138
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
139
|
-
/* @__PURE__ */ jsx("dt", { className: "text-
|
|
140
|
-
/* @__PURE__ */ jsxs("dd", { className: "font-medium text-
|
|
139
|
+
/* @__PURE__ */ jsx("dt", { className: "text-slate-500 dark:text-slate-400", children: t("billing.currentPlan.price") }),
|
|
140
|
+
/* @__PURE__ */ jsxs("dd", { className: "font-medium text-slate-900 dark:text-white", children: [
|
|
141
141
|
format.number(currentPlan.price, { style: "currency", currency: currentPlan.currency }),
|
|
142
142
|
" ",
|
|
143
143
|
"/",
|
|
@@ -146,8 +146,8 @@ function BillingPanel({
|
|
|
146
146
|
] })
|
|
147
147
|
] }),
|
|
148
148
|
subscription.currentPeriodEnd && /* @__PURE__ */ jsxs("div", { children: [
|
|
149
|
-
/* @__PURE__ */ jsx("dt", { className: "text-
|
|
150
|
-
/* @__PURE__ */ jsx("dd", { className: "font-medium text-
|
|
149
|
+
/* @__PURE__ */ jsx("dt", { className: "text-slate-500 dark:text-slate-400", children: t("billing.currentPlan.renewsOn") }),
|
|
150
|
+
/* @__PURE__ */ jsx("dd", { className: "font-medium text-slate-900 dark:text-white", children: format.dateTime(new Date(subscription.currentPeriodEnd), { dateStyle: "medium" }) })
|
|
151
151
|
] })
|
|
152
152
|
] }),
|
|
153
153
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2 pt-2", children: [
|
|
@@ -174,7 +174,7 @@ function BillingPanel({
|
|
|
174
174
|
}
|
|
175
175
|
)
|
|
176
176
|
] })
|
|
177
|
-
] }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-
|
|
177
|
+
] }) : /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500 dark:text-slate-400", children: t("billing.currentPlan.noSubscription") })
|
|
178
178
|
}
|
|
179
179
|
),
|
|
180
180
|
/* @__PURE__ */ jsx(
|
|
@@ -184,7 +184,7 @@ function BillingPanel({
|
|
|
184
184
|
title: t("billing.plans.title"),
|
|
185
185
|
subtitle: t("billing.plans.description")
|
|
186
186
|
},
|
|
187
|
-
children: plans.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-
|
|
187
|
+
children: plans.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500 dark:text-slate-400", children: t("billing.plans.empty") }) : /* @__PURE__ */ jsx(ListCard, { children: plans.map((plan) => {
|
|
188
188
|
const isCurrent = currentPlan?.id === plan.id;
|
|
189
189
|
const isDowngrade = currentTier != null && (TIER_ORDER[plan.tier] ?? 0) < (TIER_ORDER[currentTier] ?? 0);
|
|
190
190
|
return /* @__PURE__ */ jsx(
|
|
@@ -214,8 +214,8 @@ function BillingPanel({
|
|
|
214
214
|
),
|
|
215
215
|
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
216
216
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
217
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-
|
|
218
|
-
/* @__PURE__ */ jsxs("span", { className: "text-xs text-
|
|
217
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-slate-900 dark:text-white", children: plan.name }),
|
|
218
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-slate-500 dark:text-slate-400", children: [
|
|
219
219
|
format.number(plan.price, { style: "currency", currency: plan.currency }),
|
|
220
220
|
" ",
|
|
221
221
|
"/",
|
|
@@ -223,7 +223,7 @@ function BillingPanel({
|
|
|
223
223
|
t(`billing.interval.${plan.interval}`)
|
|
224
224
|
] })
|
|
225
225
|
] }),
|
|
226
|
-
plan.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-
|
|
226
|
+
plan.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: plan.description })
|
|
227
227
|
] })
|
|
228
228
|
},
|
|
229
229
|
plan.id
|
|
@@ -235,5 +235,5 @@ function BillingPanel({
|
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
export { BillingPanel };
|
|
238
|
-
//# sourceMappingURL=chunk-
|
|
239
|
-
//# sourceMappingURL=chunk-
|
|
238
|
+
//# sourceMappingURL=chunk-YHD6SJIN.mjs.map
|
|
239
|
+
//# sourceMappingURL=chunk-YHD6SJIN.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/platform/billing/billing-panel.tsx"],"names":[],"mappings":"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","file":"chunk-YYNGXKUE.mjs","sourcesContent":["// =============================================================================\n// @datatechsolutions/windsock/ui — BillingPanel\n// Shows the current organization subscription plus the plan catalogue, with\n// actions for opening the Stripe portal, starting checkout, or cancelling.\n// Backed by `AuthClient.getSubscription / getPlans / createPortalSession /\n// createCheckoutSession / cancelSubscription`.\n// =============================================================================\n\nimport { useEffect, useState, useCallback } from 'react'\nimport { useTranslations, useFormatter } from '@ui/lib/i18n-context'\nimport {\n SectionCard,\n Button,\n Badge,\n StatusBadge,\n InlineSpinner,\n ListCard,\n ListCardItem,\n triggerHaptic,\n} from '@ui/index'\nimport type {\n SubscriptionDetails,\n PlanDefinition,\n SubscriptionTier,\n} from '@datatechsolutions/shared-domain'\nimport { useAuth } from '../../_auth'\n\nexport interface BillingPanelProps {\n /**\n * Which billing interval to prefer when starting checkout. Defaults to\n * `'monthly'`. Surface a toggle in the host app if both matter.\n */\n defaultBillingInterval?: 'monthly' | 'yearly'\n /**\n * Called after the portal/checkout URL is resolved. Defaults to\n * `window.location.assign(url)`. Override to open in a new tab, use a\n * router, etc.\n */\n onRedirect?: (url: string) => void\n}\n\nconst TIER_ORDER: Record<SubscriptionTier, number> = {\n free_trial: 0,\n starter: 1,\n professional: 2,\n enterprise: 3,\n}\n\nexport function BillingPanel({\n defaultBillingInterval = 'monthly',\n onRedirect,\n}: BillingPanelProps) {\n const t = useTranslations('windsock')\n const format = useFormatter()\n const { client } = useAuth()\n\n const [subscription, setSubscription] = useState<SubscriptionDetails | null>(null)\n const [plans, setPlans] = useState<PlanDefinition[]>([])\n const [isLoading, setIsLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [busyAction, setBusyAction] = useState<string | null>(null)\n\n const redirect = useCallback((url: string) => {\n if (onRedirect) {\n onRedirect(url)\n } else if (typeof window !== 'undefined') {\n window.location.assign(url)\n }\n }, [onRedirect])\n\n const load = useCallback(async () => {\n setIsLoading(true)\n setError(null)\n try {\n const [sub, availablePlans] = await Promise.all([\n client.getSubscription(),\n client.getPlans(),\n ])\n setSubscription(sub)\n setPlans(\n [...availablePlans]\n .filter((plan: { active: boolean }) => plan.active)\n .sort(\n (a: { tier: SubscriptionTier }, b: { tier: SubscriptionTier }) =>\n (TIER_ORDER[a.tier] ?? 0) - (TIER_ORDER[b.tier] ?? 0),\n ),\n )\n } catch (loadError) {\n setError(loadError instanceof Error ? loadError.message : String(loadError))\n } finally {\n setIsLoading(false)\n }\n }, [client])\n\n useEffect(() => {\n void load()\n }, [load])\n\n const handleOpenPortal = useCallback(async () => {\n setBusyAction('portal')\n triggerHaptic('light')\n try {\n const { url } = await client.createPortalSession()\n redirect(url)\n } catch (portalError) {\n setError(portalError instanceof Error ? portalError.message : String(portalError))\n triggerHaptic('error')\n } finally {\n setBusyAction(null)\n }\n }, [client, redirect])\n\n const handleStartCheckout = useCallback(async (planCode: string) => {\n setBusyAction(`checkout:${planCode}`)\n triggerHaptic('light')\n try {\n const { url } = await client.createCheckoutSession(planCode, defaultBillingInterval)\n redirect(url)\n } catch (checkoutError) {\n setError(checkoutError instanceof Error ? checkoutError.message : String(checkoutError))\n triggerHaptic('error')\n } finally {\n setBusyAction(null)\n }\n }, [client, defaultBillingInterval, redirect])\n\n const handleCancel = useCallback(async () => {\n if (typeof window !== 'undefined') {\n const confirmed = window.confirm(t('billing.cancelConfirm'))\n if (!confirmed) return\n }\n setBusyAction('cancel')\n triggerHaptic('warning')\n try {\n const result = await client.cancelSubscription()\n if (!result.success) {\n throw new Error(result.error ?? 'Subscription cancellation failed')\n }\n triggerHaptic('success')\n await load()\n } catch (cancelError) {\n setError(cancelError instanceof Error ? cancelError.message : String(cancelError))\n triggerHaptic('error')\n } finally {\n setBusyAction(null)\n }\n }, [client, load, t])\n\n if (isLoading) {\n return (\n <div className=\"flex items-center justify-center py-12\">\n <InlineSpinner />\n </div>\n )\n }\n\n const currentPlan = subscription?.plan ?? plans.find((plan) => plan.id === subscription?.planId) ?? null\n const currentTier = subscription?.tier ?? currentPlan?.tier ?? null\n\n return (\n <div className=\"space-y-6\">\n {error && (\n <div\n role=\"alert\"\n className=\"rounded-xl border border-red-300/40 bg-red-50/80 px-4 py-3 text-sm text-red-700 dark:border-red-500/30 dark:bg-red-500/10 dark:text-red-300\"\n >\n {error}\n </div>\n )}\n\n <SectionCard\n header={{\n title: t('billing.currentPlan.title'),\n subtitle: t('billing.currentPlan.description'),\n }}\n >\n {subscription && currentPlan ? (\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"text-lg font-semibold text-gray-900 dark:text-white\">\n {currentPlan.name}\n </span>\n <StatusBadge\n status={\n subscription.status === 'active' ? 'success'\n : subscription.status === 'past_due' ? 'pending'\n : 'error'\n }\n label={t(`billing.status.${subscription.status}`)}\n />\n {subscription.cancelAtPeriodEnd && (\n <Badge color=\"amber\">{t('billing.currentPlan.cancelAtPeriodEnd')}</Badge>\n )}\n </div>\n\n <dl className=\"grid grid-cols-1 gap-3 text-sm sm:grid-cols-2\">\n <div>\n <dt className=\"text-gray-500 dark:text-gray-400\">\n {t('billing.currentPlan.price')}\n </dt>\n <dd className=\"font-medium text-gray-900 dark:text-white\">\n {format.number(currentPlan.price, { style: 'currency', currency: currentPlan.currency })}\n {' '}/{' '}\n {t(`billing.interval.${currentPlan.interval}`)}\n </dd>\n </div>\n {subscription.currentPeriodEnd && (\n <div>\n <dt className=\"text-gray-500 dark:text-gray-400\">\n {t('billing.currentPlan.renewsOn')}\n </dt>\n <dd className=\"font-medium text-gray-900 dark:text-white\">\n {format.dateTime(new Date(subscription.currentPeriodEnd), { dateStyle: 'medium' })}\n </dd>\n </div>\n )}\n </dl>\n\n <div className=\"flex flex-wrap gap-2 pt-2\">\n <Button\n size=\"sm\"\n color=\"ios-glass-blue\"\n onClick={handleOpenPortal}\n loading={busyAction === 'portal'}\n disabled={busyAction !== null}\n >\n {t('billing.currentPlan.manageInPortal')}\n </Button>\n {subscription.status === 'active' && !subscription.cancelAtPeriodEnd && (\n <Button\n size=\"sm\"\n color=\"ios-glass-red\"\n onClick={handleCancel}\n loading={busyAction === 'cancel'}\n disabled={busyAction !== null}\n >\n {t('billing.currentPlan.cancel')}\n </Button>\n )}\n </div>\n </div>\n ) : (\n <p className=\"text-sm text-gray-500 dark:text-gray-400\">\n {t('billing.currentPlan.noSubscription')}\n </p>\n )}\n </SectionCard>\n\n <SectionCard\n header={{\n title: t('billing.plans.title'),\n subtitle: t('billing.plans.description'),\n }}\n >\n {plans.length === 0 ? (\n <p className=\"text-sm text-gray-500 dark:text-gray-400\">\n {t('billing.plans.empty')}\n </p>\n ) : (\n <ListCard>\n {plans.map((plan) => {\n const isCurrent = currentPlan?.id === plan.id\n const isDowngrade = currentTier != null\n && (TIER_ORDER[plan.tier] ?? 0) < (TIER_ORDER[currentTier] ?? 0)\n return (\n <ListCardItem\n key={plan.id}\n leading={\n <div className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-gradient-to-br from-violet-500/20 to-blue-500/20 text-violet-600 dark:text-violet-300\">\n <span className=\"text-sm font-bold uppercase\">{plan.tier.charAt(0)}</span>\n </div>\n }\n trailing={\n isCurrent ? (\n <Badge color=\"green\">{t('billing.plans.currentBadge')}</Badge>\n ) : (\n isDowngrade ? (\n <Button\n size=\"sm\"\n plain\n onClick={() => handleStartCheckout(plan.code)}\n loading={busyAction === `checkout:${plan.code}`}\n disabled={busyAction !== null}\n >\n {t('billing.plans.downgradeAction')}\n </Button>\n ) : (\n <Button\n size=\"sm\"\n color=\"ios-glass-blue\"\n onClick={() => handleStartCheckout(plan.code)}\n loading={busyAction === `checkout:${plan.code}`}\n disabled={busyAction !== null}\n >\n {t('billing.plans.selectAction')}\n </Button>\n )\n )\n }\n >\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex items-center gap-2\">\n <p className=\"text-sm font-medium text-gray-900 dark:text-white\">\n {plan.name}\n </p>\n <span className=\"text-xs text-gray-500 dark:text-gray-400\">\n {format.number(plan.price, { style: 'currency', currency: plan.currency })}\n {' '}/{' '}\n {t(`billing.interval.${plan.interval}`)}\n </span>\n </div>\n {plan.description && (\n <p className=\"text-xs text-gray-500 dark:text-gray-400\">\n {plan.description}\n </p>\n )}\n </div>\n </ListCardItem>\n )\n })}\n </ListCard>\n )}\n </SectionCard>\n </div>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/platform/billing/billing-panel.tsx"],"names":[],"mappings":"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","file":"chunk-YHD6SJIN.mjs","sourcesContent":["// =============================================================================\n// @datatechsolutions/windsock/ui — BillingPanel\n// Shows the current organization subscription plus the plan catalogue, with\n// actions for opening the Stripe portal, starting checkout, or cancelling.\n// Backed by `AuthClient.getSubscription / getPlans / createPortalSession /\n// createCheckoutSession / cancelSubscription`.\n// =============================================================================\n\nimport { useEffect, useState, useCallback } from 'react'\nimport { useTranslations, useFormatter } from '@ui/lib/i18n-context'\nimport {\n SectionCard,\n Button,\n Badge,\n StatusBadge,\n InlineSpinner,\n ListCard,\n ListCardItem,\n triggerHaptic,\n} from '@ui/index'\nimport type {\n SubscriptionDetails,\n PlanDefinition,\n SubscriptionTier,\n} from '@datatechsolutions/shared-domain'\nimport { useAuth } from '../../_auth'\n\nexport interface BillingPanelProps {\n /**\n * Which billing interval to prefer when starting checkout. Defaults to\n * `'monthly'`. Surface a toggle in the host app if both matter.\n */\n defaultBillingInterval?: 'monthly' | 'yearly'\n /**\n * Called after the portal/checkout URL is resolved. Defaults to\n * `window.location.assign(url)`. Override to open in a new tab, use a\n * router, etc.\n */\n onRedirect?: (url: string) => void\n}\n\nconst TIER_ORDER: Record<SubscriptionTier, number> = {\n free_trial: 0,\n starter: 1,\n professional: 2,\n enterprise: 3,\n}\n\nexport function BillingPanel({\n defaultBillingInterval = 'monthly',\n onRedirect,\n}: BillingPanelProps) {\n const t = useTranslations('windsock')\n const format = useFormatter()\n const { client } = useAuth()\n\n const [subscription, setSubscription] = useState<SubscriptionDetails | null>(null)\n const [plans, setPlans] = useState<PlanDefinition[]>([])\n const [isLoading, setIsLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [busyAction, setBusyAction] = useState<string | null>(null)\n\n const redirect = useCallback((url: string) => {\n if (onRedirect) {\n onRedirect(url)\n } else if (typeof window !== 'undefined') {\n window.location.assign(url)\n }\n }, [onRedirect])\n\n const load = useCallback(async () => {\n setIsLoading(true)\n setError(null)\n try {\n const [sub, availablePlans] = await Promise.all([\n client.getSubscription(),\n client.getPlans(),\n ])\n setSubscription(sub)\n setPlans(\n [...availablePlans]\n .filter((plan: { active: boolean }) => plan.active)\n .sort(\n (a: { tier: SubscriptionTier }, b: { tier: SubscriptionTier }) =>\n (TIER_ORDER[a.tier] ?? 0) - (TIER_ORDER[b.tier] ?? 0),\n ),\n )\n } catch (loadError) {\n setError(loadError instanceof Error ? loadError.message : String(loadError))\n } finally {\n setIsLoading(false)\n }\n }, [client])\n\n useEffect(() => {\n void load()\n }, [load])\n\n const handleOpenPortal = useCallback(async () => {\n setBusyAction('portal')\n triggerHaptic('light')\n try {\n const { url } = await client.createPortalSession()\n redirect(url)\n } catch (portalError) {\n setError(portalError instanceof Error ? portalError.message : String(portalError))\n triggerHaptic('error')\n } finally {\n setBusyAction(null)\n }\n }, [client, redirect])\n\n const handleStartCheckout = useCallback(async (planCode: string) => {\n setBusyAction(`checkout:${planCode}`)\n triggerHaptic('light')\n try {\n const { url } = await client.createCheckoutSession(planCode, defaultBillingInterval)\n redirect(url)\n } catch (checkoutError) {\n setError(checkoutError instanceof Error ? checkoutError.message : String(checkoutError))\n triggerHaptic('error')\n } finally {\n setBusyAction(null)\n }\n }, [client, defaultBillingInterval, redirect])\n\n const handleCancel = useCallback(async () => {\n if (typeof window !== 'undefined') {\n const confirmed = window.confirm(t('billing.cancelConfirm'))\n if (!confirmed) return\n }\n setBusyAction('cancel')\n triggerHaptic('warning')\n try {\n const result = await client.cancelSubscription()\n if (!result.success) {\n throw new Error(result.error ?? 'Subscription cancellation failed')\n }\n triggerHaptic('success')\n await load()\n } catch (cancelError) {\n setError(cancelError instanceof Error ? cancelError.message : String(cancelError))\n triggerHaptic('error')\n } finally {\n setBusyAction(null)\n }\n }, [client, load, t])\n\n if (isLoading) {\n return (\n <div className=\"flex items-center justify-center py-12\">\n <InlineSpinner />\n </div>\n )\n }\n\n const currentPlan = subscription?.plan ?? plans.find((plan) => plan.id === subscription?.planId) ?? null\n const currentTier = subscription?.tier ?? currentPlan?.tier ?? null\n\n return (\n <div className=\"space-y-6\">\n {error && (\n <div\n role=\"alert\"\n className=\"rounded-xl border border-red-300/40 bg-red-50/80 px-4 py-3 text-sm text-red-700 dark:border-red-500/30 dark:bg-red-500/10 dark:text-red-300\"\n >\n {error}\n </div>\n )}\n\n <SectionCard\n header={{\n title: t('billing.currentPlan.title'),\n subtitle: t('billing.currentPlan.description'),\n }}\n >\n {subscription && currentPlan ? (\n <div className=\"space-y-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"text-lg font-semibold text-slate-900 dark:text-white\">\n {currentPlan.name}\n </span>\n <StatusBadge\n status={\n subscription.status === 'active' ? 'success'\n : subscription.status === 'past_due' ? 'pending'\n : 'error'\n }\n label={t(`billing.status.${subscription.status}`)}\n />\n {subscription.cancelAtPeriodEnd && (\n <Badge color=\"amber\">{t('billing.currentPlan.cancelAtPeriodEnd')}</Badge>\n )}\n </div>\n\n <dl className=\"grid grid-cols-1 gap-3 text-sm sm:grid-cols-2\">\n <div>\n <dt className=\"text-slate-500 dark:text-slate-400\">\n {t('billing.currentPlan.price')}\n </dt>\n <dd className=\"font-medium text-slate-900 dark:text-white\">\n {format.number(currentPlan.price, { style: 'currency', currency: currentPlan.currency })}\n {' '}/{' '}\n {t(`billing.interval.${currentPlan.interval}`)}\n </dd>\n </div>\n {subscription.currentPeriodEnd && (\n <div>\n <dt className=\"text-slate-500 dark:text-slate-400\">\n {t('billing.currentPlan.renewsOn')}\n </dt>\n <dd className=\"font-medium text-slate-900 dark:text-white\">\n {format.dateTime(new Date(subscription.currentPeriodEnd), { dateStyle: 'medium' })}\n </dd>\n </div>\n )}\n </dl>\n\n <div className=\"flex flex-wrap gap-2 pt-2\">\n <Button\n size=\"sm\"\n color=\"ios-glass-blue\"\n onClick={handleOpenPortal}\n loading={busyAction === 'portal'}\n disabled={busyAction !== null}\n >\n {t('billing.currentPlan.manageInPortal')}\n </Button>\n {subscription.status === 'active' && !subscription.cancelAtPeriodEnd && (\n <Button\n size=\"sm\"\n color=\"ios-glass-red\"\n onClick={handleCancel}\n loading={busyAction === 'cancel'}\n disabled={busyAction !== null}\n >\n {t('billing.currentPlan.cancel')}\n </Button>\n )}\n </div>\n </div>\n ) : (\n <p className=\"text-sm text-slate-500 dark:text-slate-400\">\n {t('billing.currentPlan.noSubscription')}\n </p>\n )}\n </SectionCard>\n\n <SectionCard\n header={{\n title: t('billing.plans.title'),\n subtitle: t('billing.plans.description'),\n }}\n >\n {plans.length === 0 ? (\n <p className=\"text-sm text-slate-500 dark:text-slate-400\">\n {t('billing.plans.empty')}\n </p>\n ) : (\n <ListCard>\n {plans.map((plan) => {\n const isCurrent = currentPlan?.id === plan.id\n const isDowngrade = currentTier != null\n && (TIER_ORDER[plan.tier] ?? 0) < (TIER_ORDER[currentTier] ?? 0)\n return (\n <ListCardItem\n key={plan.id}\n leading={\n <div className=\"flex h-10 w-10 items-center justify-center rounded-xl bg-gradient-to-br from-violet-500/20 to-blue-500/20 text-violet-600 dark:text-violet-300\">\n <span className=\"text-sm font-bold uppercase\">{plan.tier.charAt(0)}</span>\n </div>\n }\n trailing={\n isCurrent ? (\n <Badge color=\"green\">{t('billing.plans.currentBadge')}</Badge>\n ) : (\n isDowngrade ? (\n <Button\n size=\"sm\"\n plain\n onClick={() => handleStartCheckout(plan.code)}\n loading={busyAction === `checkout:${plan.code}`}\n disabled={busyAction !== null}\n >\n {t('billing.plans.downgradeAction')}\n </Button>\n ) : (\n <Button\n size=\"sm\"\n color=\"ios-glass-blue\"\n onClick={() => handleStartCheckout(plan.code)}\n loading={busyAction === `checkout:${plan.code}`}\n disabled={busyAction !== null}\n >\n {t('billing.plans.selectAction')}\n </Button>\n )\n )\n }\n >\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex items-center gap-2\">\n <p className=\"text-sm font-medium text-slate-900 dark:text-white\">\n {plan.name}\n </p>\n <span className=\"text-xs text-slate-500 dark:text-slate-400\">\n {format.number(plan.price, { style: 'currency', currency: plan.currency })}\n {' '}/{' '}\n {t(`billing.interval.${plan.interval}`)}\n </span>\n </div>\n {plan.description && (\n <p className=\"text-xs text-slate-500 dark:text-slate-400\">\n {plan.description}\n </p>\n )}\n </div>\n </ListCardItem>\n )\n })}\n </ListCard>\n )}\n </SectionCard>\n </div>\n )\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createContext, useContext } from 'react';
|
|
3
|
+
import { IntlMessageFormat } from 'intl-messageformat';
|
|
3
4
|
import { jsx } from 'react/jsx-runtime';
|
|
4
5
|
|
|
5
6
|
// src/lib/i18n-context.tsx
|
|
@@ -66,6 +67,19 @@ function useFormatter() {
|
|
|
66
67
|
number: (value, options) => new Intl.NumberFormat(locale, options).format(value)
|
|
67
68
|
};
|
|
68
69
|
}
|
|
70
|
+
var FORMATTER_CACHE = /* @__PURE__ */ new Map();
|
|
71
|
+
function getFormatter(locale, raw) {
|
|
72
|
+
const key = `${locale}\u200B${raw}`;
|
|
73
|
+
let formatter = FORMATTER_CACHE.get(key);
|
|
74
|
+
if (formatter) return formatter;
|
|
75
|
+
try {
|
|
76
|
+
formatter = new IntlMessageFormat(raw, locale, void 0, { ignoreTag: true });
|
|
77
|
+
FORMATTER_CACHE.set(key, formatter);
|
|
78
|
+
return formatter;
|
|
79
|
+
} catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
69
83
|
function createI18nFromMessages(locale, messages) {
|
|
70
84
|
return {
|
|
71
85
|
locale,
|
|
@@ -74,7 +88,16 @@ function createI18nFromMessages(locale, messages) {
|
|
|
74
88
|
const fn = ((key, params) => {
|
|
75
89
|
const fullKey = namespace ? `${namespace}.${key}` : key;
|
|
76
90
|
const raw = getNestedValue(messages, fullKey);
|
|
77
|
-
|
|
91
|
+
if (typeof raw !== "string") return key;
|
|
92
|
+
const formatter = getFormatter(locale, raw);
|
|
93
|
+
if (formatter) {
|
|
94
|
+
try {
|
|
95
|
+
const out = formatter.format(params);
|
|
96
|
+
return typeof out === "string" ? out : Array.isArray(out) ? out.join("") : String(out);
|
|
97
|
+
} catch {
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
let result = raw;
|
|
78
101
|
if (params) {
|
|
79
102
|
for (const [paramKey, paramValue] of Object.entries(params)) {
|
|
80
103
|
result = result.replace(new RegExp(`\\{${paramKey}\\}`, "g"), String(paramValue));
|
|
@@ -92,5 +115,5 @@ function createI18nFromMessages(locale, messages) {
|
|
|
92
115
|
}
|
|
93
116
|
|
|
94
117
|
export { I18nProvider, createI18nFromMessages, useFormatter, useLocale, useTranslations };
|
|
95
|
-
//# sourceMappingURL=chunk-
|
|
96
|
-
//# sourceMappingURL=chunk-
|
|
118
|
+
//# sourceMappingURL=chunk-ZEFNBGYI.mjs.map
|
|
119
|
+
//# sourceMappingURL=chunk-ZEFNBGYI.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/i18n-context.tsx"],"names":[],"mappings":"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","file":"chunk-ZEFNBGYI.mjs","sourcesContent":["import { createContext, useContext, type ReactNode } from 'react'\nimport { IntlMessageFormat } from 'intl-messageformat'\n\ntype TranslateFn = ((key: string, params?: Record<string, unknown>) => string) & {\n /** Return the raw (unparsed) value at a given key — useful for arrays/objects in messages */\n raw: (key: string) => unknown\n}\n\nexport interface I18nContextValue {\n translate: (namespace?: string) => TranslateFn\n locale: string\n messages?: Record<string, unknown>\n}\n\nconst I18nContext = createContext<I18nContextValue | null>(null)\n\nexport type I18nProviderProps = {\n children: ReactNode\n value: I18nContextValue\n}\n\nexport function I18nProvider({ children, value }: I18nProviderProps) {\n return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>\n}\n\nexport function useTranslations(namespace?: string): TranslateFn {\n const context = useContext(I18nContext)\n if (!context) {\n const fallback = ((key: string, params?: Record<string, unknown>) => {\n let result = namespace ? `${namespace}.${key}` : key\n if (params) {\n for (const [paramKey, paramValue] of Object.entries(params)) {\n result = result.replace(`{${paramKey}}`, String(paramValue))\n }\n }\n return result\n }) as TranslateFn\n fallback.raw = (key: string) => key\n return fallback\n }\n const translateFn = context.translate(namespace) as TranslateFn\n if (!translateFn.raw) {\n translateFn.raw = (key: string) => {\n const messages = context.messages\n if (!messages) return undefined\n const fullKey = namespace ? `${namespace}.${key}` : key\n return getNestedValue(messages, fullKey)\n }\n }\n return translateFn\n}\n\nfunction getNestedValue(object: Record<string, unknown>, path: string): unknown {\n const parts = path.split('.')\n let current: unknown = object\n for (const part of parts) {\n if (current === null || current === undefined || typeof current !== 'object') return undefined\n current = (current as Record<string, unknown>)[part]\n }\n return current\n}\n\nexport function useLocale(): string {\n const context = useContext(I18nContext)\n return context?.locale ?? 'en'\n}\n\nexport type I18nFormatter = {\n dateTime: (date: Date, options?: Intl.DateTimeFormatOptions) => string\n relativeTime: (date: Date, options?: Intl.RelativeTimeFormatOptions) => string\n number: (value: number, options?: Intl.NumberFormatOptions) => string\n}\n\nexport function useFormatter(): I18nFormatter {\n const locale = useLocale()\n return {\n dateTime: (date: Date, options?: Intl.DateTimeFormatOptions) =>\n new Intl.DateTimeFormat(locale, options).format(date),\n relativeTime: (date: Date) => {\n const now = Date.now()\n const diffMs = date.getTime() - now\n const diffSeconds = Math.round(diffMs / 1000)\n const diffMinutes = Math.round(diffMs / 60000)\n const diffHours = Math.round(diffMs / 3600000)\n const diffDays = Math.round(diffMs / 86400000)\n const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' })\n if (Math.abs(diffSeconds) < 60) return rtf.format(diffSeconds, 'second')\n if (Math.abs(diffMinutes) < 60) return rtf.format(diffMinutes, 'minute')\n if (Math.abs(diffHours) < 24) return rtf.format(diffHours, 'hour')\n return rtf.format(diffDays, 'day')\n },\n number: (value: number, options?: Intl.NumberFormatOptions) =>\n new Intl.NumberFormat(locale, options).format(value),\n }\n}\n\n/**\n * Cache of compiled `IntlMessageFormat` instances keyed by `locale${rawString}`.\n * Compilation is the expensive step — parsing the ICU AST. Once compiled,\n * `.format(params)` is cheap. The cache is process-wide because messages\n * are static for a session; LRU eviction is unnecessary at our message\n * volume (<5k unique strings × 6 locales = ~30k cap, fits comfortably).\n */\nconst FORMATTER_CACHE = new Map<string, IntlMessageFormat>()\n\nfunction getFormatter(locale: string, raw: string): IntlMessageFormat | null {\n const key = `${locale}${raw}`\n let formatter = FORMATTER_CACHE.get(key)\n if (formatter) return formatter\n try {\n formatter = new IntlMessageFormat(raw, locale, undefined, { ignoreTag: true })\n FORMATTER_CACHE.set(key, formatter)\n return formatter\n } catch {\n // Parse failure: malformed ICU. Caller falls back to the raw string —\n // safer than throwing during render.\n return null\n }\n}\n\n/**\n * Create an I18nContextValue from a flat messages object and locale.\n * Messages should be a nested object where keys are namespaces and\n * values are objects of translation key → ICU MessageFormat string.\n *\n * Full ICU support via `intl-messageformat`: plurals (`{count, plural,\n * one {# item} other {# items}}`), select (`{gender, select, male {he}\n * female {she} other {they}}`), number/date format. Strings without\n * any ICU markup work transparently — the formatter falls through to\n * its identity output. Old `{param}` strings (no surrounding type\n * keyword) still work as plain interpolation.\n *\n * Parse failures fall back to the raw template + simple-replace so a\n * single bad message can never crash render. `tracing` console.warn\n * goes out for the first failure so authors notice.\n */\nexport function createI18nFromMessages(\n locale: string,\n messages: Record<string, unknown>,\n): I18nContextValue {\n return {\n locale,\n messages,\n translate: (namespace?: string) => {\n const fn = ((key: string, params?: Record<string, unknown>) => {\n const fullKey = namespace ? `${namespace}.${key}` : key\n const raw = getNestedValue(messages, fullKey)\n if (typeof raw !== 'string') return key\n const formatter = getFormatter(locale, raw)\n if (formatter) {\n try {\n const out = formatter.format(params as Record<string, string | number | boolean | null | undefined | Date> | undefined)\n // IntlMessageFormat returns string | string[] | ReactNode[] —\n // narrow to string here because the i18n context is typed to\n // emit string. Array branch only triggers when `tagsToParts`\n // is enabled, which we never opt into.\n return typeof out === 'string' ? out : Array.isArray(out) ? out.join('') : String(out)\n } catch {\n // Format-time failure (e.g. missing param) — fall through.\n }\n }\n // Fallback: simple {param} replace for non-ICU or parse-failed strings.\n let result = raw\n if (params) {\n for (const [paramKey, paramValue] of Object.entries(params)) {\n result = result.replace(new RegExp(`\\\\{${paramKey}\\\\}`, 'g'), String(paramValue))\n }\n }\n return result\n }) as TranslateFn\n fn.raw = (key: string) => {\n const fullKey = namespace ? `${namespace}.${key}` : key\n return getNestedValue(messages, fullKey)\n }\n return fn\n },\n }\n}\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { AdminOrganizationDetail } from './chunk-
|
|
3
|
-
import { BillingPanel } from './chunk-
|
|
4
|
-
import { UserProfile } from './chunk-
|
|
5
|
-
import { useAuth, InlineSpinner, SegmentedControl } from './chunk-
|
|
6
|
-
import { useTranslations } from './chunk-
|
|
2
|
+
import { AdminOrganizationDetail } from './chunk-SCGICCQM.mjs';
|
|
3
|
+
import { BillingPanel } from './chunk-YHD6SJIN.mjs';
|
|
4
|
+
import { UserProfile } from './chunk-3VCSMSJB.mjs';
|
|
5
|
+
import { useAuth, InlineSpinner, SegmentedControl } from './chunk-QEACOJXX.mjs';
|
|
6
|
+
import { useTranslations } from './chunk-ZEFNBGYI.mjs';
|
|
7
7
|
import { useMemo, useState, useEffect } from 'react';
|
|
8
8
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
9
9
|
|
|
@@ -94,5 +94,5 @@ function PlatformSettings({
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
export { PlatformSettings };
|
|
97
|
-
//# sourceMappingURL=chunk-
|
|
98
|
-
//# sourceMappingURL=chunk-
|
|
97
|
+
//# sourceMappingURL=chunk-ZPV7X4ZE.mjs.map
|
|
98
|
+
//# sourceMappingURL=chunk-ZPV7X4ZE.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/platform/settings/platform-settings.tsx"],"names":[],"mappings":"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","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/platform/settings/platform-settings.tsx"],"names":[],"mappings":"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","file":"chunk-ZPV7X4ZE.mjs","sourcesContent":["// =============================================================================\n// @datatechsolutions/windsock/ui — PlatformSettings\n// Unified settings shell consumed by every product (astrlabe, kori).\n// Composes existing building blocks:\n// - `<UserProfile>` — Profile / Security / Sessions / Linked accounts\n// - `<AdminOrganizationDetail>` — Members / Invitations / Domains\n// - `<BillingPanel>` — Current subscription + plan catalogue\n// Apps mount this at their `/settings` route; feature toggles hide sections\n// that a given user's role cannot access.\n// =============================================================================\n\nimport { useEffect, useMemo, useState } from 'react'\nimport { useTranslations } from '@ui/lib/i18n-context'\nimport { SegmentedControl, InlineSpinner } from '@ui/index'\nimport type { AdminClient, AuthOrganization } from '@datatechsolutions/shared-domain'\n\nimport { useAuth } from '../../_auth'\nimport { UserProfile } from '../auth/user-profile'\nimport { AdminOrganizationDetail } from '../admin/admin-organization-detail'\nimport { BillingPanel, type BillingPanelProps } from '../billing/billing-panel'\n\nexport type PlatformSettingsSection = 'account' | 'organization' | 'billing'\n\nexport interface PlatformSettingsProps {\n /**\n * Sections to surface to the current user. The host app is responsible for\n * picking the right set based on RBAC — e.g. hide `organization` for users\n * without `org:manage` and hide `billing` for users without `billing:read`.\n * Defaults to all three.\n */\n sections?: PlatformSettingsSection[]\n /** Starting section. Defaults to the first item in `sections`. */\n defaultSection?: PlatformSettingsSection\n /**\n * Windsock admin API client. Required when `organization` is in `sections`.\n * Create it once with `createAdminClient({ issuer, authClient })` and reuse.\n */\n adminClient?: AdminClient\n /**\n * Current organization id (usually `ctx.organizationId` from the JWT).\n * Required when `organization` is in `sections`.\n */\n organizationId?: string\n /** Forwarded to `<BillingPanel>` — e.g. redirect handler, billing interval. */\n billing?: BillingPanelProps\n}\n\nconst DEFAULT_SECTIONS: PlatformSettingsSection[] = ['account', 'organization', 'billing']\n\nexport function PlatformSettings({\n sections = DEFAULT_SECTIONS,\n defaultSection,\n adminClient,\n organizationId,\n billing,\n}: PlatformSettingsProps) {\n const t = useTranslations('windsock')\n const { status } = useAuth()\n\n const visibleSections = useMemo(() => {\n // Drop `organization` if the caller didn't pass an admin client + org id.\n return sections.filter((section) => {\n if (section === 'organization') {\n return Boolean(adminClient && organizationId)\n }\n return true\n })\n }, [sections, adminClient, organizationId])\n\n const initialSection: PlatformSettingsSection = (\n defaultSection && visibleSections.includes(defaultSection)\n ? defaultSection\n : visibleSections[0] ?? 'account'\n )\n\n const [activeSection, setActiveSection] = useState<PlatformSettingsSection>(initialSection)\n const [organization, setOrganization] = useState<AuthOrganization | null>(null)\n const [orgLoadError, setOrgLoadError] = useState<string | null>(null)\n\n // Resolve the org detail record (AdminOrganizationDetail needs the full\n // AuthOrganization, not just the id). Fires once the organization tab is\n // first selected so the listOrganizations round-trip is lazy.\n useEffect(() => {\n if (activeSection !== 'organization') return\n if (!adminClient || !organizationId) return\n if (organization?.id === organizationId) return\n\n let cancelled = false\n setOrgLoadError(null)\n void adminClient.listOrganizations()\n .then((orgs) => {\n if (cancelled) return\n const match = orgs.find((org) => org.id === organizationId)\n if (match) {\n setOrganization(match)\n } else {\n setOrgLoadError('Organization not found')\n }\n })\n .catch((loadError: unknown) => {\n if (cancelled) return\n setOrgLoadError(loadError instanceof Error ? loadError.message : String(loadError))\n })\n return () => {\n cancelled = true\n }\n }, [activeSection, adminClient, organizationId, organization?.id])\n\n if (status === 'loading') {\n return (\n <div className=\"flex items-center justify-center py-12\">\n <InlineSpinner />\n </div>\n )\n }\n\n if (status !== 'authenticated') {\n return null\n }\n\n if (visibleSections.length === 0) {\n return null\n }\n\n const segments = visibleSections.map((section) => ({\n value: section,\n label: t(`platformSettings.sections.${section}`),\n }))\n\n return (\n <div className=\"space-y-6\">\n {visibleSections.length > 1 && (\n <SegmentedControl\n segments={segments}\n value={activeSection}\n onChange={(value: string) => setActiveSection(value as PlatformSettingsSection)}\n fullWidth\n />\n )}\n\n {activeSection === 'account' && <UserProfile />}\n\n {activeSection === 'organization' && adminClient && organizationId && (\n organization ? (\n <AdminOrganizationDetail\n client={adminClient}\n organization={organization}\n />\n ) : orgLoadError ? (\n <div\n role=\"alert\"\n className=\"rounded-xl border border-red-300/40 bg-red-50/80 px-4 py-3 text-sm text-red-700 dark:border-red-500/30 dark:bg-red-500/10 dark:text-red-300\"\n >\n {orgLoadError}\n </div>\n ) : (\n <div className=\"flex items-center justify-center py-12\">\n <InlineSpinner />\n </div>\n )\n )}\n\n {activeSection === 'billing' && <BillingPanel {...billing} />}\n </div>\n )\n}\n"]}
|