@flamingo-stack/openframe-frontend-core 0.0.575 → 0.0.577-1943.5293.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/{chunk-BGE7CKXC.js → chunk-2YCUEUIZ.js} +8 -8
- package/dist/{chunk-42PQFBUS.js → chunk-4D2BR756.js} +3 -3
- package/dist/{chunk-BTZF3JRS.js → chunk-4KR7JWKB.js} +4 -4
- package/dist/{chunk-7G23ANVM.cjs → chunk-5DPCIIJ7.cjs} +95 -95
- package/dist/{chunk-7G23ANVM.cjs.map → chunk-5DPCIIJ7.cjs.map} +1 -1
- package/dist/{chunk-K3XONUML.cjs → chunk-6FJABKPX.cjs} +11 -11
- package/dist/{chunk-K3XONUML.cjs.map → chunk-6FJABKPX.cjs.map} +1 -1
- package/dist/{chunk-K574Y2QR.cjs → chunk-6GJBSIRU.cjs} +3 -3
- package/dist/{chunk-K574Y2QR.cjs.map → chunk-6GJBSIRU.cjs.map} +1 -1
- package/dist/{chunk-7Z64COGD.cjs → chunk-72OIVRPG.cjs} +7 -7
- package/dist/{chunk-7Z64COGD.cjs.map → chunk-72OIVRPG.cjs.map} +1 -1
- package/dist/{chunk-XC7WPYPJ.cjs → chunk-75X6BRID.cjs} +171 -171
- package/dist/{chunk-XC7WPYPJ.cjs.map → chunk-75X6BRID.cjs.map} +1 -1
- package/dist/{chunk-QF5B6V4L.cjs → chunk-APFGR2KK.cjs} +41 -41
- package/dist/{chunk-QF5B6V4L.cjs.map → chunk-APFGR2KK.cjs.map} +1 -1
- package/dist/{chunk-2EPUD2VR.js → chunk-AQ5MZVYN.js} +3 -3
- package/dist/{chunk-T5DAFFK7.js → chunk-BBZ6NQL2.js} +2 -2
- package/dist/{chunk-IRJQH7RJ.cjs → chunk-CFTZAZ7R.cjs} +28 -28
- package/dist/{chunk-IRJQH7RJ.cjs.map → chunk-CFTZAZ7R.cjs.map} +1 -1
- package/dist/{chunk-UILNZL6J.cjs → chunk-CIUYHBAY.cjs} +5 -5
- package/dist/{chunk-UILNZL6J.cjs.map → chunk-CIUYHBAY.cjs.map} +1 -1
- package/dist/{chunk-QTVW5XBL.cjs → chunk-ET3Q4FIZ.cjs} +12 -12
- package/dist/{chunk-QTVW5XBL.cjs.map → chunk-ET3Q4FIZ.cjs.map} +1 -1
- package/dist/{chunk-IWISKP3F.js → chunk-FCVAVOXS.js} +3 -3
- package/dist/{chunk-PUL6X6HY.cjs → chunk-GDWBJFMG.cjs} +32 -32
- package/dist/{chunk-PUL6X6HY.cjs.map → chunk-GDWBJFMG.cjs.map} +1 -1
- package/dist/{chunk-ZQE7HN4Q.cjs → chunk-GPWU3PPR.cjs} +37 -37
- package/dist/{chunk-ZQE7HN4Q.cjs.map → chunk-GPWU3PPR.cjs.map} +1 -1
- package/dist/{chunk-BGZCZ2JS.cjs → chunk-HSOMYCUG.cjs} +11 -11
- package/dist/{chunk-BGZCZ2JS.cjs.map → chunk-HSOMYCUG.cjs.map} +1 -1
- package/dist/{chunk-DTSRMQIY.js → chunk-IQFXDS5O.js} +9 -9
- package/dist/{chunk-6D4RVZZJ.js → chunk-JCH6HGQD.js} +3 -3
- package/dist/{chunk-SIRFPFBQ.js → chunk-JQI726T3.js} +2 -2
- package/dist/{chunk-QDOBY3TP.cjs → chunk-KE2TCUOH.cjs} +327 -324
- package/dist/chunk-KE2TCUOH.cjs.map +1 -0
- package/dist/{chunk-7GLY26JF.js → chunk-LHR6AA65.js} +33 -6
- package/dist/chunk-LHR6AA65.js.map +1 -0
- package/dist/{chunk-OE7NV7H3.js → chunk-LYOGSVFO.js} +4 -4
- package/dist/{chunk-SPAAKHQA.cjs → chunk-MIY5FYX3.cjs} +8 -8
- package/dist/{chunk-SPAAKHQA.cjs.map → chunk-MIY5FYX3.cjs.map} +1 -1
- package/dist/{chunk-UPEIX7VG.js → chunk-NEKT67O5.js} +6 -6
- package/dist/{chunk-PBS4F534.js → chunk-NP3XN6ZX.js} +8 -5
- package/dist/chunk-NP3XN6ZX.js.map +1 -0
- package/dist/{chunk-3IUQLB47.cjs → chunk-NQCGDZJ3.cjs} +3 -3
- package/dist/{chunk-3IUQLB47.cjs.map → chunk-NQCGDZJ3.cjs.map} +1 -1
- package/dist/{chunk-BKXL7OYT.cjs → chunk-RCLJSENK.cjs} +6 -6
- package/dist/{chunk-BKXL7OYT.cjs.map → chunk-RCLJSENK.cjs.map} +1 -1
- package/dist/{chunk-WVKRSC65.js → chunk-RNUH5IHZ.js} +3 -3
- package/dist/{chunk-2IK6SB6F.js → chunk-RSMUAAPW.js} +4 -4
- package/dist/{chunk-KSKCQ3ZN.js → chunk-RUJKOU5F.js} +2 -2
- package/dist/{chunk-VIAZWBZ2.cjs → chunk-S4CLML75.cjs} +7 -7
- package/dist/{chunk-VIAZWBZ2.cjs.map → chunk-S4CLML75.cjs.map} +1 -1
- package/dist/{chunk-WAWMZSCP.js → chunk-THDGDYJ3.js} +6 -6
- package/dist/{chunk-KG7D35RU.js → chunk-TU32TSAK.js} +5 -5
- package/dist/{chunk-5QDGP3RI.js → chunk-U3SDSA5K.js} +5 -5
- package/dist/{chunk-SVUZUFT4.cjs → chunk-WOHHZZJK.cjs} +65 -65
- package/dist/{chunk-SVUZUFT4.cjs.map → chunk-WOHHZZJK.cjs.map} +1 -1
- package/dist/{chunk-3U2P63NQ.cjs → chunk-XBBCUC32.cjs} +15 -15
- package/dist/{chunk-3U2P63NQ.cjs.map → chunk-XBBCUC32.cjs.map} +1 -1
- package/dist/{chunk-GFSJXRX7.cjs → chunk-XBSW7IF6.cjs} +23 -23
- package/dist/{chunk-GFSJXRX7.cjs.map → chunk-XBSW7IF6.cjs.map} +1 -1
- package/dist/{chunk-RXJZXMDZ.cjs → chunk-XG2WNF4L.cjs} +26 -26
- package/dist/{chunk-RXJZXMDZ.cjs.map → chunk-XG2WNF4L.cjs.map} +1 -1
- package/dist/{chunk-S6LZN66D.cjs → chunk-YHNIPSG6.cjs} +33 -6
- package/dist/chunk-YHNIPSG6.cjs.map +1 -0
- package/dist/{chunk-5DRCLGOX.js → chunk-YLNZPFDW.js} +2 -2
- package/dist/{chunk-QQ5ZVCD4.js → chunk-Z2FZ5HP2.js} +3 -3
- package/dist/{chunk-ISULYCGY.js → chunk-ZBJ6XSDO.js} +4 -4
- package/dist/components/calendar.cjs +4 -4
- package/dist/components/calendar.js +1 -1
- package/dist/components/case-studies/index.cjs +12 -12
- package/dist/components/case-studies/index.js +6 -6
- package/dist/components/chart.d.ts +18 -3
- package/dist/components/chart.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +4 -4
- package/dist/components/chat/index.js +3 -3
- package/dist/components/contact/index.cjs +7 -7
- package/dist/components/contact/index.js +6 -6
- package/dist/components/docs/index.cjs +10 -10
- package/dist/components/docs/index.js +9 -9
- package/dist/components/embeds/index.cjs +7 -7
- package/dist/components/embeds/index.js +6 -6
- package/dist/components/faq/index.cjs +7 -7
- package/dist/components/faq/index.js +6 -6
- package/dist/components/features/index.cjs +6 -6
- package/dist/components/features/index.js +5 -5
- package/dist/components/help-center-pages/index.cjs +28 -28
- package/dist/components/help-center-pages/index.js +19 -19
- package/dist/components/index.cjs +153 -153
- package/dist/components/index.js +19 -19
- package/dist/components/meeting-scheduler/index.cjs +52 -48
- package/dist/components/meeting-scheduler/index.cjs.map +1 -1
- package/dist/components/meeting-scheduler/index.d.ts.map +1 -1
- package/dist/components/meeting-scheduler/index.js +17 -13
- package/dist/components/meeting-scheduler/index.js.map +1 -1
- package/dist/components/navigation/index.cjs +9 -9
- package/dist/components/navigation/index.js +8 -8
- package/dist/components/onboarding-guides/index.cjs +9 -9
- package/dist/components/onboarding-guides/index.js +8 -8
- package/dist/components/related-content/index.cjs +5 -5
- package/dist/components/related-content/index.js +4 -4
- package/dist/components/tickets/index.cjs +11 -11
- package/dist/components/tickets/index.js +10 -10
- package/dist/components/ui/button/button-styles.d.ts +4 -0
- package/dist/components/ui/button/button-styles.d.ts.map +1 -1
- package/dist/components/ui/button/button.d.ts.map +1 -1
- package/dist/components/ui/dropdown-button.d.ts +9 -1
- package/dist/components/ui/dropdown-button.d.ts.map +1 -1
- package/dist/components/ui/file-manager/index.cjs +11 -11
- package/dist/components/ui/file-manager/index.js +1 -1
- package/dist/components/ui/index.cjs +6 -6
- package/dist/components/ui/index.js +5 -5
- package/dist/index.cjs +10 -10
- package/dist/index.js +9 -9
- package/package.json +1 -1
- package/src/components/chart.tsx +21 -3
- package/src/components/meeting-scheduler/index.tsx +16 -14
- package/src/components/ui/button/button-styles.ts +14 -0
- package/src/components/ui/button/button.tsx +24 -5
- package/src/components/ui/dropdown-button.tsx +11 -0
- package/dist/chunk-7GLY26JF.js.map +0 -1
- package/dist/chunk-PBS4F534.js.map +0 -1
- package/dist/chunk-QDOBY3TP.cjs.map +0 -1
- package/dist/chunk-S6LZN66D.cjs.map +0 -1
- /package/dist/{chunk-BGE7CKXC.js.map → chunk-2YCUEUIZ.js.map} +0 -0
- /package/dist/{chunk-42PQFBUS.js.map → chunk-4D2BR756.js.map} +0 -0
- /package/dist/{chunk-BTZF3JRS.js.map → chunk-4KR7JWKB.js.map} +0 -0
- /package/dist/{chunk-2EPUD2VR.js.map → chunk-AQ5MZVYN.js.map} +0 -0
- /package/dist/{chunk-T5DAFFK7.js.map → chunk-BBZ6NQL2.js.map} +0 -0
- /package/dist/{chunk-IWISKP3F.js.map → chunk-FCVAVOXS.js.map} +0 -0
- /package/dist/{chunk-DTSRMQIY.js.map → chunk-IQFXDS5O.js.map} +0 -0
- /package/dist/{chunk-6D4RVZZJ.js.map → chunk-JCH6HGQD.js.map} +0 -0
- /package/dist/{chunk-SIRFPFBQ.js.map → chunk-JQI726T3.js.map} +0 -0
- /package/dist/{chunk-OE7NV7H3.js.map → chunk-LYOGSVFO.js.map} +0 -0
- /package/dist/{chunk-UPEIX7VG.js.map → chunk-NEKT67O5.js.map} +0 -0
- /package/dist/{chunk-WVKRSC65.js.map → chunk-RNUH5IHZ.js.map} +0 -0
- /package/dist/{chunk-2IK6SB6F.js.map → chunk-RSMUAAPW.js.map} +0 -0
- /package/dist/{chunk-KSKCQ3ZN.js.map → chunk-RUJKOU5F.js.map} +0 -0
- /package/dist/{chunk-WAWMZSCP.js.map → chunk-THDGDYJ3.js.map} +0 -0
- /package/dist/{chunk-KG7D35RU.js.map → chunk-TU32TSAK.js.map} +0 -0
- /package/dist/{chunk-5QDGP3RI.js.map → chunk-U3SDSA5K.js.map} +0 -0
- /package/dist/{chunk-5DRCLGOX.js.map → chunk-YLNZPFDW.js.map} +0 -0
- /package/dist/{chunk-QQ5ZVCD4.js.map → chunk-Z2FZ5HP2.js.map} +0 -0
- /package/dist/{chunk-ISULYCGY.js.map → chunk-ZBJ6XSDO.js.map} +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
var
|
|
7
|
+
var _chunkKE2TCUOHcjs = require('./chunk-KE2TCUOH.cjs');
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
@@ -14,7 +14,7 @@ var _chunk2BFZHTSDcjs = require('./chunk-2BFZHTSD.cjs');
|
|
|
14
14
|
var _chunkQYQXAXVRcjs = require('./chunk-QYQXAXVR.cjs');
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
var
|
|
17
|
+
var _chunk75X6BRIDcjs = require('./chunk-75X6BRID.cjs');
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
var _chunk36NFJULVcjs = require('./chunk-36NFJULV.cjs');
|
|
@@ -38,7 +38,7 @@ var _chunkGSQM4PDRcjs = require('./chunk-GSQM4PDR.cjs');
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
var
|
|
41
|
+
var _chunkMIY5FYX3cjs = require('./chunk-MIY5FYX3.cjs');
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
var _chunkWLSFBRT5cjs = require('./chunk-WLSFBRT5.cjs');
|
|
@@ -47,7 +47,7 @@ var _chunkWLSFBRT5cjs = require('./chunk-WLSFBRT5.cjs');
|
|
|
47
47
|
var _chunk3QDJLLD2cjs = require('./chunk-3QDJLLD2.cjs');
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
var
|
|
50
|
+
var _chunkYHNIPSG6cjs = require('./chunk-YHNIPSG6.cjs');
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
var _chunkPRPZBXWZcjs = require('./chunk-PRPZBXWZ.cjs');
|
|
@@ -122,7 +122,7 @@ CveLink.displayName = "CveLink";
|
|
|
122
122
|
// src/components/platform/ToolBadge.tsx
|
|
123
123
|
|
|
124
124
|
var ToolBadge = ({ toolType, className, iconClassName }) => {
|
|
125
|
-
const label =
|
|
125
|
+
const label = _chunkKE2TCUOHcjs.getToolLabel.call(void 0, toolType);
|
|
126
126
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkPRPZBXWZcjs.cn.call(void 0, "flex items-center gap-1 text-ods-text-secondary", className), children: [
|
|
127
127
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk36NFJULVcjs.ToolIcon, { toolType, className: iconClassName, size: 16 }),
|
|
128
128
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-ods-text-primary text-h4", children: label })
|
|
@@ -133,31 +133,31 @@ ToolBadge.displayName = "ToolBadge";
|
|
|
133
133
|
// src/components/platform/ShellTypeBadge.tsx
|
|
134
134
|
|
|
135
135
|
var shellIconMap = {
|
|
136
|
-
[
|
|
136
|
+
[_chunkKE2TCUOHcjs.ShellTypeValues.POWERSHELL]: {
|
|
137
137
|
icon: _chunkGSQM4PDRcjs.PowershellLogoGreyIcon,
|
|
138
138
|
props: { size: 16, className: "text-ods-text-secondary" }
|
|
139
139
|
},
|
|
140
|
-
[
|
|
140
|
+
[_chunkKE2TCUOHcjs.ShellTypeValues.CMD]: {
|
|
141
141
|
icon: _chunkKZAAIUP5cjs.CmdIcon,
|
|
142
142
|
props: { size: 16, color: "var(--color-text-secondary)" }
|
|
143
143
|
},
|
|
144
|
-
[
|
|
144
|
+
[_chunkKE2TCUOHcjs.ShellTypeValues.BASH]: {
|
|
145
145
|
icon: _chunkKZAAIUP5cjs.BashIcon,
|
|
146
146
|
props: { size: 16, color: "var(--color-text-secondary)" }
|
|
147
147
|
},
|
|
148
|
-
[
|
|
148
|
+
[_chunkKE2TCUOHcjs.ShellTypeValues.PYTHON]: {
|
|
149
149
|
icon: _chunkGSQM4PDRcjs.PythonLogoIcon,
|
|
150
150
|
props: { size: 16, className: "text-ods-text-secondary" }
|
|
151
151
|
},
|
|
152
|
-
[
|
|
152
|
+
[_chunkKE2TCUOHcjs.ShellTypeValues.NUSHELL]: {
|
|
153
153
|
icon: _chunkKZAAIUP5cjs.NushellIcon,
|
|
154
154
|
props: { size: 16, color: "var(--color-text-secondary)" }
|
|
155
155
|
},
|
|
156
|
-
[
|
|
156
|
+
[_chunkKE2TCUOHcjs.ShellTypeValues.DENO]: {
|
|
157
157
|
icon: _chunkKZAAIUP5cjs.DenoIcon,
|
|
158
158
|
props: { size: 16, color: "var(--color-text-secondary)" }
|
|
159
159
|
},
|
|
160
|
-
[
|
|
160
|
+
[_chunkKE2TCUOHcjs.ShellTypeValues.SHELL]: {
|
|
161
161
|
icon: _chunkKZAAIUP5cjs.ShellIcon,
|
|
162
162
|
props: { size: 16, color: "var(--color-text-secondary)" }
|
|
163
163
|
}
|
|
@@ -168,7 +168,7 @@ var defaultIconConfig = {
|
|
|
168
168
|
};
|
|
169
169
|
var ShellTypeBadge = ({ shellType, className, iconClassName }) => {
|
|
170
170
|
const normalizedType = _optionalChain([shellType, 'optionalAccess', _ => _.toUpperCase, 'call', _2 => _2()]);
|
|
171
|
-
const label =
|
|
171
|
+
const label = _chunkKE2TCUOHcjs.getShellLabel.call(void 0, normalizedType);
|
|
172
172
|
const { icon: IconComponent, props: iconProps } = _nullishCoalesce(shellIconMap[normalizedType], () => ( defaultIconConfig));
|
|
173
173
|
const defaultIconClassName = "className" in iconProps ? iconProps.className : void 0;
|
|
174
174
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkPRPZBXWZcjs.cn.call(void 0, "flex items-center gap-1", className), children: [
|
|
@@ -184,7 +184,7 @@ function formatSupportedPlatforms(platforms) {
|
|
|
184
184
|
if (!platforms || platforms.length === 0) {
|
|
185
185
|
return "All Platforms";
|
|
186
186
|
}
|
|
187
|
-
return platforms.map((platform) =>
|
|
187
|
+
return platforms.map((platform) => _chunkKE2TCUOHcjs.getOSLabel.call(void 0, platform)).join(", ");
|
|
188
188
|
}
|
|
189
189
|
function getInitials(name) {
|
|
190
190
|
const parts = name.trim().split(/\s+/);
|
|
@@ -211,7 +211,7 @@ var ScriptInfoSection = ({
|
|
|
211
211
|
author,
|
|
212
212
|
className
|
|
213
213
|
}) => {
|
|
214
|
-
const shellLabel =
|
|
214
|
+
const shellLabel = _chunkKE2TCUOHcjs.getShellLabel.call(void 0, shellType);
|
|
215
215
|
const platformsLabel = formatSupportedPlatforms(supportedPlatforms);
|
|
216
216
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkPRPZBXWZcjs.cn.call(void 0, "overflow-hidden rounded-[6px] border border-ods-border bg-ods-card", className), children: [
|
|
217
217
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "border-b border-ods-border p-4", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-1", children: [
|
|
@@ -296,7 +296,7 @@ var ScriptArguments = ({
|
|
|
296
296
|
}
|
|
297
297
|
) }),
|
|
298
298
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
299
|
-
|
|
299
|
+
_chunkYHNIPSG6cjs.Button,
|
|
300
300
|
{
|
|
301
301
|
type: "button",
|
|
302
302
|
variant: "outline",
|
|
@@ -310,7 +310,7 @@ var ScriptArguments = ({
|
|
|
310
310
|
] })
|
|
311
311
|
] }, arg.id)),
|
|
312
312
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex justify-start", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
313
|
-
|
|
313
|
+
_chunkYHNIPSG6cjs.Button,
|
|
314
314
|
{
|
|
315
315
|
type: "button",
|
|
316
316
|
variant: "outline",
|
|
@@ -353,7 +353,7 @@ function OnboardingStepCard({
|
|
|
353
353
|
onSkip();
|
|
354
354
|
};
|
|
355
355
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
356
|
-
|
|
356
|
+
_chunkMIY5FYX3cjs.InteractiveCard,
|
|
357
357
|
{
|
|
358
358
|
clickable: false,
|
|
359
359
|
className: _chunkPRPZBXWZcjs.cn.call(void 0,
|
|
@@ -379,9 +379,9 @@ function OnboardingStepCard({
|
|
|
379
379
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[32px] w-[100px] animate-pulse rounded-[6px] bg-ods-border" }),
|
|
380
380
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[32px] w-[120px] animate-pulse rounded-[6px] bg-ods-border" })
|
|
381
381
|
] }) : isCompleted ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
382
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
382
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkMIY5FYX3cjs.StatusBadge, { text: "COMPLETED", variant: "card", colorScheme: "success" }),
|
|
383
383
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
384
|
-
|
|
384
|
+
_chunkYHNIPSG6cjs.Button,
|
|
385
385
|
{
|
|
386
386
|
variant: "outline",
|
|
387
387
|
onClick: handleAction,
|
|
@@ -390,9 +390,9 @@ function OnboardingStepCard({
|
|
|
390
390
|
children: step.completedText
|
|
391
391
|
}
|
|
392
392
|
)
|
|
393
|
-
] }) : isSkipped ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
394
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
395
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
393
|
+
] }) : isSkipped ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkMIY5FYX3cjs.StatusBadge, { text: "SKIPPED", variant: "card", colorScheme: "default" }) }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
394
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYHNIPSG6cjs.Button, { variant: "outline", onClick: handleSkip, children: "Skip Step" }),
|
|
395
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYHNIPSG6cjs.Button, { variant: "accent", onClick: handleAction, disabled: isProcessing, leftIcon: step.actionIcon("black"), children: step.actionText })
|
|
396
396
|
] })
|
|
397
397
|
}
|
|
398
398
|
)
|
|
@@ -501,8 +501,8 @@ function OnboardingWalkthrough({
|
|
|
501
501
|
const isAllComplete = allStepsComplete(steps);
|
|
502
502
|
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkPRPZBXWZcjs.cn.call(void 0, "w-full space-y-4", className), children: [
|
|
503
503
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-start justify-between gap-3 md:flex-row md:items-center md:gap-0", children: [
|
|
504
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className:
|
|
505
|
-
isLoadingCompletion ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[48px] w-full animate-pulse rounded-[6px] bg-ods-border md:w-[160px]" }) : isAllComplete ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
504
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: _chunk75X6BRIDcjs.SECTION_HEADING_CLASS, children: "Get Started" }),
|
|
505
|
+
isLoadingCompletion ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[48px] w-full animate-pulse rounded-[6px] bg-ods-border md:w-[160px]" }) : isAllComplete ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYHNIPSG6cjs.Button, { variant: "accent", onClick: handleDismiss, className: "w-full md:w-auto", children: "Close Onboarding" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYHNIPSG6cjs.Button, { variant: "outline", onClick: handleDismiss, className: "w-full md:w-auto", children: "Skip Onboarding" })
|
|
506
506
|
] }),
|
|
507
507
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _chunkPRPZBXWZcjs.cn.call(void 0, spacing), children: steps.map((step) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
508
508
|
OnboardingStepCard,
|
|
@@ -530,4 +530,4 @@ function OnboardingWalkthrough({
|
|
|
530
530
|
|
|
531
531
|
|
|
532
532
|
exports.SoftwareInfo = SoftwareInfo; exports.SoftwareSourceBadge = SoftwareSourceBadge; exports.CveLink = CveLink; exports.ToolBadge = ToolBadge; exports.ShellTypeBadge = ShellTypeBadge; exports.ScriptInfoSection = ScriptInfoSection; exports.ScriptArguments = ScriptArguments; exports.OnboardingStepCard = OnboardingStepCard; exports.OnboardingWalkthrough = OnboardingWalkthrough;
|
|
533
|
-
//# sourceMappingURL=chunk-
|
|
533
|
+
//# sourceMappingURL=chunk-XG2WNF4L.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-RXJZXMDZ.cjs","../src/components/platform/SoftwareInfo.tsx","../src/components/platform/SoftwareSourceBadge.tsx","../src/components/platform/CveLink.tsx","../src/components/platform/ToolBadge.tsx","../src/components/platform/ShellTypeBadge.tsx","../src/components/platform/ScriptInfoSection.tsx","../src/components/platform/ScriptArguments.tsx","../src/components/shared/onboarding/onboarding-step-card.tsx","../src/components/shared/onboarding/onboarding-walkthrough.tsx"],"names":["jsx","jsxs","cn"],"mappings":"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","file":"/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-RXJZXMDZ.cjs","sourcesContent":[null,"/**\n * SoftwareInfo Component\n *\n * Displays software name with optional vendor information below it.\n * Part of the ODS (OpenFrame Design System) platform components.\n *\n * @example\n * ```tsx\n * <SoftwareInfo name=\"Visual Studio Code\" vendor=\"Microsoft\" />\n * <SoftwareInfo name=\"Chrome\" /> // Without vendor\n * ```\n */\n\nimport type React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport interface SoftwareInfoProps {\n /** Software name (required) */\n name: string;\n /** Software vendor (optional) */\n vendor?: string;\n /** Software version (optional) */\n version?: string;\n /** Additional CSS classes */\n className?: string;\n}\n\nexport const SoftwareInfo: React.FC<SoftwareInfoProps> = ({ name, vendor, version, className }) => {\n return (\n <div className={cn('flex flex-col gap-1', className)}>\n <div className=\"flex items-center gap-2\">\n <div className=\"text-ods-text-primary text-h4\">{name}</div>\n {version && (\n <div className=\"rounded bg-ods-bg-surface px-2 py-1 text-ods-text-secondary text-h6\">{version}</div>\n )}\n </div>\n {vendor && <div className=\"text-ods-text-secondary text-h6\">{vendor}</div>}\n </div>\n );\n};\n\nSoftwareInfo.displayName = 'SoftwareInfo';\n","/**\n * SoftwareSourceBadge Component\n *\n * Displays a badge for software source types from Fleet MDM.\n * Supports all osquery software source types with appropriate styling.\n *\n * Fleet MDM Software Sources:\n * - apps: macOS Applications\n * - chrome_extensions: Chrome Browser Extensions\n * - firefox_addons: Firefox Browser Extensions\n * - safari_extensions: Safari Browser Extensions\n * - ie_extensions: Internet Explorer Extensions\n * - vscode_extensions: VS Code Extensions\n * - atom_packages: Atom Packages\n * - homebrew_packages: Homebrew Packages (macOS)\n * - npm_packages: NPM Packages\n * - python_packages: Python Packages\n * - apt_sources: APT Packages (Debian/Ubuntu)\n * - deb_packages: DEB Packages\n * - rpm_packages: RPM Packages (Red Hat/CentOS)\n * - yum_sources: YUM Packages\n * - portage_packages: Portage Packages (Gentoo)\n * - chocolatey_packages: Chocolatey Packages (Windows)\n * - programs: Windows Programs\n * - pkg_packages: PKG Packages\n *\n * @example\n * ```tsx\n * <SoftwareSourceBadge source=\"apps\" />\n * <SoftwareSourceBadge source=\"chrome_extensions\" />\n * <SoftwareSourceBadge source=\"python_packages\" />\n * ```\n */\n\nimport type React from 'react';\nimport { cn } from '../../utils/common';\nimport { PackageIcon, WindowsIcon, MacOSIcon, LinuxIcon } from '../icons';\n\nexport type SoftwareSource =\n | 'apps'\n | 'chrome_extensions'\n | 'firefox_addons'\n | 'safari_extensions'\n | 'ie_extensions'\n | 'vscode_extensions'\n | 'atom_packages'\n | 'homebrew_packages'\n | 'npm_packages'\n | 'python_packages'\n | 'apt_sources'\n | 'deb_packages'\n | 'rpm_packages'\n | 'yum_sources'\n | 'portage_packages'\n | 'chocolatey_packages'\n | 'programs'\n | 'pkg_packages';\n\nexport interface SoftwareSourceBadgeProps {\n /** Software source type from Fleet MDM */\n source: SoftwareSource;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Maps source types to human-readable labels and icons\n */\nconst sourceConfig: Record<SoftwareSource, { label: string; icon: React.ReactNode }> = {\n apps: { label: 'App', icon: <MacOSIcon className=\"h-4 w-4\" /> },\n chrome_extensions: { label: 'Chrome', icon: <PackageIcon className=\"h-4 w-4\" /> },\n firefox_addons: { label: 'Firefox', icon: <PackageIcon className=\"h-4 w-4\" /> },\n safari_extensions: { label: 'Safari', icon: <PackageIcon className=\"h-4 w-4\" /> },\n ie_extensions: { label: 'IE', icon: <PackageIcon className=\"h-4 w-4\" /> },\n vscode_extensions: { label: 'VS Code', icon: <PackageIcon className=\"h-4 w-4\" /> },\n atom_packages: { label: 'Atom', icon: <PackageIcon className=\"h-4 w-4\" /> },\n homebrew_packages: { label: 'Homebrew', icon: <MacOSIcon className=\"h-4 w-4\" /> },\n npm_packages: { label: 'NPM', icon: <PackageIcon className=\"h-4 w-4\" /> },\n python_packages: { label: 'Python', icon: <PackageIcon className=\"h-4 w-4\" /> },\n apt_sources: { label: 'APT', icon: <LinuxIcon className=\"h-4 w-4\" /> },\n deb_packages: { label: 'DEB', icon: <LinuxIcon className=\"h-4 w-4\" /> },\n rpm_packages: { label: 'RPM', icon: <LinuxIcon className=\"h-4 w-4\" /> },\n yum_sources: { label: 'YUM', icon: <LinuxIcon className=\"h-4 w-4\" /> },\n portage_packages: { label: 'Portage', icon: <LinuxIcon className=\"h-4 w-4\" /> },\n chocolatey_packages: { label: 'Chocolatey', icon: <WindowsIcon className=\"h-4 w-4\" /> },\n programs: { label: 'Windows', icon: <WindowsIcon className=\"h-4 w-4\" /> },\n pkg_packages: { label: 'PKG', icon: <PackageIcon className=\"h-4 w-4\" /> },\n};\n\nexport const SoftwareSourceBadge: React.FC<SoftwareSourceBadgeProps> = ({ source, className }) => {\n const config = sourceConfig[source] || { label: source, icon: <PackageIcon className=\"h-4 w-4\" /> };\n\n return (\n <span className={cn('inline-flex items-center gap-2 text-ods-text-primary', className)}>\n {config.icon}\n {config.label}\n </span>\n );\n};\n\nSoftwareSourceBadge.displayName = 'SoftwareSourceBadge';\n","/**\n * CveLink Component\n *\n * Displays a CVE ID with an external link icon that links to the NIST NVD database.\n * Part of the ODS (OpenFrame Design System) platform components.\n *\n * @example\n * ```tsx\n * <CveLink cveId=\"CVE-2024-1234\" />\n * ```\n */\n\nimport type React from 'react';\nimport { cn } from '../../utils/cn';\nimport { CustomExternalLinkIcon } from '../icons';\n\nexport interface CveLinkProps {\n /** CVE ID (e.g., \"CVE-2024-1234\") */\n cveId: string;\n /** Additional CSS classes */\n className?: string;\n}\n\nexport const CveLink: React.FC<CveLinkProps> = ({ cveId, className }) => {\n const nistUrl = `https://nvd.nist.gov/vuln/detail/${cveId}`;\n\n return (\n <a\n href={nistUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cn(\n 'group inline-flex items-center gap-2 text-ods-text-primary transition-colors text-code hover:text-ods-accent',\n className,\n )}\n >\n <span>{cveId}</span>\n <CustomExternalLinkIcon className=\"h-4 w-4 text-ods-text-secondary transition-colors group-hover:text-ods-accent\" />\n </a>\n );\n};\n\nCveLink.displayName = 'CveLink';\n","/**\n * ToolBadge Component\n *\n * Displays a tool type badge with icon for OpenFrame integrated tools.\n * Used in tables to show tool sources like Fleet MDM, MeshCentral, etc.\n *\n * @example\n * ```tsx\n * <ToolBadge toolType=\"OPENFRAME_RMM\" />\n * <ToolBadge toolType=\"FLEET\" />\n * <ToolBadge toolType=\"MESHCENTRAL\" />\n * ```\n */\n\nimport type React from 'react';\nimport type { ToolType } from '../../types/tool.types';\nimport { cn } from '../../utils/cn';\nimport { getToolLabel } from '../../utils/tool-utils';\nimport { ToolIcon } from '../tool-icon';\n\nexport type { ToolType } from '../../types/tool.types';\n\nexport interface ToolBadgeProps {\n /** Tool type */\n toolType: ToolType;\n /** Additional CSS classes */\n className?: string;\n iconClassName?: string;\n}\n\nexport const ToolBadge: React.FC<ToolBadgeProps> = ({ toolType, className, iconClassName }) => {\n const label = getToolLabel(toolType);\n\n return (\n <div className={cn('flex items-center gap-1 text-ods-text-secondary', className)}>\n <ToolIcon toolType={toolType} className={iconClassName} size={16} />\n <span className=\"text-ods-text-primary text-h4\">{label}</span>\n </div>\n );\n};\n\nToolBadge.displayName = 'ToolBadge';\n","/**\n * ShellTypeBadge Component\n *\n * Displays a badge for shell/script types with appropriate icon and label.\n * Supports all RMM shell types.\n */\n\nimport type React from 'react';\nimport { type ShellType, ShellTypeValues } from '../../types/shell.types';\nimport { cn } from '../../utils/cn';\nimport { getShellLabel } from '../../utils/shell-utils';\nimport { BashIcon, CmdIcon, DenoIcon, NushellIcon, ShellIcon } from '../icons';\nimport { PowershellLogoGreyIcon } from '../icons-v2-generated/brand-logos/powershell-logo-grey-icon';\nimport { PythonLogoIcon } from '../icons-v2-generated/brand-logos/python-logo-icon';\n\n/**\n * Shell icon configuration with typed mapping\n */\ninterface ShellIconConfig {\n icon: React.ComponentType<{ size?: number; color?: string; className?: string }>;\n props: { size: number } & ({ className: string } | { color: string });\n}\n\n/**\n * Typed mapping of shell types to their icon configurations\n * Using Record<ShellType, ...> ensures all shell types are covered\n */\nconst shellIconMap: Record<ShellType, ShellIconConfig> = {\n [ShellTypeValues.POWERSHELL]: {\n icon: PowershellLogoGreyIcon,\n props: { size: 16, className: 'text-ods-text-secondary' },\n },\n [ShellTypeValues.CMD]: {\n icon: CmdIcon,\n props: { size: 16, color: 'var(--color-text-secondary)' },\n },\n [ShellTypeValues.BASH]: {\n icon: BashIcon,\n props: { size: 16, color: 'var(--color-text-secondary)' },\n },\n [ShellTypeValues.PYTHON]: {\n icon: PythonLogoIcon,\n props: { size: 16, className: 'text-ods-text-secondary' },\n },\n [ShellTypeValues.NUSHELL]: {\n icon: NushellIcon,\n props: { size: 16, color: 'var(--color-text-secondary)' },\n },\n [ShellTypeValues.DENO]: {\n icon: DenoIcon,\n props: { size: 16, color: 'var(--color-text-secondary)' },\n },\n [ShellTypeValues.SHELL]: {\n icon: ShellIcon,\n props: { size: 16, color: 'var(--color-text-secondary)' },\n },\n} as const;\n\nconst defaultIconConfig: ShellIconConfig = {\n icon: ShellIcon,\n props: { size: 16, color: 'var(--color-text-secondary)' },\n};\n\nexport interface ShellTypeBadgeProps {\n shellType: ShellType;\n className?: string;\n iconClassName?: string;\n}\n\nexport const ShellTypeBadge: React.FC<ShellTypeBadgeProps> = ({ shellType, className, iconClassName }) => {\n const normalizedType = shellType?.toUpperCase() as ShellType;\n const label = getShellLabel(normalizedType);\n const { icon: IconComponent, props: iconProps } = shellIconMap[normalizedType] ?? defaultIconConfig;\n const defaultIconClassName = 'className' in iconProps ? iconProps.className : undefined;\n\n return (\n <div className={cn('flex items-center gap-1', className)}>\n <IconComponent size={16} className={cn(defaultIconClassName, iconClassName)} />\n <span className=\"text-ods-text-primary text-h4\">{label}</span>\n </div>\n );\n};\n\nShellTypeBadge.displayName = 'ShellTypeBadge';\n","/**\n * ScriptInfoSection Component\n *\n * Displays script information in a card with header (title, description)\n * and detail cells (shell type, supported platforms, category, author).\n * Responsive layout: stacks cells on mobile, shows grid on desktop.\n */\n\nimport type React from 'react';\nimport Image from '../../embed-shims/next-image';\nimport { cn } from '../../utils/cn';\nimport { getOSLabel } from '../../utils/os-utils';\nimport { getShellLabel } from '../../utils/shell-utils';\n\n/**\n * Props for author avatar display\n */\nexport interface ScriptAuthor {\n /** Author name */\n name: string;\n /** Author initials (used when no photo) */\n initials?: string;\n /** URL to author's photo */\n photoUrl?: string;\n}\n\n/**\n * Props for ScriptInfoSection component\n */\nexport interface ScriptInfoSectionProps {\n /** Script title/name */\n headline: string;\n /** Script description */\n subheadline?: string;\n /** Shell type (POWERSHELL, BASH, CMD, etc.) */\n shellType?: string;\n /** Array of supported platform strings (windows, darwin, linux, etc.) */\n supportedPlatforms?: string[];\n /** Script category */\n category: string;\n /** Author information */\n author?: ScriptAuthor;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Formats supported platforms array into a display string\n * @param platforms - Array of platform strings (e.g., ['windows', 'darwin', 'linux'])\n * @returns Formatted string (e.g., 'Windows, macOS, Linux')\n */\nfunction formatSupportedPlatforms(platforms?: string[]): string {\n if (!platforms || platforms.length === 0) {\n return 'All Platforms';\n }\n return platforms.map(platform => getOSLabel(platform)).join(', ');\n}\n\n/**\n * Gets initials from a name\n * @param name - Full name\n * @returns Two-letter initials\n */\nfunction getInitials(name: string): string {\n const parts = name.trim().split(/\\s+/);\n if (parts.length >= 2) {\n return `${parts[0][0]}${parts[1][0]}`.toUpperCase();\n }\n return name.slice(0, 2).toUpperCase();\n}\n\n/**\n * InfoCell - Single info cell with label and value\n */\ninterface InfoCellProps {\n label: string;\n value: string;\n avatar?: ScriptAuthor;\n className?: string;\n}\n\nfunction InfoCell({ label, value, avatar, className }: InfoCellProps) {\n return (\n <div className={cn('flex min-w-0 items-center gap-2', className)}>\n {/* Avatar for author cell */}\n {avatar && (\n <div className=\"relative size-8 shrink-0 overflow-hidden rounded-full border border-ods-border bg-ods-bg\">\n {avatar.photoUrl ? (\n <Image src={avatar.photoUrl} alt={avatar.name} className=\"object-cover\" fill sizes=\"32px\" unoptimized />\n ) : (\n <div className=\"flex size-full items-center justify-center text-ods-text-secondary text-h6\">\n {avatar.initials || getInitials(avatar.name)}\n </div>\n )}\n </div>\n )}\n\n {/* Text content */}\n <div className=\"flex min-w-0 flex-col\">\n <span className=\"truncate text-ods-text-primary text-h4\" title={value}>\n {value}\n </span>\n <span className=\"truncate text-ods-text-secondary text-h6\">{label}</span>\n </div>\n </div>\n );\n}\n\n/**\n * ScriptInfoSection - Displays script information in a structured card\n *\n * @example\n * ```tsx\n * <ScriptInfoSection\n * title=\"System Backup Script\"\n * description=\"Comprehensive Linux system backup script...\"\n * shellType=\"BASH\"\n * supportedPlatforms={['linux']}\n * category=\"System Maintenance\"\n * author={{ name: 'John Doe', photoUrl: '/avatars/john.jpg' }}\n * />\n * ```\n */\nexport const ScriptInfoSection: React.FC<ScriptInfoSectionProps> = ({\n headline,\n subheadline,\n shellType,\n supportedPlatforms,\n category,\n author,\n className,\n}) => {\n const shellLabel = getShellLabel(shellType);\n const platformsLabel = formatSupportedPlatforms(supportedPlatforms);\n\n return (\n <div className={cn('overflow-hidden rounded-[6px] border border-ods-border bg-ods-card', className)}>\n {/* Header row with title and description */}\n <div className=\"border-b border-ods-border p-4\">\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"text-ods-text-primary text-h4\">{headline}</h3>\n {subheadline && <p className=\"break-words text-ods-text-secondary text-h6\">{subheadline}</p>}\n </div>\n </div>\n\n {/* Details section with info cells\n - Mobile/Tablet (<lg): 2x2 grid with divider between rows\n - Desktop (lg+): 4 columns in single row\n */}\n {/* First row: Shell Type, Supported Platforms */}\n <div className=\"grid grid-cols-2 gap-4 border-b border-ods-border px-4 py-4 lg:grid-cols-4 lg:border-b-0\">\n <InfoCell label=\"Shell Type\" value={shellLabel} />\n <InfoCell label=\"Supported Platforms\" value={platformsLabel} />\n {/* Desktop only: Category and Author in same row */}\n <InfoCell label=\"Category\" value={category} className=\"hidden lg:flex\" />\n {author && <InfoCell label=\"Added by\" value={author.name} avatar={author} className=\"hidden lg:flex\" />}\n </div>\n {/* Second row (mobile/tablet only): Category, Author */}\n <div className=\"grid grid-cols-2 gap-4 px-4 py-4 lg:hidden\">\n <InfoCell label=\"Category\" value={category} />\n {author && <InfoCell label=\"Added by\" value={author.name} avatar={author} />}\n </div>\n </div>\n );\n};\n\nScriptInfoSection.displayName = 'ScriptInfoSection';\n","/**\n * ScriptArguments Component\n *\n * Displays and manages script arguments as key-value pairs.\n * Each argument has a name (key) and value input field with delete button.\n * Includes an \"Add Script Argument\" button to add new entries.\n */\n\nimport { Trash2 } from 'lucide-react';\nimport type React from 'react';\nimport { cn } from '../../utils/cn';\nimport { PlusCircleIcon } from '../icons-v2-generated';\nimport { Button } from '../ui/button';\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\n\n/**\n * Single script argument with key and value\n */\nexport interface ScriptArgument {\n /** Unique identifier for the argument */\n id: string;\n /** Argument name/key */\n key: string;\n /** Argument value (empty string for flag-type arguments) */\n value: string;\n}\n\n/**\n * Props for ScriptArguments component\n */\nexport interface ScriptArgumentsProps {\n /** Array of script arguments */\n arguments: ScriptArgument[];\n /** Callback when arguments change */\n onArgumentsChange?: (args: ScriptArgument[]) => void;\n /** Placeholder for key input */\n keyPlaceholder?: string;\n /** Placeholder for value input */\n valuePlaceholder?: string;\n /** Label for the add button */\n addButtonLabel?: string;\n /** Whether the component is disabled */\n disabled?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Label for the title input */\n titleLabel: string;\n}\n\n/**\n * ScriptArguments - Displays and manages script arguments\n *\n * @example\n * ```tsx\n * <ScriptArguments\n * arguments={[\n * { id: '1', key: 'port', value: '3000' },\n * { id: '2', key: 'verbose', value: '' },\n * ]}\n * onArgumentsChange={(args) => setArguments(args)}\n * />\n * ```\n */\nexport const ScriptArguments: React.FC<ScriptArgumentsProps> = ({\n arguments: args,\n onArgumentsChange,\n keyPlaceholder = 'Enter Key',\n valuePlaceholder = 'Enter Value (empty=flag)',\n addButtonLabel = 'Add Script Argument',\n disabled = false,\n className,\n titleLabel,\n}) => {\n const handleKeyChange = (id: string, newKey: string) => {\n if (!onArgumentsChange) return;\n const updated = args.map(arg => (arg.id === id ? { ...arg, key: newKey } : arg));\n onArgumentsChange(updated);\n };\n\n const handleValueChange = (id: string, newValue: string) => {\n if (!onArgumentsChange) return;\n const updated = args.map(arg => (arg.id === id ? { ...arg, value: newValue } : arg));\n onArgumentsChange(updated);\n };\n\n const handleDelete = (id: string) => {\n if (!onArgumentsChange) return;\n const updated = args.filter(arg => arg.id !== id);\n onArgumentsChange(updated);\n };\n\n const handleAdd = () => {\n if (!onArgumentsChange) return;\n const newArg: ScriptArgument = {\n id: crypto.randomUUID(),\n key: '',\n value: '',\n };\n onArgumentsChange([...args, newArg]);\n };\n\n const isFirstRow = (index: number) => index === 0;\n\n return (\n <div className={cn('flex flex-col gap-2', className)}>\n {args.map((arg, index) => (\n <div key={arg.id} className=\"flex w-full items-end gap-2\">\n {/* Key input - with label only on first row */}\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n {isFirstRow(index) && <Label spacing=\"tight\">{titleLabel}</Label>}\n <Input\n value={arg.key}\n onChange={e => handleKeyChange(arg.id, e.target.value)}\n placeholder={keyPlaceholder}\n disabled={disabled}\n />\n </div>\n\n {/* Value input with delete button */}\n {/* Value input with delete button */}\n <div className=\"flex min-w-0 flex-1 items-center gap-2\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <Input\n value={arg.value}\n onChange={e => handleValueChange(arg.id, e.target.value)}\n placeholder={valuePlaceholder}\n disabled={disabled}\n className={cn(!arg.value && 'placeholder:text-ods-text-muted')}\n />\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon\"\n onClick={() => handleDelete(arg.id)}\n disabled={disabled}\n aria-label=\"Delete argument\"\n leftIcon={<Trash2 className=\"size-4 md:size-6\" color=\"var(--color-error)\" />}\n />\n </div>\n </div>\n ))}\n\n {/* Add button - aligned left */}\n <div className=\"flex justify-start\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"small\"\n onClick={handleAdd}\n disabled={disabled}\n className=\"self-start\"\n leftIcon={<PlusCircleIcon className=\"text-ods-text-secondary\" />}\n >\n {addButtonLabel}\n </Button>\n </div>\n </div>\n );\n};\n\nScriptArguments.displayName = 'ScriptArguments';\n","'use client';\n\nimport React from 'react';\nimport { cn } from '../../../utils/cn';\nimport { Button } from '../../ui/button';\nimport { InteractiveCard } from '../../ui/interactive-card';\nimport { StatusBadge } from '../../ui/status-badge';\n\nexport interface OnboardingStepCardProps {\n step: {\n id: string;\n title: string;\n description: string;\n actionIcon: (color?: string) => React.ReactNode;\n actionText: string;\n completedText: string;\n onAction: () => void | Promise<void>;\n onSkip?: () => void;\n };\n isCompleted: boolean;\n isSkipped: boolean;\n isCheckingCompletion: boolean;\n onAction: () => void | Promise<void>;\n onSkip: () => void;\n className?: string;\n}\n\nexport function OnboardingStepCard({\n step,\n isCompleted,\n isSkipped,\n isCheckingCompletion,\n onAction,\n onSkip,\n className,\n}: OnboardingStepCardProps) {\n const [isProcessing, setIsProcessing] = React.useState(false);\n\n const handleAction = async (e: React.MouseEvent) => {\n e.stopPropagation();\n setIsProcessing(true);\n try {\n await onAction();\n } finally {\n setIsProcessing(false);\n }\n };\n\n const handleSkip = (e: React.MouseEvent) => {\n e.stopPropagation();\n onSkip();\n };\n\n return (\n <InteractiveCard\n clickable={false}\n className={cn(\n 'rounded-[6px] border border-ods-border bg-ods-card',\n 'flex flex-col md:flex-row',\n 'min-h-[80px] md:h-[80px]',\n 'items-start md:items-center',\n 'gap-3 md:gap-4',\n 'px-4 py-4 md:py-0',\n className,\n )}\n >\n {/* Left column - content */}\n <div className=\"flex w-full min-w-0 flex-1 flex-col justify-center gap-1 md:w-auto\">\n <h3 className=\"truncate text-ods-text-primary text-h4\" title={step.title}>\n {step.title}\n </h3>\n <p className=\"h-[20px] truncate text-ods-text-secondary text-h6\" title={step.description}>\n {step.description}\n </p>\n </div>\n\n {/* Right column - action buttons, completed badge, or skipped badge */}\n <div\n className=\"flex w-full shrink-0 items-center justify-start gap-2 md:w-auto md:justify-end\"\n onClick={e => e.stopPropagation()}\n >\n {isCheckingCompletion ? (\n <>\n <div className=\"h-[32px] w-[100px] animate-pulse rounded-[6px] bg-ods-border\" />\n <div className=\"h-[32px] w-[120px] animate-pulse rounded-[6px] bg-ods-border\" />\n </>\n ) : isCompleted ? (\n <>\n <StatusBadge text=\"COMPLETED\" variant=\"card\" colorScheme=\"success\" />\n <Button\n variant=\"outline\"\n onClick={handleAction}\n disabled={isProcessing}\n leftIcon={step.actionIcon('white')}\n >\n {step.completedText}\n </Button>\n </>\n ) : isSkipped ? (\n <>\n <StatusBadge text=\"SKIPPED\" variant=\"card\" colorScheme=\"default\" />\n </>\n ) : (\n <>\n <Button variant=\"outline\" onClick={handleSkip}>\n Skip Step\n </Button>\n <Button variant=\"accent\" onClick={handleAction} disabled={isProcessing} leftIcon={step.actionIcon('black')}>\n {step.actionText}\n </Button>\n </>\n )}\n </div>\n </InteractiveCard>\n );\n}\n","'use client';\n\nimport React, { useRef, useCallback } from 'react';\nimport { useOnboardingState, type OnboardingStepConfig } from '../../../hooks/ui/use-onboarding-state';\nimport { cn } from '../../../utils/cn';\nimport { SECTION_HEADING_CLASS } from '../../layout/page-heading';\nimport { Button } from '../../ui/button';\nimport { OnboardingStepCard } from './onboarding-step-card';\n\nexport interface OnboardingWalkthroughProps {\n steps: OnboardingStepConfig[];\n onDismiss?: () => void;\n storageKey?: string;\n className?: string;\n spacing?: string;\n /**\n * Completion status from hook-based checks (e.g., useOnboardingCompletion)\n * Object mapping step IDs to boolean completion status\n */\n completionStatus?: Record<string, boolean>;\n /**\n * Whether completion checks are still loading\n */\n isLoadingCompletion?: boolean;\n}\n\nexport function OnboardingWalkthrough({\n steps,\n onDismiss,\n storageKey = 'openframe-onboarding-state',\n className,\n spacing = 'space-y-4',\n completionStatus,\n isLoadingCompletion = false,\n}: OnboardingWalkthroughProps) {\n const {\n state,\n markComplete,\n markSkipped,\n dismissOnboarding,\n isStepComplete,\n isStepSkipped,\n allStepsComplete,\n markMultipleComplete,\n } = useOnboardingState(storageKey);\n\n // Refs to prevent race conditions - ALL refs must be declared before any conditional returns\n const hasAutoMarkedRef = useRef(false);\n const autoMarkingInProgressRef = useRef(false);\n const lastCompletionStatusRef = useRef<string | null>(null);\n // Ref to track in-flight action handlers - moved here to be before conditional return\n const actionInProgressRef = useRef<Set<string>>(new Set());\n\n // Sync completion status from hooks to localStorage\n // Uses refs to prevent duplicate calls and race conditions\n React.useEffect(() => {\n // Skip if still loading\n if (isLoadingCompletion) {\n hasAutoMarkedRef.current = false; // Reset when loading starts\n return;\n }\n\n // Skip if no completion status\n if (!completionStatus) return;\n\n // Create a stable key from completion status to detect actual changes\n const statusKey = JSON.stringify(completionStatus);\n\n // Skip if we've already processed this exact status\n if (lastCompletionStatusRef.current === statusKey) return;\n\n // Skip if auto-marking is currently in progress\n if (autoMarkingInProgressRef.current) return;\n\n // Find steps that need to be marked complete\n // Read directly from state to avoid stale closure issues\n const completedStepIds = Object.entries(completionStatus)\n .filter(([stepId, isComplete]) => {\n if (!isComplete) return false;\n // Check against current state, not the callback\n return !state.completedSteps.includes(stepId);\n })\n .map(([stepId]) => stepId);\n\n if (completedStepIds.length > 0) {\n // Mark as in progress to prevent concurrent calls\n autoMarkingInProgressRef.current = true;\n\n console.log('📊 Auto-marking steps as complete from hook data:', completedStepIds);\n markMultipleComplete(completedStepIds);\n\n // Update the last processed status key\n lastCompletionStatusRef.current = statusKey;\n\n // Reset the in-progress flag after a short delay\n // This prevents rapid successive calls while allowing future updates\n setTimeout(() => {\n autoMarkingInProgressRef.current = false;\n }, 100);\n } else {\n // Even if no steps to mark, update the status key to prevent re-processing\n lastCompletionStatusRef.current = statusKey;\n }\n }, [completionStatus, isLoadingCompletion, state.completedSteps, markMultipleComplete]);\n\n // useCallback must be called unconditionally (before any early returns)\n const handleStepAction = useCallback(\n async (step: OnboardingStepConfig) => {\n // Prevent duplicate action handling for the same step\n if (actionInProgressRef.current.has(step.id)) {\n console.log(`⏳ Action already in progress for \"${step.id}\", skipping`);\n return;\n }\n\n // Mark as in progress\n actionInProgressRef.current.add(step.id);\n\n try {\n await step.onAction();\n\n // Skip if already completed (could have been auto-marked while action was running)\n if (state.completedSteps.includes(step.id)) {\n console.log(`✓ Step \"${step.id}\" already completed, skipping mark`);\n return;\n }\n\n // Auto-mark Knowledge Base as complete (no verification needed)\n if (step.id === 'knowledge-base') {\n console.log(`🎯 Auto-completing Knowledge Base`);\n markComplete(step.id);\n return;\n }\n\n // For other steps, re-check completion after action\n if (step.checkComplete) {\n try {\n const isComplete = await step.checkComplete();\n console.log(`🔍 Post-action check for \"${step.id}\": isComplete=${isComplete}`);\n\n // Double-check it wasn't completed while we were checking\n if (isComplete && !state.completedSteps.includes(step.id)) {\n markComplete(step.id);\n }\n } catch (error) {\n console.error(`Error checking completion for \"${step.id}\":`, error);\n }\n }\n } finally {\n // Remove from in-progress set\n actionInProgressRef.current.delete(step.id);\n }\n },\n [state.completedSteps, markComplete],\n );\n\n const handleStepSkip = (step: OnboardingStepConfig) => {\n step.onSkip?.();\n markSkipped(step.id);\n };\n\n const handleDismiss = () => {\n dismissOnboarding();\n onDismiss?.();\n };\n\n // ALL hooks have been called above - now safe to do conditional returns\n // Don't render if dismissed\n if (state.dismissed) {\n return null;\n }\n\n const isAllComplete = allStepsComplete(steps);\n\n return (\n <div className={cn('w-full space-y-4', className)}>\n {/* Header - responsive: stacks on mobile */}\n <div className=\"flex flex-col items-start justify-between gap-3 md:flex-row md:items-center md:gap-0\">\n <h2 className={SECTION_HEADING_CLASS}>Get Started</h2>\n\n {isLoadingCompletion ? (\n <div className=\"h-[48px] w-full animate-pulse rounded-[6px] bg-ods-border md:w-[160px]\" />\n ) : isAllComplete ? (\n <Button variant=\"accent\" onClick={handleDismiss} className=\"w-full md:w-auto\">\n Close Onboarding\n </Button>\n ) : (\n <Button variant=\"outline\" onClick={handleDismiss} className=\"w-full md:w-auto\">\n Skip Onboarding\n </Button>\n )}\n </div>\n\n {/* Step cards - no wrapper, direct rendering */}\n <div className={cn(spacing)}>\n {steps.map(step => (\n <OnboardingStepCard\n key={step.id}\n step={step}\n isCompleted={isStepComplete(step.id)}\n isSkipped={isStepSkipped(step.id)}\n isCheckingCompletion={isLoadingCompletion}\n onAction={() => handleStepAction(step)}\n onSkip={() => handleStepSkip(step)}\n />\n ))}\n </div>\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-XG2WNF4L.cjs","../src/components/platform/SoftwareInfo.tsx","../src/components/platform/SoftwareSourceBadge.tsx","../src/components/platform/CveLink.tsx","../src/components/platform/ToolBadge.tsx","../src/components/platform/ShellTypeBadge.tsx","../src/components/platform/ScriptInfoSection.tsx","../src/components/platform/ScriptArguments.tsx","../src/components/shared/onboarding/onboarding-step-card.tsx","../src/components/shared/onboarding/onboarding-walkthrough.tsx"],"names":["jsx","jsxs","cn"],"mappings":"AAAA,6xBAAY;AACZ;AACE;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACE;AACF,wDAA6B;AAC7B;AACA;ACxBM,+CAAA;AAHC,IAAM,aAAA,EAA4C,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAS,UAAU,CAAA,EAAA,GAAM;AACjG,EAAA,uBACE,8BAAA,KAAC,EAAA,EAAI,SAAA,EAAW,kCAAA,qBAAG,EAAuB,SAAS,CAAA,EACjD,QAAA,EAAA;AAAA,oBAAA,8BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,yBAAA,EACb,QAAA,EAAA;AAAA,sBAAA,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,+BAAA,EAAiC,QAAA,EAAA,KAAA,CAAK,CAAA;AAAA,MACpD,QAAA,mBACC,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,qEAAA,EAAuE,QAAA,EAAA,QAAA,CAAQ;AAAA,IAAA,EAAA,CAElG,CAAA;AAAA,IACC,OAAA,mBAAU,6BAAA,KAAC,EAAA,EAAI,SAAA,EAAU,iCAAA,EAAmC,QAAA,EAAA,OAAA,CAAO;AAAA,EAAA,EAAA,CACtE,CAAA;AAEJ,CAAA;AAEA,YAAA,CAAa,YAAA,EAAc,cAAA;ADyB3B;AACA;AEE8B;AAD9B,IAAM,aAAA,EAAiF;AAAA,EACrF,IAAA,EAAM,EAAE,KAAA,EAAO,KAAA,EAAO,IAAA,kBAAMA,6BAAAA,2BAAC,EAAA,EAAU,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EAC9D,iBAAA,EAAmB,EAAE,KAAA,EAAO,QAAA,EAAU,IAAA,kBAAMA,6BAAAA,6BAAC,EAAA,EAAY,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EAChF,cAAA,EAAgB,EAAE,KAAA,EAAO,SAAA,EAAW,IAAA,kBAAMA,6BAAAA,6BAAC,EAAA,EAAY,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EAC9E,iBAAA,EAAmB,EAAE,KAAA,EAAO,QAAA,EAAU,IAAA,kBAAMA,6BAAAA,6BAAC,EAAA,EAAY,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EAChF,aAAA,EAAe,EAAE,KAAA,EAAO,IAAA,EAAM,IAAA,kBAAMA,6BAAAA,6BAAC,EAAA,EAAY,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EACxE,iBAAA,EAAmB,EAAE,KAAA,EAAO,SAAA,EAAW,IAAA,kBAAMA,6BAAAA,6BAAC,EAAA,EAAY,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EACjF,aAAA,EAAe,EAAE,KAAA,EAAO,MAAA,EAAQ,IAAA,kBAAMA,6BAAAA,6BAAC,EAAA,EAAY,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EAC1E,iBAAA,EAAmB,EAAE,KAAA,EAAO,UAAA,EAAY,IAAA,kBAAMA,6BAAAA,2BAAC,EAAA,EAAU,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EAChF,YAAA,EAAc,EAAE,KAAA,EAAO,KAAA,EAAO,IAAA,kBAAMA,6BAAAA,6BAAC,EAAA,EAAY,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EACxE,eAAA,EAAiB,EAAE,KAAA,EAAO,QAAA,EAAU,IAAA,kBAAMA,6BAAAA,6BAAC,EAAA,EAAY,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EAC9E,WAAA,EAAa,EAAE,KAAA,EAAO,KAAA,EAAO,IAAA,kBAAMA,6BAAAA,2BAAC,EAAA,EAAU,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EACrE,YAAA,EAAc,EAAE,KAAA,EAAO,KAAA,EAAO,IAAA,kBAAMA,6BAAAA,2BAAC,EAAA,EAAU,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EACtE,YAAA,EAAc,EAAE,KAAA,EAAO,KAAA,EAAO,IAAA,kBAAMA,6BAAAA,2BAAC,EAAA,EAAU,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EACtE,WAAA,EAAa,EAAE,KAAA,EAAO,KAAA,EAAO,IAAA,kBAAMA,6BAAAA,2BAAC,EAAA,EAAU,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EACrE,gBAAA,EAAkB,EAAE,KAAA,EAAO,SAAA,EAAW,IAAA,kBAAMA,6BAAAA,2BAAC,EAAA,EAAU,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EAC9E,mBAAA,EAAqB,EAAE,KAAA,EAAO,YAAA,EAAc,IAAA,kBAAMA,6BAAAA,6BAAC,EAAA,EAAY,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EACtF,QAAA,EAAU,EAAE,KAAA,EAAO,SAAA,EAAW,IAAA,kBAAMA,6BAAAA,6BAAC,EAAA,EAAY,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAAA,EACxE,YAAA,EAAc,EAAE,KAAA,EAAO,KAAA,EAAO,IAAA,kBAAMA,6BAAAA,6BAAC,EAAA,EAAY,SAAA,EAAU,UAAA,CAAU,EAAG;AAC1E,CAAA;AAEO,IAAM,oBAAA,EAA0D,CAAC,EAAE,MAAA,EAAQ,UAAU,CAAA,EAAA,GAAM;AAChG,EAAA,MAAM,OAAA,EAAS,YAAA,CAAa,MAAM,EAAA,GAAK,EAAE,KAAA,EAAO,MAAA,EAAQ,IAAA,kBAAMA,6BAAAA,6BAAC,EAAA,EAAY,SAAA,EAAU,UAAA,CAAU,EAAG,CAAA;AAElG,EAAA,uBACEC,8BAAAA,MAAC,EAAA,EAAK,SAAA,EAAWC,kCAAAA,sDAAG,EAAwD,SAAS,CAAA,EAClF,QAAA,EAAA;AAAA,IAAA,MAAA,CAAO,IAAA;AAAA,IACP,MAAA,CAAO;AAAA,EAAA,EAAA,CACV,CAAA;AAEJ,CAAA;AAEA,mBAAA,CAAoB,YAAA,EAAc,qBAAA;AFHlC;AACA;AGvEI;AAJG,IAAM,QAAA,EAAkC,CAAC,EAAE,KAAA,EAAO,UAAU,CAAA,EAAA,GAAM;AACvE,EAAA,MAAM,QAAA,EAAU,CAAA,iCAAA,EAAoC,KAAK,CAAA,CAAA;AAGvDD,EAAAA;AAAC,IAAA;AAAA,IAAA;AACO,MAAA;AACC,MAAA;AACH,MAAA;AACO,MAAA;AACT,QAAA;AACA,QAAA;AACF,MAAA;AAEA,MAAA;AAAa,wBAAA;AACW,wBAAA;AAA0F,MAAA;AAAA,IAAA;AACpH,EAAA;AAEJ;AAEsB;AH8EsC;AACA;AIvFxD;AAJ2F;AAC1D,EAAA;AAGd,EAAA;AACwB,oBAAA;AACzB,oBAAA;AAClB,EAAA;AAEJ;AAEwB;AJ0FoC;AACA;AKxDxD;AAjDqD;AACzB,EAAA;AACtB,IAAA;AACkD,IAAA;AAC1D,EAAA;AACuB,EAAA;AACf,IAAA;AACkD,IAAA;AAC1D,EAAA;AACwB,EAAA;AAChB,IAAA;AACkD,IAAA;AAC1D,EAAA;AAC0B,EAAA;AAClB,IAAA;AACkD,IAAA;AAC1D,EAAA;AAC2B,EAAA;AACnB,IAAA;AACkD,IAAA;AAC1D,EAAA;AACwB,EAAA;AAChB,IAAA;AACkD,IAAA;AAC1D,EAAA;AACyB,EAAA;AACjB,IAAA;AACkD,IAAA;AAC1D,EAAA;AACF;AAE2C;AACnC,EAAA;AACkD,EAAA;AAC1D;AAQoG;AACpD,EAAA;AACJ,EAAA;AACQ,EAAA;AACM,EAAA;AAGnC,EAAA;AACQ,oBAAA;AACT,oBAAA;AAClB,EAAA;AAEJ;AAE6B;ALgG+B;AACA;AM5FhD;AArCoD;AACpB,EAAA;AACjC,IAAA;AACT,EAAA;AACuD,EAAA;AACzD;AAO2C;AACJ,EAAA;AACd,EAAA;AAC6B,IAAA;AACpD,EAAA;AACoC,EAAA;AACtC;AAYsE;AAE/C,EAAA;AAGA,IAAA;AAYF,oBAAA;AACG,sBAAA;AAGA,sBAAA;AAClB,IAAA;AACF,EAAA;AAEJ;AAiBoE;AAClE,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACI;AACsC,EAAA;AACM,EAAA;AAG3B,EAAA;AAEF,oBAAA;AAEG,sBAAA;AACe,MAAA;AAEjC,IAAA;AAOe,oBAAA;AACgB,sBAAA;AACb,sBAAA;AAEW,sBAAA;AACA,MAAA;AAC7B,IAAA;AAEe,oBAAA;AACc,sBAAA;AACA,MAAA;AAC7B,IAAA;AACF,EAAA;AAEJ;AAEgC;ANmE4B;AACA;AOlOrC;AAqGb;AA7CsD;AACnD,EAAA;AACX,EAAA;AACiB,EAAA;AACE,EAAA;AACF,EAAA;AACN,EAAA;AACX,EAAA;AACA,EAAA;AACI;AACoD,EAAA;AAC9B,IAAA;AAC8B,IAAA;AAC7B,IAAA;AAC3B,EAAA;AAE4D,EAAA;AAClC,IAAA;AAC8B,IAAA;AAC7B,IAAA;AAC3B,EAAA;AAEqC,EAAA;AACX,IAAA;AACwB,IAAA;AACvB,IAAA;AAC3B,EAAA;AAEwB,EAAA;AACE,IAAA;AACO,IAAA;AACP,MAAA;AACjB,MAAA;AACE,MAAA;AACT,IAAA;AACmC,IAAA;AACrC,EAAA;AAEgD,EAAA;AAG3B,EAAA;AAEG,IAAA;AAED,sBAAA;AACgB,QAAA;AAC7BD,wBAAAA;AAAC,UAAA;AAAA,UAAA;AACY,YAAA;AAC8B,YAAA;AAC5B,YAAA;AACb,YAAA;AAAA,UAAA;AACF,QAAA;AACF,MAAA;AAIe,sBAAA;AACE,wBAAA;AACZ,UAAA;AAAA,UAAA;AACY,YAAA;AACgC,YAAA;AAC9B,YAAA;AACb,YAAA;AAC4B,YAAA;AAAiC,UAAA;AAEjE,QAAA;AACAA,wBAAAA;AAAC,UAAA;AAAA,UAAA;AACM,YAAA;AACG,YAAA;AACH,YAAA;AAC6B,YAAA;AAClC,YAAA;AACW,YAAA;AACO,YAAA;AAAwD,UAAA;AAC5E,QAAA;AACF,MAAA;AAEH,IAAA;AAGc,oBAAA;AACZ,MAAA;AAAA,MAAA;AACM,QAAA;AACG,QAAA;AACH,QAAA;AACI,QAAA;AACT,QAAA;AACU,QAAA;AACgB,QAAA;AAEzB,QAAA;AAAA,MAAA;AAEL,IAAA;AACF,EAAA;AAEJ;AAE8B;APqK8B;AACA;AQtU1C;AAiEZ;AAxC6B;AACjC,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AAC0B;AAC6B,EAAA;AAEH,EAAA;AAChC,IAAA;AACE,IAAA;AAChB,IAAA;AACa,MAAA;AACf,IAAA;AACqB,MAAA;AACvB,IAAA;AACF,EAAA;AAE4C,EAAA;AACxB,IAAA;AACX,IAAA;AACT,EAAA;AAGEC,EAAAA;AAAC,IAAA;AAAA,IAAA;AACY,MAAA;AACA,MAAA;AACT,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AAGA,MAAA;AAAe,wBAAA;AACC,0BAAA;AAGD,0BAAA;AAGf,QAAA;AAGAD,wBAAAA;AAAC,UAAA;AAAA,UAAA;AACW,YAAA;AACsB,YAAA;AAG9B,YAAA;AACiB,8BAAA;AACA,8BAAA;AAGjB,YAAA;AACoB,8BAAA;AAClBA,8BAAAA;AAAC,gBAAA;AAAA,gBAAA;AACS,kBAAA;AACC,kBAAA;AACC,kBAAA;AACuB,kBAAA;AAE3B,kBAAA;AAAA,gBAAA;AACR,cAAA;AAGF,YAAA;AAKkB,8BAAA;AAGA,8BAAA;AAGlB,YAAA;AAAA,UAAA;AAEJ,QAAA;AAAA,MAAA;AAAA,IAAA;AACF,EAAA;AAEJ;AR+R4D;AACA;ASjZjB;AA8KrC;AAtJgC;AACpC,EAAA;AACA,EAAA;AACa,EAAA;AACb,EAAA;AACU,EAAA;AACV,EAAA;AACsB,EAAA;AACO;AACvB,EAAA;AACJ,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AAC+B,EAAA;AAGI,EAAA;AACQ,EAAA;AACa,EAAA;AAEN,EAAA;AAI9B,EAAA;AAEK,IAAA;AACI,MAAA;AAC3B,MAAA;AACF,IAAA;AAGuB,IAAA;AAG0B,IAAA;AAGE,IAAA;AAGb,IAAA;AAIkB,IAAA;AAE5B,MAAA;AAEoB,MAAA;AAErB,IAAA;AAEM,IAAA;AAEI,MAAA;AAEvB,MAAA;AACyB,MAAA;AAGH,MAAA;AAIjB,MAAA;AACoB,QAAA;AAC/B,MAAA;AACD,IAAA;AAE6B,MAAA;AACpC,IAAA;AAC+C,EAAA;AAGxB,EAAA;AACe,IAAA;AAEU,MAAA;AAChC,QAAA;AACZ,QAAA;AACF,MAAA;AAGuC,MAAA;AAEnC,MAAA;AACkB,QAAA;AAGwB,QAAA;AACZ,UAAA;AAC9B,UAAA;AACF,QAAA;AAGkC,QAAA;AACpB,UAAA;AACQ,UAAA;AACpB,UAAA;AACF,QAAA;AAGwB,QAAA;AAClB,UAAA;AAC0C,YAAA;AACH,YAAA;AAGD,YAAA;AAClB,cAAA;AACtB,YAAA;AACc,UAAA;AACkC,YAAA;AAClD,UAAA;AACF,QAAA;AACA,MAAA;AAE0C,QAAA;AAC5C,MAAA;AACF,IAAA;AACmC,IAAA;AACrC,EAAA;AAEuD,EAAA;AACvC,oBAAA;AACK,IAAA;AACrB,EAAA;AAE4B,EAAA;AACR,IAAA;AACN,oBAAA;AACd,EAAA;AAIqB,EAAA;AACZ,IAAA;AACT,EAAA;AAE4C,EAAA;AAGvB,EAAA;AAEF,oBAAA;AACE,sBAAA;AAGR,MAAA;AAUT,IAAA;AAIG,oBAAA;AACE,MAAA;AAAA,MAAA;AAEC,QAAA;AACmC,QAAA;AACH,QAAA;AACV,QAAA;AACe,QAAA;AACJ,QAAA;AAAA,MAAA;AANvB,MAAA;AAShB,IAAA;AACF,EAAA;AAEJ;ATwT4D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-XG2WNF4L.cjs","sourcesContent":[null,"/**\n * SoftwareInfo Component\n *\n * Displays software name with optional vendor information below it.\n * Part of the ODS (OpenFrame Design System) platform components.\n *\n * @example\n * ```tsx\n * <SoftwareInfo name=\"Visual Studio Code\" vendor=\"Microsoft\" />\n * <SoftwareInfo name=\"Chrome\" /> // Without vendor\n * ```\n */\n\nimport type React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport interface SoftwareInfoProps {\n /** Software name (required) */\n name: string;\n /** Software vendor (optional) */\n vendor?: string;\n /** Software version (optional) */\n version?: string;\n /** Additional CSS classes */\n className?: string;\n}\n\nexport const SoftwareInfo: React.FC<SoftwareInfoProps> = ({ name, vendor, version, className }) => {\n return (\n <div className={cn('flex flex-col gap-1', className)}>\n <div className=\"flex items-center gap-2\">\n <div className=\"text-ods-text-primary text-h4\">{name}</div>\n {version && (\n <div className=\"rounded bg-ods-bg-surface px-2 py-1 text-ods-text-secondary text-h6\">{version}</div>\n )}\n </div>\n {vendor && <div className=\"text-ods-text-secondary text-h6\">{vendor}</div>}\n </div>\n );\n};\n\nSoftwareInfo.displayName = 'SoftwareInfo';\n","/**\n * SoftwareSourceBadge Component\n *\n * Displays a badge for software source types from Fleet MDM.\n * Supports all osquery software source types with appropriate styling.\n *\n * Fleet MDM Software Sources:\n * - apps: macOS Applications\n * - chrome_extensions: Chrome Browser Extensions\n * - firefox_addons: Firefox Browser Extensions\n * - safari_extensions: Safari Browser Extensions\n * - ie_extensions: Internet Explorer Extensions\n * - vscode_extensions: VS Code Extensions\n * - atom_packages: Atom Packages\n * - homebrew_packages: Homebrew Packages (macOS)\n * - npm_packages: NPM Packages\n * - python_packages: Python Packages\n * - apt_sources: APT Packages (Debian/Ubuntu)\n * - deb_packages: DEB Packages\n * - rpm_packages: RPM Packages (Red Hat/CentOS)\n * - yum_sources: YUM Packages\n * - portage_packages: Portage Packages (Gentoo)\n * - chocolatey_packages: Chocolatey Packages (Windows)\n * - programs: Windows Programs\n * - pkg_packages: PKG Packages\n *\n * @example\n * ```tsx\n * <SoftwareSourceBadge source=\"apps\" />\n * <SoftwareSourceBadge source=\"chrome_extensions\" />\n * <SoftwareSourceBadge source=\"python_packages\" />\n * ```\n */\n\nimport type React from 'react';\nimport { cn } from '../../utils/common';\nimport { PackageIcon, WindowsIcon, MacOSIcon, LinuxIcon } from '../icons';\n\nexport type SoftwareSource =\n | 'apps'\n | 'chrome_extensions'\n | 'firefox_addons'\n | 'safari_extensions'\n | 'ie_extensions'\n | 'vscode_extensions'\n | 'atom_packages'\n | 'homebrew_packages'\n | 'npm_packages'\n | 'python_packages'\n | 'apt_sources'\n | 'deb_packages'\n | 'rpm_packages'\n | 'yum_sources'\n | 'portage_packages'\n | 'chocolatey_packages'\n | 'programs'\n | 'pkg_packages';\n\nexport interface SoftwareSourceBadgeProps {\n /** Software source type from Fleet MDM */\n source: SoftwareSource;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Maps source types to human-readable labels and icons\n */\nconst sourceConfig: Record<SoftwareSource, { label: string; icon: React.ReactNode }> = {\n apps: { label: 'App', icon: <MacOSIcon className=\"h-4 w-4\" /> },\n chrome_extensions: { label: 'Chrome', icon: <PackageIcon className=\"h-4 w-4\" /> },\n firefox_addons: { label: 'Firefox', icon: <PackageIcon className=\"h-4 w-4\" /> },\n safari_extensions: { label: 'Safari', icon: <PackageIcon className=\"h-4 w-4\" /> },\n ie_extensions: { label: 'IE', icon: <PackageIcon className=\"h-4 w-4\" /> },\n vscode_extensions: { label: 'VS Code', icon: <PackageIcon className=\"h-4 w-4\" /> },\n atom_packages: { label: 'Atom', icon: <PackageIcon className=\"h-4 w-4\" /> },\n homebrew_packages: { label: 'Homebrew', icon: <MacOSIcon className=\"h-4 w-4\" /> },\n npm_packages: { label: 'NPM', icon: <PackageIcon className=\"h-4 w-4\" /> },\n python_packages: { label: 'Python', icon: <PackageIcon className=\"h-4 w-4\" /> },\n apt_sources: { label: 'APT', icon: <LinuxIcon className=\"h-4 w-4\" /> },\n deb_packages: { label: 'DEB', icon: <LinuxIcon className=\"h-4 w-4\" /> },\n rpm_packages: { label: 'RPM', icon: <LinuxIcon className=\"h-4 w-4\" /> },\n yum_sources: { label: 'YUM', icon: <LinuxIcon className=\"h-4 w-4\" /> },\n portage_packages: { label: 'Portage', icon: <LinuxIcon className=\"h-4 w-4\" /> },\n chocolatey_packages: { label: 'Chocolatey', icon: <WindowsIcon className=\"h-4 w-4\" /> },\n programs: { label: 'Windows', icon: <WindowsIcon className=\"h-4 w-4\" /> },\n pkg_packages: { label: 'PKG', icon: <PackageIcon className=\"h-4 w-4\" /> },\n};\n\nexport const SoftwareSourceBadge: React.FC<SoftwareSourceBadgeProps> = ({ source, className }) => {\n const config = sourceConfig[source] || { label: source, icon: <PackageIcon className=\"h-4 w-4\" /> };\n\n return (\n <span className={cn('inline-flex items-center gap-2 text-ods-text-primary', className)}>\n {config.icon}\n {config.label}\n </span>\n );\n};\n\nSoftwareSourceBadge.displayName = 'SoftwareSourceBadge';\n","/**\n * CveLink Component\n *\n * Displays a CVE ID with an external link icon that links to the NIST NVD database.\n * Part of the ODS (OpenFrame Design System) platform components.\n *\n * @example\n * ```tsx\n * <CveLink cveId=\"CVE-2024-1234\" />\n * ```\n */\n\nimport type React from 'react';\nimport { cn } from '../../utils/cn';\nimport { CustomExternalLinkIcon } from '../icons';\n\nexport interface CveLinkProps {\n /** CVE ID (e.g., \"CVE-2024-1234\") */\n cveId: string;\n /** Additional CSS classes */\n className?: string;\n}\n\nexport const CveLink: React.FC<CveLinkProps> = ({ cveId, className }) => {\n const nistUrl = `https://nvd.nist.gov/vuln/detail/${cveId}`;\n\n return (\n <a\n href={nistUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cn(\n 'group inline-flex items-center gap-2 text-ods-text-primary transition-colors text-code hover:text-ods-accent',\n className,\n )}\n >\n <span>{cveId}</span>\n <CustomExternalLinkIcon className=\"h-4 w-4 text-ods-text-secondary transition-colors group-hover:text-ods-accent\" />\n </a>\n );\n};\n\nCveLink.displayName = 'CveLink';\n","/**\n * ToolBadge Component\n *\n * Displays a tool type badge with icon for OpenFrame integrated tools.\n * Used in tables to show tool sources like Fleet MDM, MeshCentral, etc.\n *\n * @example\n * ```tsx\n * <ToolBadge toolType=\"OPENFRAME_RMM\" />\n * <ToolBadge toolType=\"FLEET\" />\n * <ToolBadge toolType=\"MESHCENTRAL\" />\n * ```\n */\n\nimport type React from 'react';\nimport type { ToolType } from '../../types/tool.types';\nimport { cn } from '../../utils/cn';\nimport { getToolLabel } from '../../utils/tool-utils';\nimport { ToolIcon } from '../tool-icon';\n\nexport type { ToolType } from '../../types/tool.types';\n\nexport interface ToolBadgeProps {\n /** Tool type */\n toolType: ToolType;\n /** Additional CSS classes */\n className?: string;\n iconClassName?: string;\n}\n\nexport const ToolBadge: React.FC<ToolBadgeProps> = ({ toolType, className, iconClassName }) => {\n const label = getToolLabel(toolType);\n\n return (\n <div className={cn('flex items-center gap-1 text-ods-text-secondary', className)}>\n <ToolIcon toolType={toolType} className={iconClassName} size={16} />\n <span className=\"text-ods-text-primary text-h4\">{label}</span>\n </div>\n );\n};\n\nToolBadge.displayName = 'ToolBadge';\n","/**\n * ShellTypeBadge Component\n *\n * Displays a badge for shell/script types with appropriate icon and label.\n * Supports all RMM shell types.\n */\n\nimport type React from 'react';\nimport { type ShellType, ShellTypeValues } from '../../types/shell.types';\nimport { cn } from '../../utils/cn';\nimport { getShellLabel } from '../../utils/shell-utils';\nimport { BashIcon, CmdIcon, DenoIcon, NushellIcon, ShellIcon } from '../icons';\nimport { PowershellLogoGreyIcon } from '../icons-v2-generated/brand-logos/powershell-logo-grey-icon';\nimport { PythonLogoIcon } from '../icons-v2-generated/brand-logos/python-logo-icon';\n\n/**\n * Shell icon configuration with typed mapping\n */\ninterface ShellIconConfig {\n icon: React.ComponentType<{ size?: number; color?: string; className?: string }>;\n props: { size: number } & ({ className: string } | { color: string });\n}\n\n/**\n * Typed mapping of shell types to their icon configurations\n * Using Record<ShellType, ...> ensures all shell types are covered\n */\nconst shellIconMap: Record<ShellType, ShellIconConfig> = {\n [ShellTypeValues.POWERSHELL]: {\n icon: PowershellLogoGreyIcon,\n props: { size: 16, className: 'text-ods-text-secondary' },\n },\n [ShellTypeValues.CMD]: {\n icon: CmdIcon,\n props: { size: 16, color: 'var(--color-text-secondary)' },\n },\n [ShellTypeValues.BASH]: {\n icon: BashIcon,\n props: { size: 16, color: 'var(--color-text-secondary)' },\n },\n [ShellTypeValues.PYTHON]: {\n icon: PythonLogoIcon,\n props: { size: 16, className: 'text-ods-text-secondary' },\n },\n [ShellTypeValues.NUSHELL]: {\n icon: NushellIcon,\n props: { size: 16, color: 'var(--color-text-secondary)' },\n },\n [ShellTypeValues.DENO]: {\n icon: DenoIcon,\n props: { size: 16, color: 'var(--color-text-secondary)' },\n },\n [ShellTypeValues.SHELL]: {\n icon: ShellIcon,\n props: { size: 16, color: 'var(--color-text-secondary)' },\n },\n} as const;\n\nconst defaultIconConfig: ShellIconConfig = {\n icon: ShellIcon,\n props: { size: 16, color: 'var(--color-text-secondary)' },\n};\n\nexport interface ShellTypeBadgeProps {\n shellType: ShellType;\n className?: string;\n iconClassName?: string;\n}\n\nexport const ShellTypeBadge: React.FC<ShellTypeBadgeProps> = ({ shellType, className, iconClassName }) => {\n const normalizedType = shellType?.toUpperCase() as ShellType;\n const label = getShellLabel(normalizedType);\n const { icon: IconComponent, props: iconProps } = shellIconMap[normalizedType] ?? defaultIconConfig;\n const defaultIconClassName = 'className' in iconProps ? iconProps.className : undefined;\n\n return (\n <div className={cn('flex items-center gap-1', className)}>\n <IconComponent size={16} className={cn(defaultIconClassName, iconClassName)} />\n <span className=\"text-ods-text-primary text-h4\">{label}</span>\n </div>\n );\n};\n\nShellTypeBadge.displayName = 'ShellTypeBadge';\n","/**\n * ScriptInfoSection Component\n *\n * Displays script information in a card with header (title, description)\n * and detail cells (shell type, supported platforms, category, author).\n * Responsive layout: stacks cells on mobile, shows grid on desktop.\n */\n\nimport type React from 'react';\nimport Image from '../../embed-shims/next-image';\nimport { cn } from '../../utils/cn';\nimport { getOSLabel } from '../../utils/os-utils';\nimport { getShellLabel } from '../../utils/shell-utils';\n\n/**\n * Props for author avatar display\n */\nexport interface ScriptAuthor {\n /** Author name */\n name: string;\n /** Author initials (used when no photo) */\n initials?: string;\n /** URL to author's photo */\n photoUrl?: string;\n}\n\n/**\n * Props for ScriptInfoSection component\n */\nexport interface ScriptInfoSectionProps {\n /** Script title/name */\n headline: string;\n /** Script description */\n subheadline?: string;\n /** Shell type (POWERSHELL, BASH, CMD, etc.) */\n shellType?: string;\n /** Array of supported platform strings (windows, darwin, linux, etc.) */\n supportedPlatforms?: string[];\n /** Script category */\n category: string;\n /** Author information */\n author?: ScriptAuthor;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Formats supported platforms array into a display string\n * @param platforms - Array of platform strings (e.g., ['windows', 'darwin', 'linux'])\n * @returns Formatted string (e.g., 'Windows, macOS, Linux')\n */\nfunction formatSupportedPlatforms(platforms?: string[]): string {\n if (!platforms || platforms.length === 0) {\n return 'All Platforms';\n }\n return platforms.map(platform => getOSLabel(platform)).join(', ');\n}\n\n/**\n * Gets initials from a name\n * @param name - Full name\n * @returns Two-letter initials\n */\nfunction getInitials(name: string): string {\n const parts = name.trim().split(/\\s+/);\n if (parts.length >= 2) {\n return `${parts[0][0]}${parts[1][0]}`.toUpperCase();\n }\n return name.slice(0, 2).toUpperCase();\n}\n\n/**\n * InfoCell - Single info cell with label and value\n */\ninterface InfoCellProps {\n label: string;\n value: string;\n avatar?: ScriptAuthor;\n className?: string;\n}\n\nfunction InfoCell({ label, value, avatar, className }: InfoCellProps) {\n return (\n <div className={cn('flex min-w-0 items-center gap-2', className)}>\n {/* Avatar for author cell */}\n {avatar && (\n <div className=\"relative size-8 shrink-0 overflow-hidden rounded-full border border-ods-border bg-ods-bg\">\n {avatar.photoUrl ? (\n <Image src={avatar.photoUrl} alt={avatar.name} className=\"object-cover\" fill sizes=\"32px\" unoptimized />\n ) : (\n <div className=\"flex size-full items-center justify-center text-ods-text-secondary text-h6\">\n {avatar.initials || getInitials(avatar.name)}\n </div>\n )}\n </div>\n )}\n\n {/* Text content */}\n <div className=\"flex min-w-0 flex-col\">\n <span className=\"truncate text-ods-text-primary text-h4\" title={value}>\n {value}\n </span>\n <span className=\"truncate text-ods-text-secondary text-h6\">{label}</span>\n </div>\n </div>\n );\n}\n\n/**\n * ScriptInfoSection - Displays script information in a structured card\n *\n * @example\n * ```tsx\n * <ScriptInfoSection\n * title=\"System Backup Script\"\n * description=\"Comprehensive Linux system backup script...\"\n * shellType=\"BASH\"\n * supportedPlatforms={['linux']}\n * category=\"System Maintenance\"\n * author={{ name: 'John Doe', photoUrl: '/avatars/john.jpg' }}\n * />\n * ```\n */\nexport const ScriptInfoSection: React.FC<ScriptInfoSectionProps> = ({\n headline,\n subheadline,\n shellType,\n supportedPlatforms,\n category,\n author,\n className,\n}) => {\n const shellLabel = getShellLabel(shellType);\n const platformsLabel = formatSupportedPlatforms(supportedPlatforms);\n\n return (\n <div className={cn('overflow-hidden rounded-[6px] border border-ods-border bg-ods-card', className)}>\n {/* Header row with title and description */}\n <div className=\"border-b border-ods-border p-4\">\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"text-ods-text-primary text-h4\">{headline}</h3>\n {subheadline && <p className=\"break-words text-ods-text-secondary text-h6\">{subheadline}</p>}\n </div>\n </div>\n\n {/* Details section with info cells\n - Mobile/Tablet (<lg): 2x2 grid with divider between rows\n - Desktop (lg+): 4 columns in single row\n */}\n {/* First row: Shell Type, Supported Platforms */}\n <div className=\"grid grid-cols-2 gap-4 border-b border-ods-border px-4 py-4 lg:grid-cols-4 lg:border-b-0\">\n <InfoCell label=\"Shell Type\" value={shellLabel} />\n <InfoCell label=\"Supported Platforms\" value={platformsLabel} />\n {/* Desktop only: Category and Author in same row */}\n <InfoCell label=\"Category\" value={category} className=\"hidden lg:flex\" />\n {author && <InfoCell label=\"Added by\" value={author.name} avatar={author} className=\"hidden lg:flex\" />}\n </div>\n {/* Second row (mobile/tablet only): Category, Author */}\n <div className=\"grid grid-cols-2 gap-4 px-4 py-4 lg:hidden\">\n <InfoCell label=\"Category\" value={category} />\n {author && <InfoCell label=\"Added by\" value={author.name} avatar={author} />}\n </div>\n </div>\n );\n};\n\nScriptInfoSection.displayName = 'ScriptInfoSection';\n","/**\n * ScriptArguments Component\n *\n * Displays and manages script arguments as key-value pairs.\n * Each argument has a name (key) and value input field with delete button.\n * Includes an \"Add Script Argument\" button to add new entries.\n */\n\nimport { Trash2 } from 'lucide-react';\nimport type React from 'react';\nimport { cn } from '../../utils/cn';\nimport { PlusCircleIcon } from '../icons-v2-generated';\nimport { Button } from '../ui/button';\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\n\n/**\n * Single script argument with key and value\n */\nexport interface ScriptArgument {\n /** Unique identifier for the argument */\n id: string;\n /** Argument name/key */\n key: string;\n /** Argument value (empty string for flag-type arguments) */\n value: string;\n}\n\n/**\n * Props for ScriptArguments component\n */\nexport interface ScriptArgumentsProps {\n /** Array of script arguments */\n arguments: ScriptArgument[];\n /** Callback when arguments change */\n onArgumentsChange?: (args: ScriptArgument[]) => void;\n /** Placeholder for key input */\n keyPlaceholder?: string;\n /** Placeholder for value input */\n valuePlaceholder?: string;\n /** Label for the add button */\n addButtonLabel?: string;\n /** Whether the component is disabled */\n disabled?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Label for the title input */\n titleLabel: string;\n}\n\n/**\n * ScriptArguments - Displays and manages script arguments\n *\n * @example\n * ```tsx\n * <ScriptArguments\n * arguments={[\n * { id: '1', key: 'port', value: '3000' },\n * { id: '2', key: 'verbose', value: '' },\n * ]}\n * onArgumentsChange={(args) => setArguments(args)}\n * />\n * ```\n */\nexport const ScriptArguments: React.FC<ScriptArgumentsProps> = ({\n arguments: args,\n onArgumentsChange,\n keyPlaceholder = 'Enter Key',\n valuePlaceholder = 'Enter Value (empty=flag)',\n addButtonLabel = 'Add Script Argument',\n disabled = false,\n className,\n titleLabel,\n}) => {\n const handleKeyChange = (id: string, newKey: string) => {\n if (!onArgumentsChange) return;\n const updated = args.map(arg => (arg.id === id ? { ...arg, key: newKey } : arg));\n onArgumentsChange(updated);\n };\n\n const handleValueChange = (id: string, newValue: string) => {\n if (!onArgumentsChange) return;\n const updated = args.map(arg => (arg.id === id ? { ...arg, value: newValue } : arg));\n onArgumentsChange(updated);\n };\n\n const handleDelete = (id: string) => {\n if (!onArgumentsChange) return;\n const updated = args.filter(arg => arg.id !== id);\n onArgumentsChange(updated);\n };\n\n const handleAdd = () => {\n if (!onArgumentsChange) return;\n const newArg: ScriptArgument = {\n id: crypto.randomUUID(),\n key: '',\n value: '',\n };\n onArgumentsChange([...args, newArg]);\n };\n\n const isFirstRow = (index: number) => index === 0;\n\n return (\n <div className={cn('flex flex-col gap-2', className)}>\n {args.map((arg, index) => (\n <div key={arg.id} className=\"flex w-full items-end gap-2\">\n {/* Key input - with label only on first row */}\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n {isFirstRow(index) && <Label spacing=\"tight\">{titleLabel}</Label>}\n <Input\n value={arg.key}\n onChange={e => handleKeyChange(arg.id, e.target.value)}\n placeholder={keyPlaceholder}\n disabled={disabled}\n />\n </div>\n\n {/* Value input with delete button */}\n {/* Value input with delete button */}\n <div className=\"flex min-w-0 flex-1 items-center gap-2\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <Input\n value={arg.value}\n onChange={e => handleValueChange(arg.id, e.target.value)}\n placeholder={valuePlaceholder}\n disabled={disabled}\n className={cn(!arg.value && 'placeholder:text-ods-text-muted')}\n />\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon\"\n onClick={() => handleDelete(arg.id)}\n disabled={disabled}\n aria-label=\"Delete argument\"\n leftIcon={<Trash2 className=\"size-4 md:size-6\" color=\"var(--color-error)\" />}\n />\n </div>\n </div>\n ))}\n\n {/* Add button - aligned left */}\n <div className=\"flex justify-start\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"small\"\n onClick={handleAdd}\n disabled={disabled}\n className=\"self-start\"\n leftIcon={<PlusCircleIcon className=\"text-ods-text-secondary\" />}\n >\n {addButtonLabel}\n </Button>\n </div>\n </div>\n );\n};\n\nScriptArguments.displayName = 'ScriptArguments';\n","'use client';\n\nimport React from 'react';\nimport { cn } from '../../../utils/cn';\nimport { Button } from '../../ui/button';\nimport { InteractiveCard } from '../../ui/interactive-card';\nimport { StatusBadge } from '../../ui/status-badge';\n\nexport interface OnboardingStepCardProps {\n step: {\n id: string;\n title: string;\n description: string;\n actionIcon: (color?: string) => React.ReactNode;\n actionText: string;\n completedText: string;\n onAction: () => void | Promise<void>;\n onSkip?: () => void;\n };\n isCompleted: boolean;\n isSkipped: boolean;\n isCheckingCompletion: boolean;\n onAction: () => void | Promise<void>;\n onSkip: () => void;\n className?: string;\n}\n\nexport function OnboardingStepCard({\n step,\n isCompleted,\n isSkipped,\n isCheckingCompletion,\n onAction,\n onSkip,\n className,\n}: OnboardingStepCardProps) {\n const [isProcessing, setIsProcessing] = React.useState(false);\n\n const handleAction = async (e: React.MouseEvent) => {\n e.stopPropagation();\n setIsProcessing(true);\n try {\n await onAction();\n } finally {\n setIsProcessing(false);\n }\n };\n\n const handleSkip = (e: React.MouseEvent) => {\n e.stopPropagation();\n onSkip();\n };\n\n return (\n <InteractiveCard\n clickable={false}\n className={cn(\n 'rounded-[6px] border border-ods-border bg-ods-card',\n 'flex flex-col md:flex-row',\n 'min-h-[80px] md:h-[80px]',\n 'items-start md:items-center',\n 'gap-3 md:gap-4',\n 'px-4 py-4 md:py-0',\n className,\n )}\n >\n {/* Left column - content */}\n <div className=\"flex w-full min-w-0 flex-1 flex-col justify-center gap-1 md:w-auto\">\n <h3 className=\"truncate text-ods-text-primary text-h4\" title={step.title}>\n {step.title}\n </h3>\n <p className=\"h-[20px] truncate text-ods-text-secondary text-h6\" title={step.description}>\n {step.description}\n </p>\n </div>\n\n {/* Right column - action buttons, completed badge, or skipped badge */}\n <div\n className=\"flex w-full shrink-0 items-center justify-start gap-2 md:w-auto md:justify-end\"\n onClick={e => e.stopPropagation()}\n >\n {isCheckingCompletion ? (\n <>\n <div className=\"h-[32px] w-[100px] animate-pulse rounded-[6px] bg-ods-border\" />\n <div className=\"h-[32px] w-[120px] animate-pulse rounded-[6px] bg-ods-border\" />\n </>\n ) : isCompleted ? (\n <>\n <StatusBadge text=\"COMPLETED\" variant=\"card\" colorScheme=\"success\" />\n <Button\n variant=\"outline\"\n onClick={handleAction}\n disabled={isProcessing}\n leftIcon={step.actionIcon('white')}\n >\n {step.completedText}\n </Button>\n </>\n ) : isSkipped ? (\n <>\n <StatusBadge text=\"SKIPPED\" variant=\"card\" colorScheme=\"default\" />\n </>\n ) : (\n <>\n <Button variant=\"outline\" onClick={handleSkip}>\n Skip Step\n </Button>\n <Button variant=\"accent\" onClick={handleAction} disabled={isProcessing} leftIcon={step.actionIcon('black')}>\n {step.actionText}\n </Button>\n </>\n )}\n </div>\n </InteractiveCard>\n );\n}\n","'use client';\n\nimport React, { useRef, useCallback } from 'react';\nimport { useOnboardingState, type OnboardingStepConfig } from '../../../hooks/ui/use-onboarding-state';\nimport { cn } from '../../../utils/cn';\nimport { SECTION_HEADING_CLASS } from '../../layout/page-heading';\nimport { Button } from '../../ui/button';\nimport { OnboardingStepCard } from './onboarding-step-card';\n\nexport interface OnboardingWalkthroughProps {\n steps: OnboardingStepConfig[];\n onDismiss?: () => void;\n storageKey?: string;\n className?: string;\n spacing?: string;\n /**\n * Completion status from hook-based checks (e.g., useOnboardingCompletion)\n * Object mapping step IDs to boolean completion status\n */\n completionStatus?: Record<string, boolean>;\n /**\n * Whether completion checks are still loading\n */\n isLoadingCompletion?: boolean;\n}\n\nexport function OnboardingWalkthrough({\n steps,\n onDismiss,\n storageKey = 'openframe-onboarding-state',\n className,\n spacing = 'space-y-4',\n completionStatus,\n isLoadingCompletion = false,\n}: OnboardingWalkthroughProps) {\n const {\n state,\n markComplete,\n markSkipped,\n dismissOnboarding,\n isStepComplete,\n isStepSkipped,\n allStepsComplete,\n markMultipleComplete,\n } = useOnboardingState(storageKey);\n\n // Refs to prevent race conditions - ALL refs must be declared before any conditional returns\n const hasAutoMarkedRef = useRef(false);\n const autoMarkingInProgressRef = useRef(false);\n const lastCompletionStatusRef = useRef<string | null>(null);\n // Ref to track in-flight action handlers - moved here to be before conditional return\n const actionInProgressRef = useRef<Set<string>>(new Set());\n\n // Sync completion status from hooks to localStorage\n // Uses refs to prevent duplicate calls and race conditions\n React.useEffect(() => {\n // Skip if still loading\n if (isLoadingCompletion) {\n hasAutoMarkedRef.current = false; // Reset when loading starts\n return;\n }\n\n // Skip if no completion status\n if (!completionStatus) return;\n\n // Create a stable key from completion status to detect actual changes\n const statusKey = JSON.stringify(completionStatus);\n\n // Skip if we've already processed this exact status\n if (lastCompletionStatusRef.current === statusKey) return;\n\n // Skip if auto-marking is currently in progress\n if (autoMarkingInProgressRef.current) return;\n\n // Find steps that need to be marked complete\n // Read directly from state to avoid stale closure issues\n const completedStepIds = Object.entries(completionStatus)\n .filter(([stepId, isComplete]) => {\n if (!isComplete) return false;\n // Check against current state, not the callback\n return !state.completedSteps.includes(stepId);\n })\n .map(([stepId]) => stepId);\n\n if (completedStepIds.length > 0) {\n // Mark as in progress to prevent concurrent calls\n autoMarkingInProgressRef.current = true;\n\n console.log('📊 Auto-marking steps as complete from hook data:', completedStepIds);\n markMultipleComplete(completedStepIds);\n\n // Update the last processed status key\n lastCompletionStatusRef.current = statusKey;\n\n // Reset the in-progress flag after a short delay\n // This prevents rapid successive calls while allowing future updates\n setTimeout(() => {\n autoMarkingInProgressRef.current = false;\n }, 100);\n } else {\n // Even if no steps to mark, update the status key to prevent re-processing\n lastCompletionStatusRef.current = statusKey;\n }\n }, [completionStatus, isLoadingCompletion, state.completedSteps, markMultipleComplete]);\n\n // useCallback must be called unconditionally (before any early returns)\n const handleStepAction = useCallback(\n async (step: OnboardingStepConfig) => {\n // Prevent duplicate action handling for the same step\n if (actionInProgressRef.current.has(step.id)) {\n console.log(`⏳ Action already in progress for \"${step.id}\", skipping`);\n return;\n }\n\n // Mark as in progress\n actionInProgressRef.current.add(step.id);\n\n try {\n await step.onAction();\n\n // Skip if already completed (could have been auto-marked while action was running)\n if (state.completedSteps.includes(step.id)) {\n console.log(`✓ Step \"${step.id}\" already completed, skipping mark`);\n return;\n }\n\n // Auto-mark Knowledge Base as complete (no verification needed)\n if (step.id === 'knowledge-base') {\n console.log(`🎯 Auto-completing Knowledge Base`);\n markComplete(step.id);\n return;\n }\n\n // For other steps, re-check completion after action\n if (step.checkComplete) {\n try {\n const isComplete = await step.checkComplete();\n console.log(`🔍 Post-action check for \"${step.id}\": isComplete=${isComplete}`);\n\n // Double-check it wasn't completed while we were checking\n if (isComplete && !state.completedSteps.includes(step.id)) {\n markComplete(step.id);\n }\n } catch (error) {\n console.error(`Error checking completion for \"${step.id}\":`, error);\n }\n }\n } finally {\n // Remove from in-progress set\n actionInProgressRef.current.delete(step.id);\n }\n },\n [state.completedSteps, markComplete],\n );\n\n const handleStepSkip = (step: OnboardingStepConfig) => {\n step.onSkip?.();\n markSkipped(step.id);\n };\n\n const handleDismiss = () => {\n dismissOnboarding();\n onDismiss?.();\n };\n\n // ALL hooks have been called above - now safe to do conditional returns\n // Don't render if dismissed\n if (state.dismissed) {\n return null;\n }\n\n const isAllComplete = allStepsComplete(steps);\n\n return (\n <div className={cn('w-full space-y-4', className)}>\n {/* Header - responsive: stacks on mobile */}\n <div className=\"flex flex-col items-start justify-between gap-3 md:flex-row md:items-center md:gap-0\">\n <h2 className={SECTION_HEADING_CLASS}>Get Started</h2>\n\n {isLoadingCompletion ? (\n <div className=\"h-[48px] w-full animate-pulse rounded-[6px] bg-ods-border md:w-[160px]\" />\n ) : isAllComplete ? (\n <Button variant=\"accent\" onClick={handleDismiss} className=\"w-full md:w-auto\">\n Close Onboarding\n </Button>\n ) : (\n <Button variant=\"outline\" onClick={handleDismiss} className=\"w-full md:w-auto\">\n Skip Onboarding\n </Button>\n )}\n </div>\n\n {/* Step cards - no wrapper, direct rendering */}\n <div className={cn(spacing)}>\n {steps.map(step => (\n <OnboardingStepCard\n key={step.id}\n step={step}\n isCompleted={isStepComplete(step.id)}\n isSkipped={isStepSkipped(step.id)}\n isCheckingCompletion={isLoadingCompletion}\n onAction={() => handleStepAction(step)}\n onSkip={() => handleStepSkip(step)}\n />\n ))}\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -32,6 +32,10 @@ var buttonSurfaceClasses = {
|
|
|
32
32
|
};
|
|
33
33
|
var outlineBorderClasses = "border border-ods-border hover:border-ods-border-hover active:border-ods-border-active disabled:border-ods-border aria-disabled:border-ods-border";
|
|
34
34
|
var splitGlyphSizeClasses = "[&_svg]:h-4 [&_svg]:w-4 md:[&_svg]:h-6 md:[&_svg]:w-6";
|
|
35
|
+
var splitGlyphSizeBySize = {
|
|
36
|
+
default: splitGlyphSizeClasses,
|
|
37
|
+
small: "[&_svg]:h-4 [&_svg]:w-4"
|
|
38
|
+
};
|
|
35
39
|
var splitDividerColorClasses = {
|
|
36
40
|
accent: "border-ods-accent-active",
|
|
37
41
|
outline: "border-ods-border",
|
|
@@ -172,12 +176,21 @@ var splitSlotVariants = _classvarianceauthority.cva.call(void 0,
|
|
|
172
176
|
main: "gap-[var(--spacing-system-xsf)]",
|
|
173
177
|
icon: "border-l"
|
|
174
178
|
},
|
|
175
|
-
size:
|
|
176
|
-
variant: { accent: "", outline: "", transparent: "", destructive: "", warning: "" }
|
|
179
|
+
size: splitGlyphSizeBySize,
|
|
180
|
+
variant: { accent: "", outline: "", transparent: "", destructive: "", warning: "" },
|
|
181
|
+
fullWidth: { true: "", false: "" }
|
|
177
182
|
},
|
|
178
183
|
compoundVariants: [
|
|
179
184
|
{ slot: "main", size: "default", class: "px-[var(--spacing-system-m)] py-[var(--spacing-system-sf)]" },
|
|
180
185
|
{ slot: "main", size: "small", class: "px-[var(--spacing-system-xs)]" },
|
|
186
|
+
// `fullWidth` stretches the SHELL, not its children, so without this the main
|
|
187
|
+
// half stays content-sized and the icon half floats mid-button with dead space
|
|
188
|
+
// after it instead of sitting flush against the trailing edge. Keyed on
|
|
189
|
+
// `fullWidth` to match `SplitButton`, which grows its main half on exactly the
|
|
190
|
+
// same condition (`grow={fullWidth}`) — the two split layouts render side by
|
|
191
|
+
// side in the same rows and must not disagree. Callers that stretch the shell
|
|
192
|
+
// some other way (a `flex-1` className, a grid cell) keep the old behaviour.
|
|
193
|
+
{ slot: "main", fullWidth: true, class: "flex-1" },
|
|
181
194
|
{ slot: "icon", size: "default", class: "w-10" },
|
|
182
195
|
{ slot: "icon", size: "small", class: "w-6 md:w-8" },
|
|
183
196
|
{
|
|
@@ -207,7 +220,7 @@ var splitSlotVariants = _classvarianceauthority.cva.call(void 0,
|
|
|
207
220
|
)
|
|
208
221
|
}
|
|
209
222
|
],
|
|
210
|
-
defaultVariants: { slot: "main", size: "default", variant: "accent" }
|
|
223
|
+
defaultVariants: { slot: "main", size: "default", variant: "accent", fullWidth: false }
|
|
211
224
|
}
|
|
212
225
|
);
|
|
213
226
|
var Spinner = () => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "svg", { className: "animate-spin", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
|
|
@@ -248,7 +261,7 @@ var Button = _react2.default.forwardRef(function ButtonImpl({
|
|
|
248
261
|
const safeSize = _nullishCoalesce(size, () => ( "default"));
|
|
249
262
|
const safeVariant = _nullishCoalesce(variant, () => ( "accent"));
|
|
250
263
|
const shellClasses = _chunkPRPZBXWZcjs.cn.call(void 0, splitShellVariants({ variant: safeVariant, size: safeSize, font, fullWidth }), className);
|
|
251
|
-
const mainSlotClass = splitSlotVariants({ slot: "main", size: safeSize, variant: safeVariant });
|
|
264
|
+
const mainSlotClass = splitSlotVariants({ slot: "main", size: safeSize, variant: safeVariant, fullWidth });
|
|
252
265
|
const iconSlotClass = splitSlotVariants({ slot: "icon", size: safeSize, variant: safeVariant });
|
|
253
266
|
const splitContent = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
|
|
254
267
|
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: _chunkPRPZBXWZcjs.cn.call(void 0, "contents", loading && "invisible"), children: [
|
|
@@ -259,7 +272,21 @@ var Button = _react2.default.forwardRef(function ButtonImpl({
|
|
|
259
272
|
] }),
|
|
260
273
|
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { "aria-hidden": "true", className: iconSlotClass, children: splitIcon })
|
|
261
274
|
] }),
|
|
262
|
-
loading &&
|
|
275
|
+
loading && // Carries the glyph scale itself: this overlay is a SIBLING of the slots, so
|
|
276
|
+
// it inherits neither their `[&_svg]` sizing nor a shell base rule (the shell
|
|
277
|
+
// deliberately has none — see `splitSlotVariants`). Without it the spinner
|
|
278
|
+
// renders unconstrained and fills the button. Reads the same per-size ramp the
|
|
279
|
+
// slots do, so it matches the glyphs it covers at both breakpoints.
|
|
280
|
+
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
281
|
+
"span",
|
|
282
|
+
{
|
|
283
|
+
className: _chunkPRPZBXWZcjs.cn.call(void 0,
|
|
284
|
+
"absolute inset-0 inline-flex items-center justify-center text-ods-text-primary",
|
|
285
|
+
splitGlyphSizeBySize[safeSize]
|
|
286
|
+
),
|
|
287
|
+
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, {})
|
|
288
|
+
}
|
|
289
|
+
)
|
|
263
290
|
] });
|
|
264
291
|
const splitAnchor = _nullishCoalesce(linkProps, () => ( (href ? {
|
|
265
292
|
href,
|
|
@@ -510,4 +537,4 @@ SplitButton.displayName = "SplitButton";
|
|
|
510
537
|
|
|
511
538
|
|
|
512
539
|
exports.buttonVariants = buttonVariants; exports.Button = Button; exports.SplitButton = SplitButton;
|
|
513
|
-
//# sourceMappingURL=chunk-
|
|
540
|
+
//# sourceMappingURL=chunk-YHNIPSG6.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-YHNIPSG6.cjs","../src/components/ui/button/button.tsx","../src/components/ui/button/button-styles.ts","../src/components/ui/button/split-button.tsx"],"names":["cva","jsx","jsxs"],"mappings":"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","file":"/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-YHNIPSG6.cjs","sourcesContent":[null,"'use client';\n\nimport { Slot } from '@radix-ui/react-slot';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport React from 'react';\nimport Link from '../../../embed-shims/next-link';\nimport { cn } from '../../../utils/cn';\nimport {\n buttonSurfaceClasses,\n outlineBorderClasses,\n splitDividerColorClasses,\n splitGlyphSizeBySize,\n} from './button-styles';\n\n// Default layout: centered single content area, padding/gap on the button itself.\nconst buttonVariants = cva(\n [\n 'relative inline-flex items-center justify-center gap-[var(--spacing-system-xsf)]',\n 'whitespace-nowrap rounded-md',\n 'transition-colors duration-200',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ods-focus',\n 'disabled:pointer-events-none',\n '[&_svg]:pointer-events-none [&_svg]:h-5 [&_svg]:w-5 [&_svg]:shrink-0',\n ],\n {\n variants: {\n variant: {\n accent: buttonSurfaceClasses.accent,\n outline: cn(buttonSurfaceClasses.outline, outlineBorderClasses),\n transparent: buttonSurfaceClasses.transparent,\n destructive: buttonSurfaceClasses.destructive,\n warning: buttonSurfaceClasses.warning,\n glyph: buttonSurfaceClasses.glyph,\n overlay: buttonSurfaceClasses.overlay,\n },\n size: {\n default: 'h-11 px-[var(--spacing-system-m)] py-[var(--spacing-system-sf)] text-h3 md:h-12',\n small: 'h-6 p-[var(--spacing-system-xs)] text-h5 md:h-8',\n 'small-legacy': 'h-10 px-[var(--spacing-system-m)] py-[var(--spacing-system-xs)] text-[14px] font-bold', // Temporary alias for \"small\" — deprecated; grep size=\"small-legacy\" (lib + hub) and migrate the remaining consumers before removal\n // 24px pill for slim strips (announcement/promo bars, inline banner\n // actions — Primer banner / Polaris banner / Vercel-bar convention).\n // The label matches the strip's MESSAGE type ramp exactly (DM Sans\n // regular, 13px -> md:14px, snug leading — the announcement bar's\n // subtitle styling): in-strip CTAs must never read louder than the\n // message beside them, so this deliberately uses neither the\n // mono-uppercase control style of \"small\" nor a heavier weight.\n // Pinned h-6 across breakpoints (24px = the WCAG 2.5.8 target-size\n // floor) with horizontal-dominant padding and a 14px glyph.\n compact: 'h-6 px-[var(--spacing-system-sf)] py-0 font-normal text-h6 [&_svg]:h-3.5 [&_svg]:w-3.5',\n icon: 'h-11 w-11 p-[var(--spacing-system-sf)] md:h-12 md:w-12 [&_svg]:h-4 [&_svg]:w-4 md:[&_svg]:h-6 md:[&_svg]:w-6',\n // Quiet 32px icon target with a 16px glyph, fixed across breakpoints\n // (Carbon ghost sm / Primer medium / shadcn icon-sm all pin 32px;\n // ≥ the 24px WCAG 2.5.8 target floor). For icon actions that read as\n // metadata rather than CTAs — author-page social rows, share rows.\n // Pair with variant=\"transparent\" for the ghost treatment.\n 'icon-sm': 'h-8 w-8 p-[var(--spacing-system-xxs)] [&_svg]:h-4 [&_svg]:w-4',\n // 20px inline glyph for affordances that sit INSIDE a line of text —\n // an info hint beside a badge, a copy glyph after an id. `icon-sm`'s\n // 32px target is correct for a metadata row but visually swamps a\n // 10px badge or a 14px label, so hosts were reaching for className\n // overrides to shrink it. Below the WCAG 2.5.8 target floor on purpose:\n // this is only for glyphs whose information is ALSO available another\n // way (tooltip content mirrored into an aria-describedby node), never\n // for a sole means of performing an action.\n 'icon-inline': 'h-5 min-h-0 w-5 min-w-0 shrink-0 p-0 [&_svg]:h-3.5 [&_svg]:w-3.5',\n // Bare 56px media glyph (play / unmute over video). A size variant so\n // hosts stop re-implementing a <button> to escape the 20px svg cap.\n 'icon-glyph': 'h-14 w-14 p-0 [&_svg]:h-14 [&_svg]:w-14',\n },\n // Label typography axis (Figma 133-740). `bold` is the classic h3-bold\n // label; `regular` swaps the DEFAULT size's label to the h4 step\n // (DM Sans 500, neutral tracking) — added for navigation buttons.\n // `small` keeps its mono-uppercase h5 label on both fonts per the spec.\n font: {\n bold: '',\n regular: '',\n },\n fullWidth: {\n true: 'w-full',\n false: '',\n },\n noPaddingX: {\n true: 'px-0',\n false: '',\n },\n },\n compoundVariants: [\n { size: 'small', class: '[&_svg]:h-4 [&_svg]:w-4' },\n // Comes after the size classes, so cn()'s tailwind-merge resolves the\n // ods-typography group in favour of text-h4.\n { size: 'default', font: 'regular', class: 'text-h4' },\n ],\n defaultVariants: {\n variant: 'accent',\n size: 'default',\n font: 'bold',\n fullWidth: false,\n noPaddingX: false,\n },\n },\n);\n\n// Split layout (used when `splitIcon` is provided): outer button has no padding;\n// inner slots own padding/gap so the divider can span full button height.\nconst splitShellVariants = cva(\n [\n 'group relative inline-flex items-stretch overflow-hidden whitespace-nowrap rounded-md',\n 'transition-colors duration-200',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ods-focus',\n 'disabled:pointer-events-none',\n ],\n {\n variants: {\n variant: {\n accent: buttonSurfaceClasses.accent,\n outline: cn(buttonSurfaceClasses.outline, outlineBorderClasses),\n transparent: buttonSurfaceClasses.transparent,\n destructive: buttonSurfaceClasses.destructive,\n warning: buttonSurfaceClasses.warning,\n },\n size: {\n default: 'h-12',\n small: 'h-6 text-h5 md:h-8',\n },\n // Same label-typography axis as the normal layout — `regular` swaps the\n // default size's h3-bold label for the h4 (DM Sans 500) step.\n font: { bold: '', regular: '' },\n fullWidth: { true: 'w-full', false: '' },\n },\n compoundVariants: [\n { size: 'default', font: 'bold', class: 'text-h3' },\n { size: 'default', font: 'regular', class: 'text-h4' },\n ],\n defaultVariants: { variant: 'accent', size: 'default', font: 'bold', fullWidth: false },\n },\n);\n\nconst splitSlotVariants = cva(\n // Glyph size lives per-size, not in the base: cva concatenates base + variant\n // without tailwind-merge, so a base `[&_svg]:h-5` and a variant `[&_svg]:h-4`\n // would both ship and the winner would come down to stylesheet order.\n ['inline-flex items-center justify-center', '[&_svg]:shrink-0'],\n {\n variants: {\n slot: {\n main: 'gap-[var(--spacing-system-xsf)]',\n icon: 'border-l',\n },\n size: splitGlyphSizeBySize,\n variant: { accent: '', outline: '', transparent: '', destructive: '', warning: '' },\n fullWidth: { true: '', false: '' },\n },\n compoundVariants: [\n { slot: 'main', size: 'default', class: 'px-[var(--spacing-system-m)] py-[var(--spacing-system-sf)]' },\n { slot: 'main', size: 'small', class: 'px-[var(--spacing-system-xs)]' },\n // `fullWidth` stretches the SHELL, not its children, so without this the main\n // half stays content-sized and the icon half floats mid-button with dead space\n // after it instead of sitting flush against the trailing edge. Keyed on\n // `fullWidth` to match `SplitButton`, which grows its main half on exactly the\n // same condition (`grow={fullWidth}`) — the two split layouts render side by\n // side in the same rows and must not disagree. Callers that stretch the shell\n // some other way (a `flex-1` className, a grid cell) keep the old behaviour.\n { slot: 'main', fullWidth: true, class: 'flex-1' },\n { slot: 'icon', size: 'default', class: 'w-10' },\n { slot: 'icon', size: 'small', class: 'w-6 md:w-8' },\n {\n slot: 'icon',\n variant: 'accent',\n class: cn(\n splitDividerColorClasses.accent,\n 'group-disabled:border-ods-disabled group-aria-disabled:border-ods-disabled',\n ),\n },\n { slot: 'icon', variant: 'outline', class: splitDividerColorClasses.outline },\n { slot: 'icon', variant: 'transparent', class: splitDividerColorClasses.transparent },\n {\n slot: 'icon',\n variant: 'destructive',\n class: cn(\n splitDividerColorClasses.destructive,\n 'group-disabled:border-ods-disabled group-aria-disabled:border-ods-disabled',\n ),\n },\n {\n slot: 'icon',\n variant: 'warning',\n class: cn(\n splitDividerColorClasses.warning,\n 'group-disabled:border-ods-disabled group-aria-disabled:border-ods-disabled',\n ),\n },\n ],\n defaultVariants: { slot: 'main', size: 'default', variant: 'accent', fullWidth: false },\n },\n);\n\n/** @deprecated Use `size=\"small\"` instead. Temporary alias kept for backward compatibility; will be removed in the future. */\ntype DeprecatedButtonSize = 'small-legacy';\n\ntype ButtonSize =\n Exclude<VariantProps<typeof buttonVariants>['size'], 'small-legacy' | null | undefined> | DeprecatedButtonSize;\n\ninterface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>, Omit<VariantProps<typeof buttonVariants>, 'size'> {\n asChild?: boolean;\n href?: string;\n openInNewTab?: boolean;\n prefetch?: boolean;\n /**\n * Pre-resolved anchor bundle (from `useNavLink({ href, targetPlatform })`).\n * When set, renders the Button as `<Link>` with `href` / `target` / `rel`\n * / `onClick` spread from this object. Lets callers thread the unified\n * nav decision directly without `<Button asChild><a {...linkProps}/>`\n * gymnastics. Wins over the separate `href` / `openInNewTab` props.\n */\n linkProps?: {\n href: string;\n target?: '_blank';\n rel?: 'noopener noreferrer';\n onClick?: React.MouseEventHandler<HTMLAnchorElement>;\n } | null;\n leftIcon?: React.ReactNode;\n rightIcon?: React.ReactNode;\n /**\n * Renders a vertical divider and trailing icon area inside the button.\n * The whole button stays a single click target — the icon is decorative\n * (`aria-hidden`). For two independent click targets, use `<SplitButton>`.\n * Only honored when `size` is `\"default\"` or `\"small\"`.\n */\n splitIcon?: React.ReactNode;\n loading?: boolean;\n size?: ButtonSize;\n}\n\nconst Spinner = () => (\n <svg className=\"animate-spin\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n);\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(function ButtonImpl(\n {\n className,\n variant,\n size,\n font,\n fullWidth,\n noPaddingX,\n asChild,\n href,\n openInNewTab,\n prefetch,\n linkProps,\n leftIcon,\n rightIcon,\n splitIcon,\n loading,\n children,\n disabled,\n onClick,\n ...props\n },\n ref,\n) {\n const isDisabled = disabled || loading;\n\n // splitIcon is only supported for default/small sizes. With other sizes\n // (icon, small-legacy) we silently fall back to the normal layout.\n const useSplitLayout = !!splitIcon && (size === 'default' || size === 'small' || size === undefined);\n\n if (useSplitLayout) {\n const safeSize = size ?? 'default';\n const safeVariant = (variant ?? 'accent') as 'accent' | 'outline' | 'transparent' | 'destructive' | 'warning';\n const shellClasses = cn(splitShellVariants({ variant: safeVariant, size: safeSize, font, fullWidth }), className);\n const mainSlotClass = splitSlotVariants({ slot: 'main', size: safeSize, variant: safeVariant, fullWidth });\n const iconSlotClass = splitSlotVariants({ slot: 'icon', size: safeSize, variant: safeVariant });\n\n const splitContent = (\n <>\n <span className={cn('contents', loading && 'invisible')}>\n <span className={mainSlotClass}>\n {leftIcon && <span className=\"inline-flex items-center\">{leftIcon}</span>}\n {children}\n {rightIcon && <span className=\"inline-flex items-center\">{rightIcon}</span>}\n </span>\n <span aria-hidden=\"true\" className={iconSlotClass}>\n {splitIcon}\n </span>\n </span>\n {loading && (\n // Carries the glyph scale itself: this overlay is a SIBLING of the slots, so\n // it inherits neither their `[&_svg]` sizing nor a shell base rule (the shell\n // deliberately has none — see `splitSlotVariants`). Without it the spinner\n // renders unconstrained and fills the button. Reads the same per-size ramp the\n // slots do, so it matches the glyphs it covers at both breakpoints.\n <span\n className={cn(\n 'absolute inset-0 inline-flex items-center justify-center text-ods-text-primary',\n splitGlyphSizeBySize[safeSize],\n )}\n >\n <Spinner />\n </span>\n )}\n </>\n );\n\n // `linkProps` (the pre-resolved bundle from `useNavLink({ href, targetPlatform })`)\n // wins over the legacy `href` + `openInNewTab` props so callers can thread\n // the unified nav decision directly. Either path produces the same `<Link>`.\n const splitAnchor =\n linkProps ??\n (href\n ? {\n href,\n target: openInNewTab ? ('_blank' as const) : undefined,\n rel: openInNewTab ? ('noopener noreferrer' as const) : undefined,\n onClick: onClick as unknown as React.MouseEventHandler<HTMLAnchorElement> | undefined,\n }\n : null);\n if (splitAnchor) {\n return (\n <Link\n href={splitAnchor.href}\n prefetch={prefetch}\n target={splitAnchor.target}\n rel={splitAnchor.rel}\n // The Link branches don't spread {...props} (button attrs don't\n // belong on an anchor), but the accessible name MUST survive —\n // icon-only link buttons have no text content.\n aria-label={props['aria-label']}\n aria-disabled={isDisabled || undefined}\n tabIndex={isDisabled ? -1 : undefined}\n className={cn(shellClasses, isDisabled && 'pointer-events-none')}\n onClick={splitAnchor.onClick}\n >\n {splitContent}\n </Link>\n );\n }\n\n return (\n <button ref={ref} className={shellClasses} disabled={isDisabled} onClick={onClick} {...props}>\n {splitContent}\n </button>\n );\n }\n\n const classes = cn(buttonVariants({ variant, size, font, fullWidth, noPaddingX }), className);\n\n // asChild: consumer fully controls the rendered element; we just stamp our classes.\n if (asChild) {\n return (\n <Slot ref={ref} className={classes} {...props}>\n {children}\n </Slot>\n );\n }\n\n // Real content stays in layout (preserving width) but goes invisible while loading.\n // The spinner is absolutely positioned so it never shifts the button's size.\n const content = (\n <>\n <span className={cn('contents', loading && 'invisible')}>\n {leftIcon && <span className=\"inline-flex items-center\">{leftIcon}</span>}\n {children}\n {rightIcon && <span className=\"inline-flex items-center\">{rightIcon}</span>}\n </span>\n {loading && (\n <span className=\"absolute inset-0 inline-flex items-center justify-center text-ods-text-primary\">\n <Spinner />\n </span>\n )}\n </>\n );\n\n // Same `linkProps`-wins-over-href resolution as the splitIcon branch.\n const anchor =\n linkProps ??\n (href\n ? {\n href,\n target: openInNewTab ? ('_blank' as const) : undefined,\n rel: openInNewTab ? ('noopener noreferrer' as const) : undefined,\n onClick: onClick as unknown as React.MouseEventHandler<HTMLAnchorElement> | undefined,\n }\n : null);\n if (anchor) {\n return (\n <Link\n href={anchor.href}\n prefetch={prefetch}\n target={anchor.target}\n rel={anchor.rel}\n // See the splitAnchor branch — keep the accessible name on the\n // anchor render (icon-only link buttons have no text content).\n aria-label={props['aria-label']}\n aria-disabled={isDisabled || undefined}\n tabIndex={isDisabled ? -1 : undefined}\n className={cn(classes, isDisabled && 'pointer-events-none')}\n onClick={anchor.onClick}\n >\n {content}\n </Link>\n );\n }\n\n return (\n <button ref={ref} className={classes} disabled={isDisabled} onClick={onClick} {...props}>\n {content}\n </button>\n );\n});\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants, type ButtonProps };\n","// Shared style atoms for `Button` and `SplitButton`. Extracted to keep a single\n// source of truth for surface colors, outline borders, and split-divider colors.\n\n// Each variant pairs `disabled:` (real `<button disabled>`) with `aria-disabled:`\n// (used for `<Link aria-disabled>` since anchors don't support `:disabled`).\nexport const buttonSurfaceClasses = {\n accent:\n 'bg-ods-accent text-ods-text-on-accent hover:bg-ods-accent-hover active:bg-ods-accent-active disabled:bg-ods-disabled aria-disabled:bg-ods-disabled',\n outline:\n 'bg-ods-card text-ods-text-primary hover:bg-ods-bg-hover active:bg-ods-bg-active disabled:bg-ods-card disabled:text-ods-text-disabled aria-disabled:bg-ods-card aria-disabled:text-ods-text-disabled',\n transparent:\n 'bg-transparent text-ods-text-primary hover:bg-ods-bg-hover active:bg-ods-bg-active disabled:bg-transparent disabled:text-ods-text-disabled aria-disabled:bg-transparent aria-disabled:text-ods-text-disabled',\n destructive:\n 'bg-ods-error text-ods-text-on-accent hover:bg-ods-error-hover active:bg-ods-error-active disabled:bg-ods-disabled aria-disabled:bg-ods-disabled',\n warning:\n 'bg-ods-warning text-ods-text-on-accent hover:bg-ods-warning-hover active:bg-ods-warning-active disabled:bg-ods-disabled aria-disabled:bg-ods-disabled',\n // A self-contained glyph (play badge, unmute glyph) that already carries its\n // own scrim: no button surface at all, in any state. Distinct from\n // `transparent`, whose hover/active fills would paint a rectangle behind the\n // glyph — which is why call sites were undoing them with\n // `hover:bg-transparent active:bg-transparent`.\n glyph:\n 'bg-transparent text-ods-text-primary hover:bg-transparent active:bg-transparent disabled:bg-transparent disabled:text-ods-text-disabled aria-disabled:bg-transparent aria-disabled:text-ods-text-disabled',\n // Chrome that sits ON media (video cards, image lightboxes): a scrim disc so\n // the glyph stays legible over an arbitrary frame. Promoted to a variant\n // because the walkthrough card, its theater and the bite cards were each\n // stacking the same classes at the call site.\n overlay:\n 'rounded-full bg-ods-overlay text-ods-text-primary backdrop-blur-sm hover:text-ods-accent active:text-ods-accent-active disabled:text-ods-text-disabled aria-disabled:text-ods-text-disabled',\n} as const;\n\nexport const outlineBorderClasses =\n 'border border-ods-border hover:border-ods-border-hover active:border-ods-border-active disabled:border-ods-border aria-disabled:border-ods-border';\n\n// Glyph scale for the split-layout button family: 16px below md, 24px from md.\n//\n// Shared because the same page-header action renders through EITHER of the two\n// split layouts depending on its shape — `SplitButton` for two click targets, and\n// `Button` + `splitIcon` for one with a decorative trailing glyph — and the two sit\n// side by side in the same row. They used to disagree: `SplitButton` carried this\n// responsive scale while the `Button` split slots re-declared a flat 20px, so a\n// \"submenu\" action's icons rendered 4px smaller than its neighbour's on desktop.\n// `Button`'s own flat `[&_svg]:h-5` stays as it is for ordinary (non-split) buttons.\nexport const splitGlyphSizeClasses = '[&_svg]:h-4 [&_svg]:w-4 md:[&_svg]:h-6 md:[&_svg]:w-6';\n\n// Per-size glyph scale for `Button`'s split slots AND the loading overlay that\n// covers them, so those two read from ONE place — the overlay sits outside both\n// slots and inherits neither their sizing nor a shell base rule, so without this it\n// would have to restate a number, which is the divergence described above.\n//\n// Scoped to `Button` on purpose: `SplitButton` keeps its own `small` ramp\n// (12px → 16px, vs the flat 16px here) and only shares the `default` step through\n// `splitGlyphSizeClasses`. Aligning `small` too is a visible design change, so it is\n// not folded in here silently.\nexport const splitGlyphSizeBySize = {\n default: splitGlyphSizeClasses,\n small: '[&_svg]:h-4 [&_svg]:w-4',\n} as const;\n\n// Color of the vertical seam between the main and icon halves (split layouts).\nexport const splitDividerColorClasses = {\n accent: 'border-ods-accent-active',\n outline: 'border-ods-border',\n transparent: 'border-ods-border',\n destructive: 'border-ods-error-active',\n warning: 'border-ods-warning-active',\n} as const;\n\nexport type ButtonSurfaceVariant = keyof typeof buttonSurfaceClasses;\n","'use client';\n\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport React from 'react';\nimport Link from '../../../embed-shims/next-link';\nimport { cn } from '../../../utils/cn';\nimport { buttonSurfaceClasses, splitDividerColorClasses, splitGlyphSizeClasses } from './button-styles';\n\n// Two independent interactive halves: each a `<button>` or `<a>`. The seam is\n// a 1px border on the left edge of the icon half, colored per variant. For a\n// single-target variant (decorative trailing icon), use `<Button splitIcon>`.\n\nconst splitHalfBase = [\n 'relative inline-flex items-center justify-center gap-[var(--spacing-system-xsf)]',\n 'whitespace-nowrap transition-colors duration-200',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ods-focus focus-visible:z-10',\n 'disabled:pointer-events-none',\n '[&_svg]:pointer-events-none [&_svg]:shrink-0',\n];\n\nconst splitHalfVariants = cva(splitHalfBase, {\n variants: {\n variant: {\n accent: buttonSurfaceClasses.accent,\n outline: buttonSurfaceClasses.outline, // Outline border lives in compoundVariants so we can omit the seam edge.\n transparent: buttonSurfaceClasses.transparent,\n destructive: buttonSurfaceClasses.destructive,\n warning: buttonSurfaceClasses.warning,\n },\n size: {\n default: `h-10 px-[var(--spacing-system-m)] py-[var(--spacing-system-sf)] text-h3 md:h-12 ${splitGlyphSizeClasses}`,\n small: 'h-6 px-[var(--spacing-system-xs)] text-h5 md:h-8 [&_svg]:h-3 [&_svg]:w-3 md:[&_svg]:h-4 md:[&_svg]:w-4',\n },\n side: { main: '', icon: '' },\n soloOnMobile: { true: '', false: '' },\n },\n compoundVariants: [\n // Rounded corners + per-variant seam. The icon-side's left border is the divider.\n { variant: 'accent', side: 'main', class: 'rounded-l-md' },\n {\n variant: 'accent',\n side: 'icon',\n class: cn(\n 'rounded-r-md border-l',\n splitDividerColorClasses.accent,\n 'disabled:border-ods-disabled aria-disabled:border-ods-disabled',\n ),\n },\n { variant: 'destructive', side: 'main', class: 'rounded-l-md' },\n {\n variant: 'destructive',\n side: 'icon',\n class: cn(\n 'rounded-r-md border-l',\n splitDividerColorClasses.destructive,\n 'disabled:border-ods-disabled aria-disabled:border-ods-disabled',\n ),\n },\n { variant: 'warning', side: 'main', class: 'rounded-l-md' },\n {\n variant: 'warning',\n side: 'icon',\n class: cn(\n 'rounded-r-md border-l',\n splitDividerColorClasses.warning,\n 'disabled:border-ods-disabled aria-disabled:border-ods-disabled',\n ),\n },\n { variant: 'outline', side: 'main', class: 'rounded-l-md border-y border-l border-ods-border' },\n { variant: 'outline', side: 'icon', class: 'rounded-r-md border border-ods-border' },\n { variant: 'transparent', side: 'main', class: 'rounded-md' },\n { variant: 'transparent', side: 'icon', class: cn('rounded-md', splitDividerColorClasses.transparent) },\n\n // Icon half: per Figma, narrower than main height (default: 40×48; small: 32×32).\n { side: 'icon', size: 'default', class: 'w-10 px-0' },\n { side: 'icon', size: 'small', class: 'w-6 px-0 md:w-8' },\n\n { side: 'icon', soloOnMobile: true, class: 'max-md:hidden' },\n { side: 'main', soloOnMobile: true, class: 'max-md:rounded-r-md' },\n { variant: 'outline', side: 'main', soloOnMobile: true, class: 'max-md:border-r' },\n ],\n defaultVariants: { variant: 'accent', size: 'default', side: 'main', soloOnMobile: false },\n});\n\ntype SplitButtonVariant = NonNullable<VariantProps<typeof splitHalfVariants>['variant']>;\ntype SplitButtonSize = NonNullable<VariantProps<typeof splitHalfVariants>['size']>;\n\ninterface SplitButtonIconAction {\n icon: React.ReactNode;\n /** The icon half is interactive but has no visible text — needs an accessible name. */\n 'aria-label': string;\n onClick?: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>;\n href?: string;\n /**\n * Opens `href` with `target=\"_blank\"`. Also marks the half as a new-tab\n * affordance, which hides it below `md` (set it for `onClick` handlers that\n * open a new tab/window themselves).\n */\n openInNewTab?: boolean;\n prefetch?: boolean;\n disabled?: boolean;\n}\n\ninterface SplitButtonProps {\n variant?: SplitButtonVariant;\n size?: SplitButtonSize;\n fullWidth?: boolean;\n className?: string;\n\n children: React.ReactNode;\n onClick?: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>;\n href?: string;\n openInNewTab?: boolean;\n prefetch?: boolean;\n leftIcon?: React.ReactNode;\n rightIcon?: React.ReactNode;\n /** Disables both halves. Equivalent to `mainDisabled && iconAction.disabled`. */\n disabled?: boolean;\n /** Disables only the main half. Combine with `iconAction.disabled` for finer control. */\n mainDisabled?: boolean;\n type?: 'button' | 'submit' | 'reset';\n 'aria-label'?: string;\n groupAriaLabel?: string;\n\n iconAction: SplitButtonIconAction;\n}\n\ninterface HalfOptions {\n variant: SplitButtonVariant;\n size: SplitButtonSize;\n side: 'main' | 'icon';\n soloOnMobile?: boolean;\n href?: string;\n openInNewTab?: boolean;\n prefetch?: boolean;\n onClick?: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>;\n disabled?: boolean;\n /** Stretch this half to fill the group's free space (the icon half stays fixed-width). */\n grow?: boolean;\n type?: 'button' | 'submit' | 'reset';\n ariaLabel?: string;\n children: React.ReactNode;\n}\n\nfunction Half({\n variant,\n size,\n side,\n soloOnMobile,\n href,\n openInNewTab,\n prefetch,\n onClick,\n disabled,\n grow,\n type = 'button',\n ariaLabel,\n children,\n}: HalfOptions) {\n const classes = cn(splitHalfVariants({ variant, size, side, soloOnMobile }), grow && 'flex-1');\n\n if (href) {\n return (\n <Link\n href={href}\n prefetch={prefetch}\n target={openInNewTab ? '_blank' : undefined}\n rel={openInNewTab ? 'noopener noreferrer' : undefined}\n aria-disabled={disabled || undefined}\n tabIndex={disabled ? -1 : undefined}\n aria-label={ariaLabel}\n className={cn(classes, disabled && 'pointer-events-none')}\n onClick={onClick}\n >\n {children}\n </Link>\n );\n }\n\n return (\n <button type={type} className={classes} disabled={disabled} aria-label={ariaLabel} onClick={onClick}>\n {children}\n </button>\n );\n}\n\nconst SplitButton = React.forwardRef<HTMLDivElement, SplitButtonProps>(function SplitButtonImpl(\n {\n variant = 'accent',\n size = 'default',\n fullWidth = false,\n className,\n children,\n onClick,\n href,\n openInNewTab,\n prefetch,\n leftIcon,\n rightIcon,\n disabled,\n mainDisabled,\n type,\n iconAction,\n 'aria-label': ariaLabel,\n groupAriaLabel,\n },\n ref,\n) {\n const soloOnMobile = !!iconAction.openInNewTab;\n\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-label={groupAriaLabel}\n className={cn('inline-flex items-stretch', fullWidth && 'w-full', className)}\n >\n <Half\n variant={variant}\n size={size}\n side=\"main\"\n soloOnMobile={soloOnMobile}\n href={href}\n openInNewTab={openInNewTab}\n prefetch={prefetch}\n onClick={onClick}\n disabled={disabled || mainDisabled}\n grow={fullWidth}\n type={type}\n ariaLabel={ariaLabel}\n >\n {leftIcon && <span className=\"inline-flex items-center\">{leftIcon}</span>}\n <span>{children}</span>\n {rightIcon && <span className=\"inline-flex items-center\">{rightIcon}</span>}\n </Half>\n <Half\n variant={variant}\n size={size}\n side=\"icon\"\n soloOnMobile={soloOnMobile}\n href={iconAction.href}\n openInNewTab={iconAction.openInNewTab}\n prefetch={iconAction.prefetch}\n onClick={iconAction.onClick}\n disabled={disabled || iconAction.disabled}\n ariaLabel={iconAction['aria-label']}\n >\n <span className=\"inline-flex items-center\">{iconAction.icon}</span>\n </Half>\n </div>\n );\n});\nSplitButton.displayName = 'SplitButton';\n\nexport { SplitButton, type SplitButtonProps, type SplitButtonIconAction };\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
UnifiedPagination
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-Z2FZ5HP2.js";
|
|
5
5
|
import {
|
|
6
6
|
cn
|
|
7
7
|
} from "./chunk-4CTHP7E5.js";
|
|
@@ -136,4 +136,4 @@ export {
|
|
|
136
136
|
usePaginationLoading,
|
|
137
137
|
PersistentPaginationWrapper
|
|
138
138
|
};
|
|
139
|
-
//# sourceMappingURL=chunk-
|
|
139
|
+
//# sourceMappingURL=chunk-YLNZPFDW.js.map
|