@flamingo-stack/openframe-frontend-core 0.0.674 → 0.0.675-2435.7306.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.
Files changed (94) hide show
  1. package/dist/{chunk-RSOBME56.js → chunk-2GL6DFLV.js} +2 -2
  2. package/dist/{chunk-PP3N5MN4.cjs → chunk-42GR6UIH.cjs} +3 -3
  3. package/dist/{chunk-PP3N5MN4.cjs.map → chunk-42GR6UIH.cjs.map} +1 -1
  4. package/dist/{chunk-N6CI2E7D.cjs → chunk-5X4JS67G.cjs} +3 -3
  5. package/dist/{chunk-N6CI2E7D.cjs.map → chunk-5X4JS67G.cjs.map} +1 -1
  6. package/dist/{chunk-EGQOPBXC.cjs → chunk-BVYZHKF6.cjs} +3 -3
  7. package/dist/{chunk-EGQOPBXC.cjs.map → chunk-BVYZHKF6.cjs.map} +1 -1
  8. package/dist/{chunk-FUEAXTZE.cjs → chunk-C4YD5MZV.cjs} +4 -4
  9. package/dist/{chunk-FUEAXTZE.cjs.map → chunk-C4YD5MZV.cjs.map} +1 -1
  10. package/dist/{chunk-YVJDVVHY.js → chunk-CXE6WTBZ.js} +5 -2
  11. package/dist/{chunk-YVJDVVHY.js.map → chunk-CXE6WTBZ.js.map} +1 -1
  12. package/dist/{chunk-QZMKKQQN.cjs → chunk-D3LFYXUM.cjs} +13 -13
  13. package/dist/{chunk-QZMKKQQN.cjs.map → chunk-D3LFYXUM.cjs.map} +1 -1
  14. package/dist/{chunk-MRT6DZG5.cjs → chunk-GU5JW5MX.cjs} +36 -36
  15. package/dist/{chunk-MRT6DZG5.cjs.map → chunk-GU5JW5MX.cjs.map} +1 -1
  16. package/dist/{chunk-XBNO42PI.js → chunk-HDNMMUGV.js} +2 -2
  17. package/dist/{chunk-7F73YNDS.cjs → chunk-HQ2ZYL3V.cjs} +4 -4
  18. package/dist/{chunk-7F73YNDS.cjs.map → chunk-HQ2ZYL3V.cjs.map} +1 -1
  19. package/dist/{chunk-UIQQBZLU.cjs → chunk-I3QQALKQ.cjs} +33 -33
  20. package/dist/{chunk-UIQQBZLU.cjs.map → chunk-I3QQALKQ.cjs.map} +1 -1
  21. package/dist/{chunk-XYZQXHAX.js → chunk-J24SZNH4.js} +4 -4
  22. package/dist/{chunk-CHKIZRUP.cjs → chunk-JB4ZALJS.cjs} +18 -18
  23. package/dist/{chunk-CHKIZRUP.cjs.map → chunk-JB4ZALJS.cjs.map} +1 -1
  24. package/dist/{chunk-M76D6OJZ.js → chunk-KB7YLZAC.js} +5 -5
  25. package/dist/{chunk-OAQROGFN.cjs → chunk-KFWDLZGL.cjs} +51 -51
  26. package/dist/{chunk-OAQROGFN.cjs.map → chunk-KFWDLZGL.cjs.map} +1 -1
  27. package/dist/{chunk-GJTLUW2H.js → chunk-LD76LMKM.js} +2 -2
  28. package/dist/{chunk-UYPICURQ.js → chunk-LPEFFJXX.js} +2 -2
  29. package/dist/{chunk-TWQWCOJ7.cjs → chunk-N24SOKQI.cjs} +17 -17
  30. package/dist/{chunk-TWQWCOJ7.cjs.map → chunk-N24SOKQI.cjs.map} +1 -1
  31. package/dist/{chunk-PXWMRXVI.js → chunk-OS3NLEV5.js} +5 -5
  32. package/dist/{chunk-BQICLH4C.js → chunk-PARUDSVT.js} +4 -4
  33. package/dist/{chunk-QO4RASGC.js → chunk-PSF37OWZ.js} +2 -2
  34. package/dist/{chunk-TECYEWVQ.js → chunk-Q3MTPDK4.js} +2 -2
  35. package/dist/{chunk-MMOXFVQN.js → chunk-SYTU64CK.js} +2 -2
  36. package/dist/{chunk-G7HMYIDN.js → chunk-TS4HBJNA.js} +2 -2
  37. package/dist/{chunk-EJZV4QGU.cjs → chunk-VZMST7BD.cjs} +111 -108
  38. package/dist/chunk-VZMST7BD.cjs.map +1 -0
  39. package/dist/{chunk-HN7KNVKL.cjs → chunk-WYACK3N7.cjs} +3 -3
  40. package/dist/{chunk-HN7KNVKL.cjs.map → chunk-WYACK3N7.cjs.map} +1 -1
  41. package/dist/{chunk-L7PO6NSD.cjs → chunk-XJMADFIK.cjs} +10 -10
  42. package/dist/{chunk-L7PO6NSD.cjs.map → chunk-XJMADFIK.cjs.map} +1 -1
  43. package/dist/{chunk-NRHEKFPG.js → chunk-ZI3E5SSW.js} +2 -2
  44. package/dist/{chunk-4Q6P3VHS.cjs → chunk-ZYVMSJFU.cjs} +17 -17
  45. package/dist/{chunk-4Q6P3VHS.cjs.map → chunk-ZYVMSJFU.cjs.map} +1 -1
  46. package/dist/{chunk-EPKQTPNJ.js → chunk-ZZOZZJPK.js} +3 -3
  47. package/dist/components/case-studies/index.cjs +11 -11
  48. package/dist/components/case-studies/index.js +2 -2
  49. package/dist/components/contact/index.cjs +3 -3
  50. package/dist/components/contact/index.js +2 -2
  51. package/dist/components/docs/index.cjs +6 -6
  52. package/dist/components/docs/index.js +5 -5
  53. package/dist/components/embeds/index.cjs +3 -3
  54. package/dist/components/embeds/index.js +2 -2
  55. package/dist/components/faq/index.cjs +3 -3
  56. package/dist/components/faq/index.js +2 -2
  57. package/dist/components/features/index.cjs +2 -2
  58. package/dist/components/features/index.js +1 -1
  59. package/dist/components/features/walkthrough-video.d.ts +6 -0
  60. package/dist/components/features/walkthrough-video.d.ts.map +1 -1
  61. package/dist/components/help-center-pages/index.cjs +49 -49
  62. package/dist/components/help-center-pages/index.js +13 -13
  63. package/dist/components/index.cjs +31 -31
  64. package/dist/components/index.js +12 -12
  65. package/dist/components/meeting-scheduler/index.cjs +21 -21
  66. package/dist/components/meeting-scheduler/index.js +1 -1
  67. package/dist/components/navigation/index.cjs +5 -5
  68. package/dist/components/navigation/index.js +4 -4
  69. package/dist/components/onboarding-guides/index.cjs +5 -5
  70. package/dist/components/onboarding-guides/index.js +4 -4
  71. package/dist/components/tickets/index.cjs +6 -6
  72. package/dist/components/tickets/index.js +5 -5
  73. package/dist/components/ui/index.cjs +2 -2
  74. package/dist/components/ui/index.js +1 -1
  75. package/dist/index.cjs +6 -6
  76. package/dist/index.js +5 -5
  77. package/package.json +1 -1
  78. package/src/components/features/__tests__/walkthrough-video-autoplay-card.test.tsx +89 -0
  79. package/src/components/features/walkthrough-video.tsx +12 -1
  80. package/dist/chunk-EJZV4QGU.cjs.map +0 -1
  81. /package/dist/{chunk-RSOBME56.js.map → chunk-2GL6DFLV.js.map} +0 -0
  82. /package/dist/{chunk-XBNO42PI.js.map → chunk-HDNMMUGV.js.map} +0 -0
  83. /package/dist/{chunk-XYZQXHAX.js.map → chunk-J24SZNH4.js.map} +0 -0
  84. /package/dist/{chunk-M76D6OJZ.js.map → chunk-KB7YLZAC.js.map} +0 -0
  85. /package/dist/{chunk-GJTLUW2H.js.map → chunk-LD76LMKM.js.map} +0 -0
  86. /package/dist/{chunk-UYPICURQ.js.map → chunk-LPEFFJXX.js.map} +0 -0
  87. /package/dist/{chunk-PXWMRXVI.js.map → chunk-OS3NLEV5.js.map} +0 -0
  88. /package/dist/{chunk-BQICLH4C.js.map → chunk-PARUDSVT.js.map} +0 -0
  89. /package/dist/{chunk-QO4RASGC.js.map → chunk-PSF37OWZ.js.map} +0 -0
  90. /package/dist/{chunk-TECYEWVQ.js.map → chunk-Q3MTPDK4.js.map} +0 -0
  91. /package/dist/{chunk-MMOXFVQN.js.map → chunk-SYTU64CK.js.map} +0 -0
  92. /package/dist/{chunk-G7HMYIDN.js.map → chunk-TS4HBJNA.js.map} +0 -0
  93. /package/dist/{chunk-NRHEKFPG.js.map → chunk-ZI3E5SSW.js.map} +0 -0
  94. /package/dist/{chunk-EPKQTPNJ.js.map → chunk-ZZOZZJPK.js.map} +0 -0
@@ -4,7 +4,7 @@
4
4
 
5
5
 
6
6
 
7
- var _chunkEJZV4QGUcjs = require('./chunk-EJZV4QGU.cjs');
7
+ var _chunkVZMST7BDcjs = require('./chunk-VZMST7BD.cjs');
8
8
 
9
9
 
10
10
  var _chunkRCLYHHB3cjs = require('./chunk-RCLYHHB3.cjs');
@@ -124,7 +124,7 @@ CveLink.displayName = "CveLink";
124
124
  // src/components/platform/ToolBadge.tsx
125
125
 
126
126
  var ToolBadge = ({ toolType, className, iconClassName }) => {
127
- const label = _chunkEJZV4QGUcjs.getToolLabel.call(void 0, toolType);
127
+ const label = _chunkVZMST7BDcjs.getToolLabel.call(void 0, toolType);
128
128
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkX7CEWD6Vcjs.cn.call(void 0, "flex items-center gap-1 text-ods-text-secondary", className), children: [
129
129
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkILAHSBZIcjs.ToolIcon, { toolType, className: iconClassName, size: 16 }),
130
130
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-ods-text-primary text-h4", children: label })
@@ -135,31 +135,31 @@ ToolBadge.displayName = "ToolBadge";
135
135
  // src/components/platform/ShellTypeBadge.tsx
136
136
 
137
137
  var shellIconMap = {
138
- [_chunkEJZV4QGUcjs.ShellTypeValues.POWERSHELL]: {
138
+ [_chunkVZMST7BDcjs.ShellTypeValues.POWERSHELL]: {
139
139
  icon: _chunkOIDKQ77Rcjs.PowershellLogoGreyIcon,
140
140
  props: { size: 16, className: "text-ods-text-secondary" }
141
141
  },
142
- [_chunkEJZV4QGUcjs.ShellTypeValues.CMD]: {
142
+ [_chunkVZMST7BDcjs.ShellTypeValues.CMD]: {
143
143
  icon: _chunk5R4QMTMLcjs.CmdIcon,
144
144
  props: { size: 16, color: "var(--color-text-secondary)" }
145
145
  },
146
- [_chunkEJZV4QGUcjs.ShellTypeValues.BASH]: {
146
+ [_chunkVZMST7BDcjs.ShellTypeValues.BASH]: {
147
147
  icon: _chunk5R4QMTMLcjs.BashIcon,
148
148
  props: { size: 16, color: "var(--color-text-secondary)" }
149
149
  },
150
- [_chunkEJZV4QGUcjs.ShellTypeValues.PYTHON]: {
150
+ [_chunkVZMST7BDcjs.ShellTypeValues.PYTHON]: {
151
151
  icon: _chunkOIDKQ77Rcjs.PythonLogoIcon,
152
152
  props: { size: 16, className: "text-ods-text-secondary" }
153
153
  },
154
- [_chunkEJZV4QGUcjs.ShellTypeValues.NUSHELL]: {
154
+ [_chunkVZMST7BDcjs.ShellTypeValues.NUSHELL]: {
155
155
  icon: _chunk5R4QMTMLcjs.NushellIcon,
156
156
  props: { size: 16, color: "var(--color-text-secondary)" }
157
157
  },
158
- [_chunkEJZV4QGUcjs.ShellTypeValues.DENO]: {
158
+ [_chunkVZMST7BDcjs.ShellTypeValues.DENO]: {
159
159
  icon: _chunk5R4QMTMLcjs.DenoIcon,
160
160
  props: { size: 16, color: "var(--color-text-secondary)" }
161
161
  },
162
- [_chunkEJZV4QGUcjs.ShellTypeValues.SHELL]: {
162
+ [_chunkVZMST7BDcjs.ShellTypeValues.SHELL]: {
163
163
  icon: _chunk5R4QMTMLcjs.ShellIcon,
164
164
  props: { size: 16, color: "var(--color-text-secondary)" }
165
165
  }
@@ -170,7 +170,7 @@ var defaultIconConfig = {
170
170
  };
171
171
  var ShellTypeBadge = ({ shellType, className, iconClassName }) => {
172
172
  const normalizedType = _optionalChain([shellType, 'optionalAccess', _ => _.toUpperCase, 'call', _2 => _2()]);
173
- const label = _chunkEJZV4QGUcjs.getShellLabel.call(void 0, normalizedType);
173
+ const label = _chunkVZMST7BDcjs.getShellLabel.call(void 0, normalizedType);
174
174
  const { icon: IconComponent, props: iconProps } = _nullishCoalesce(shellIconMap[normalizedType], () => ( defaultIconConfig));
175
175
  const defaultIconClassName = "className" in iconProps ? iconProps.className : void 0;
176
176
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkX7CEWD6Vcjs.cn.call(void 0, "flex items-center gap-1", className), children: [
@@ -186,7 +186,7 @@ function formatSupportedPlatforms(platforms) {
186
186
  if (!platforms || platforms.length === 0) {
187
187
  return "All Platforms";
188
188
  }
189
- return platforms.map((platform) => _chunkEJZV4QGUcjs.getOSLabel.call(void 0, platform)).join(", ");
189
+ return platforms.map((platform) => _chunkVZMST7BDcjs.getOSLabel.call(void 0, platform)).join(", ");
190
190
  }
191
191
  function InfoCell({ label, value, avatar, className }) {
192
192
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkX7CEWD6Vcjs.cn.call(void 0, "flex min-w-0 items-center gap-2", className), children: [
@@ -206,7 +206,7 @@ var ScriptInfoSection = ({
206
206
  author,
207
207
  className
208
208
  }) => {
209
- const shellLabel = _chunkEJZV4QGUcjs.getShellLabel.call(void 0, shellType);
209
+ const shellLabel = _chunkVZMST7BDcjs.getShellLabel.call(void 0, shellType);
210
210
  const platformsLabel = formatSupportedPlatforms(supportedPlatforms);
211
211
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkX7CEWD6Vcjs.cn.call(void 0, "overflow-hidden rounded-[6px] border border-ods-border bg-ods-card", className), children: [
212
212
  /* @__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: [
@@ -558,4 +558,4 @@ function OnboardingWalkthrough({
558
558
 
559
559
 
560
560
  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;
561
- //# sourceMappingURL=chunk-QZMKKQQN.cjs.map
561
+ //# sourceMappingURL=chunk-D3LFYXUM.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-QZMKKQQN.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-QZMKKQQN.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 { nameInitials } from '../../utils/format';\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 * 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 || nameInitials(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 { LockIcon, PlusCircleIcon } from '../icons-v2-generated';\nimport { Button } from '../ui/button';\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\n\n/**\n * What an untouched stored secret shows in its value field.\n *\n * Rendered as the field's PLACEHOLDER, never as its value: a mask held in\n * `value` is indistinguishable from something the user typed, and would be\n * submitted back as the secret itself.\n */\nconst SECRET_MASK = '**********';\n\nconst STORED_SECRET_KEY_HINT = \"A stored secret can't be renamed — delete it and add a new one\";\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 * A secret pair: the key carries a lock and the value is typed as a password.\n * Meaningful for environment variables only.\n */\n secret?: boolean;\n /**\n * The server holds a value for this secret and does not send it back. While\n * `value` is empty the field shows a mask, so empty means \"keep what is\n * stored\" and typing replaces it.\n *\n * The stored value is bound to the key, which is therefore read-only:\n * renaming would leave the old name holding the secret and the new one\n * holding nothing.\n */\n hasStoredValue?: boolean;\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 /** Label for a second add button that appends a secret pair. Omit to not offer secrets. */\n addSecretButtonLabel?: 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 addSecretButtonLabel,\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 = (secret = false) => {\n if (!onArgumentsChange) return;\n const newArg: ScriptArgument = {\n id: crypto.randomUUID(),\n key: '',\n value: '',\n // Only set on a secret, so a plain pair keeps the shape it always had.\n ...(secret && { secret: true }),\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 const isStoredSecret = Boolean(arg.secret && arg.hasStoredValue);\n // The mask stands for the stored value, so it goes once the user types a replacement.\n const showsMask = isStoredSecret && !arg.value;\n\n return (\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 readOnly={isStoredSecret}\n title={isStoredSecret ? STORED_SECRET_KEY_HINT : undefined}\n startAdornment={arg.secret ? <LockIcon role=\"img\" aria-label=\"Secret\" /> : undefined}\n />\n </div>\n\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 // `new-password` keeps a password manager from filling a saved login into a secret.\n type={arg.secret ? 'password' : undefined}\n autoComplete={arg.secret ? 'new-password' : undefined}\n value={arg.value}\n onChange={e => handleValueChange(arg.id, e.target.value)}\n placeholder={showsMask ? SECRET_MASK : valuePlaceholder}\n disabled={disabled}\n className={cn(\n !arg.value && 'placeholder:text-ods-text-muted',\n // The mask reads as a value that is there, not as a prompt to fill one in.\n showsMask && '[&_input]:placeholder:text-ods-text-primary',\n )}\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\n {/* Add buttons - aligned left */}\n <div className=\"flex flex-wrap justify-start gap-[var(--spacing-system-xs)]\">\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 {addSecretButtonLabel && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"small\"\n onClick={() => handleAdd(true)}\n disabled={disabled}\n className=\"self-start\"\n leftIcon={<LockIcon className=\"text-ods-text-secondary\" />}\n >\n {addSecretButtonLabel}\n </Button>\n )}\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-D3LFYXUM.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-D3LFYXUM.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 { nameInitials } from '../../utils/format';\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 * 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 || nameInitials(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 { LockIcon, PlusCircleIcon } from '../icons-v2-generated';\nimport { Button } from '../ui/button';\nimport { Input } from '../ui/input';\nimport { Label } from '../ui/label';\n\n/**\n * What an untouched stored secret shows in its value field.\n *\n * Rendered as the field's PLACEHOLDER, never as its value: a mask held in\n * `value` is indistinguishable from something the user typed, and would be\n * submitted back as the secret itself.\n */\nconst SECRET_MASK = '**********';\n\nconst STORED_SECRET_KEY_HINT = \"A stored secret can't be renamed — delete it and add a new one\";\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 * A secret pair: the key carries a lock and the value is typed as a password.\n * Meaningful for environment variables only.\n */\n secret?: boolean;\n /**\n * The server holds a value for this secret and does not send it back. While\n * `value` is empty the field shows a mask, so empty means \"keep what is\n * stored\" and typing replaces it.\n *\n * The stored value is bound to the key, which is therefore read-only:\n * renaming would leave the old name holding the secret and the new one\n * holding nothing.\n */\n hasStoredValue?: boolean;\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 /** Label for a second add button that appends a secret pair. Omit to not offer secrets. */\n addSecretButtonLabel?: 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 addSecretButtonLabel,\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 = (secret = false) => {\n if (!onArgumentsChange) return;\n const newArg: ScriptArgument = {\n id: crypto.randomUUID(),\n key: '',\n value: '',\n // Only set on a secret, so a plain pair keeps the shape it always had.\n ...(secret && { secret: true }),\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 const isStoredSecret = Boolean(arg.secret && arg.hasStoredValue);\n // The mask stands for the stored value, so it goes once the user types a replacement.\n const showsMask = isStoredSecret && !arg.value;\n\n return (\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 readOnly={isStoredSecret}\n title={isStoredSecret ? STORED_SECRET_KEY_HINT : undefined}\n startAdornment={arg.secret ? <LockIcon role=\"img\" aria-label=\"Secret\" /> : undefined}\n />\n </div>\n\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 // `new-password` keeps a password manager from filling a saved login into a secret.\n type={arg.secret ? 'password' : undefined}\n autoComplete={arg.secret ? 'new-password' : undefined}\n value={arg.value}\n onChange={e => handleValueChange(arg.id, e.target.value)}\n placeholder={showsMask ? SECRET_MASK : valuePlaceholder}\n disabled={disabled}\n className={cn(\n !arg.value && 'placeholder:text-ods-text-muted',\n // The mask reads as a value that is there, not as a prompt to fill one in.\n showsMask && '[&_input]:placeholder:text-ods-text-primary',\n )}\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\n {/* Add buttons - aligned left */}\n <div className=\"flex flex-wrap justify-start gap-[var(--spacing-system-xs)]\">\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 {addSecretButtonLabel && (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"small\"\n onClick={() => handleAdd(true)}\n disabled={disabled}\n className=\"self-start\"\n leftIcon={<LockIcon className=\"text-ods-text-secondary\" />}\n >\n {addSecretButtonLabel}\n </Button>\n )}\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"]}
@@ -5,13 +5,13 @@ var _chunkWKX7DYFMcjs = require('./chunk-WKX7DYFM.cjs');
5
5
 
6
6
 
7
7
 
8
- var _chunkL7PO6NSDcjs = require('./chunk-L7PO6NSD.cjs');
8
+ var _chunkXJMADFIKcjs = require('./chunk-XJMADFIK.cjs');
9
9
 
10
10
 
11
11
  var _chunk77BLJHKIcjs = require('./chunk-77BLJHKI.cjs');
12
12
 
13
13
 
14
- var _chunkPP3N5MN4cjs = require('./chunk-PP3N5MN4.cjs');
14
+ var _chunk42GR6UIHcjs = require('./chunk-42GR6UIH.cjs');
15
15
 
16
16
 
17
17
  var _chunkDOVVKQMZcjs = require('./chunk-DOVVKQMZ.cjs');
@@ -30,7 +30,7 @@ var _chunkDOVVKQMZcjs = require('./chunk-DOVVKQMZ.cjs');
30
30
 
31
31
 
32
32
 
33
- var _chunkEJZV4QGUcjs = require('./chunk-EJZV4QGU.cjs');
33
+ var _chunkVZMST7BDcjs = require('./chunk-VZMST7BD.cjs');
34
34
 
35
35
 
36
36
 
@@ -89,8 +89,8 @@ var _chunkX7CEWD6Vcjs = require('./chunk-X7CEWD6V.cjs');
89
89
  // src/components/shared/product-release/product-releases-view.tsx
90
90
  var _jsxruntime = require('react/jsx-runtime');
91
91
  var DEFAULT_ENDPOINT = "/api/releases";
92
- var DEFAULT_SEARCH_PARAM_KEY = _chunkEJZV4QGUcjs.DEV_SECTION_PARAM_KEYS.search;
93
- var DEFAULT_STATUS_PARAM_KEY = _chunkEJZV4QGUcjs.DEV_SECTION_PARAM_KEYS.releaseStatus;
92
+ var DEFAULT_SEARCH_PARAM_KEY = _chunkVZMST7BDcjs.DEV_SECTION_PARAM_KEYS.search;
93
+ var DEFAULT_STATUS_PARAM_KEY = _chunkVZMST7BDcjs.DEV_SECTION_PARAM_KEYS.releaseStatus;
94
94
  var DEFAULT_PAGE_PARAM_KEY = "page";
95
95
  function ReleaseRow({
96
96
  release,
@@ -99,7 +99,7 @@ function ReleaseRow({
99
99
  }) {
100
100
  const runtime = _chunkU2YLMFJKcjs.useChatRuntime.call(void 0, );
101
101
  const router = _chunkSADRZ4YIcjs.useRouter.call(void 0, );
102
- const cta = _chunkEJZV4QGUcjs.resolveContentHref.call(void 0, _optionalChain([runtime, 'optionalAccess', _2 => _2.composeContentUrl]), {
102
+ const cta = _chunkVZMST7BDcjs.resolveContentHref.call(void 0, _optionalChain([runtime, 'optionalAccess', _2 => _2.composeContentUrl]), {
103
103
  type: "product_release",
104
104
  slug: release.slug,
105
105
  basePath,
@@ -171,10 +171,10 @@ function ProductReleasesView({
171
171
  router.replace(`${pathname}?${params.toString()}`, { scroll: false });
172
172
  };
173
173
  if (error) {
174
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _chunkX7CEWD6Vcjs.cn.call(void 0, "w-full", className), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEJZV4QGUcjs.LoadError, { message: "Failed to load releases.", onRetry: reload }) });
174
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _chunkX7CEWD6Vcjs.cn.call(void 0, "w-full", className), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVZMST7BDcjs.LoadError, { message: "Failed to load releases.", onRetry: reload }) });
175
175
  }
176
176
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _chunkX7CEWD6Vcjs.cn.call(void 0, "flex w-full flex-col gap-[40px]", className), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-h-[600px]", children: showEmpty ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-[600px] items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
177
- _chunkL7PO6NSDcjs.ListEmptyState,
177
+ _chunkXJMADFIKcjs.ListEmptyState,
178
178
  {
179
179
  isFiltered: hasActiveFilters,
180
180
  filtered: {
@@ -269,7 +269,7 @@ function MediaGalleryStrip({ items, className }) {
269
269
  var _lucidereact = require('lucide-react');
270
270
 
271
271
 
272
- var DefaultMarkdownRenderer = _chunkEJZV4QGUcjs.RichMarkdownRenderer;
272
+ var DefaultMarkdownRenderer = _chunkVZMST7BDcjs.RichMarkdownRenderer;
273
273
  var DEFAULT_ENDPOINT2 = "/api/releases";
274
274
  function ReleaseDetailPage({
275
275
  authorHref,
@@ -288,7 +288,7 @@ function ReleaseDetailPage({
288
288
  }) {
289
289
  const router = _chunkSADRZ4YIcjs.useRouter.call(void 0, );
290
290
  const captions = _chunk4J7CFT6Dcjs.useCaptions.call(void 0, );
291
- const renderShell = (node) => shell ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEJZV4QGUcjs.PageShell, { children: node }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "page-shell-content", children: node });
291
+ const renderShell = (node) => shell ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVZMST7BDcjs.PageShell, { children: node }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "page-shell-content", children: node });
292
292
  const seed = initialData == null ? void 0 : initialData;
293
293
  const {
294
294
  data: release,
@@ -347,7 +347,7 @@ function ReleaseDetailPage({
347
347
  return renderShell(
348
348
  // Match the loaded page's top offset (TitleBlock's
349
349
  // `pt-[var(--spacing-system-l)]`) so content doesn't jump on load.
350
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pt-[var(--spacing-system-l)]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkPP3N5MN4cjs.DetailPageSkeleton, { bare: true, metadataColumns: 4, showImageGallery: true }) })
350
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pt-[var(--spacing-system-l)]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk42GR6UIHcjs.DetailPageSkeleton, { bare: true, metadataColumns: 4, showImageGallery: true }) })
351
351
  );
352
352
  }
353
353
  if (error || !release) {
@@ -386,7 +386,7 @@ function ReleaseDetailPage({
386
386
  const improvements = release.improvements;
387
387
  return renderShell(
388
388
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
389
- _chunkEJZV4QGUcjs.PageLayout,
389
+ _chunkVZMST7BDcjs.PageLayout,
390
390
  {
391
391
  title: releaseTitle,
392
392
  subtitle: `Version: ${releaseVersion}`,
@@ -395,7 +395,7 @@ function ReleaseDetailPage({
395
395
  backButton: showBackButton ? { label: backLabel, onClick: () => router.push(backHref) } : void 0,
396
396
  children: [
397
397
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-6 md:space-y-8", children: [
398
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEJZV4QGUcjs.EntityTagBadges, { tags: release.product_release_tags }),
398
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVZMST7BDcjs.EntityTagBadges, { tags: release.product_release_tags }),
399
399
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "grid w-full grid-cols-1 overflow-hidden rounded-md border border-ods-border md:grid-cols-4", children: [
400
400
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex flex-col gap-3 border-b border-ods-border bg-ods-card p-4 md:border-b-0 md:border-r", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-0", children: [
401
401
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-ods-text-primary text-h4", children: releaseType.toLocaleUpperCase() }),
@@ -466,7 +466,7 @@ function ReleaseDetailPage({
466
466
  ] })
467
467
  ] }) }) }),
468
468
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
469
- _chunkEJZV4QGUcjs.ReleaseChangelogSection,
469
+ _chunkVZMST7BDcjs.ReleaseChangelogSection,
470
470
  {
471
471
  title: "Breaking Changes",
472
472
  entries: breakingChanges || [],
@@ -477,7 +477,7 @@ function ReleaseDetailPage({
477
477
  }
478
478
  ),
479
479
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
480
- _chunkEJZV4QGUcjs.ReleaseChangelogSection,
480
+ _chunkVZMST7BDcjs.ReleaseChangelogSection,
481
481
  {
482
482
  title: "Features Added",
483
483
  entries: featuresAdded || [],
@@ -487,7 +487,7 @@ function ReleaseDetailPage({
487
487
  }
488
488
  ),
489
489
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
490
- _chunkEJZV4QGUcjs.ReleaseChangelogSection,
490
+ _chunkVZMST7BDcjs.ReleaseChangelogSection,
491
491
  {
492
492
  title: "Bugs Fixed",
493
493
  entries: bugFixed || [],
@@ -497,7 +497,7 @@ function ReleaseDetailPage({
497
497
  }
498
498
  ),
499
499
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
500
- _chunkEJZV4QGUcjs.ReleaseChangelogSection,
500
+ _chunkVZMST7BDcjs.ReleaseChangelogSection,
501
501
  {
502
502
  title: "Improvements",
503
503
  entries: improvements || [],
@@ -523,7 +523,7 @@ function ReleaseDetailPage({
523
523
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "tracking-[-0.28px] text-ods-text-secondary text-h5", children: "Related Enhancements and Bug-fixes" }),
524
524
  (() => {
525
525
  const deliveryCount = deliveryData ? deliveryData.completed.length + deliveryData.inProgress.length : 0;
526
- return deliveryLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DeliverySection, { data: deliveryData, isLoading: deliveryLoading }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEJZV4QGUcjs.FadePreview, { hiddenCount: deliveryCount - 1, collapsedHeight: 300, resetKey: deliveryCount, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "space-y-4", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DeliverySection, { data: deliveryData, isLoading: false }) }) });
526
+ return deliveryLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DeliverySection, { data: deliveryData, isLoading: deliveryLoading }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVZMST7BDcjs.FadePreview, { hiddenCount: deliveryCount - 1, collapsedHeight: 300, resetKey: deliveryCount, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "space-y-4", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DeliverySection, { data: deliveryData, isLoading: false }) }) });
527
527
  })()
528
528
  ] }),
529
529
  (_optionalChain([githubReleases, 'optionalAccess', _10 => _10.length]) || _optionalChain([knowledgeBaseLinks, 'optionalAccess', _11 => _11.length]) || migrationGuideUrl || documentationUrl) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "w-full space-y-1", children: [
@@ -602,7 +602,7 @@ function ReleaseDetailPage({
602
602
  // src/components/shared/product-release/release-detail-skeleton.tsx
603
603
 
604
604
  function ReleaseDetailSkeleton() {
605
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkPP3N5MN4cjs.DetailPageSkeleton, { metadataColumns: 4, showImageGallery: true });
605
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk42GR6UIHcjs.DetailPageSkeleton, { metadataColumns: 4, showImageGallery: true });
606
606
  }
607
607
 
608
608
  // src/components/shared/roadmap/use-roadmap-voting.ts
@@ -777,7 +777,7 @@ function RoadmapGridSingle({
777
777
  _chunkQRUW4UXBcjs.RoadmapCard,
778
778
  {
779
779
  item,
780
- id: _chunkEJZV4QGUcjs.devSectionAnchorId.call(void 0, "roadmap", item.id),
780
+ id: _chunkVZMST7BDcjs.devSectionAnchorId.call(void 0, "roadmap", item.id),
781
781
  userVote: getVote(item.id),
782
782
  onVote: (voteType) => onVote(item.id, voteType),
783
783
  isVoting: votingTasks.has(item.id)
@@ -893,7 +893,7 @@ function RoadmapGrid({
893
893
  );
894
894
  }
895
895
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
896
- _chunkEJZV4QGUcjs.Accordion,
896
+ _chunkVZMST7BDcjs.Accordion,
897
897
  {
898
898
  type: "multiple",
899
899
  value: expandedQuarters,
@@ -903,13 +903,13 @@ function RoadmapGrid({
903
903
  const itemCount = _optionalChain([itemsByQuarter, 'access', _20 => _20[quarter], 'optionalAccess', _21 => _21.length]) || 0;
904
904
  const isExpanded = expandedQuarters.includes(quarter);
905
905
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
906
- _chunkEJZV4QGUcjs.AccordionItem,
906
+ _chunkVZMST7BDcjs.AccordionItem,
907
907
  {
908
908
  value: quarter,
909
909
  id: `quarter-${quarter.replace(/\s+/g, "-").toLowerCase()}`,
910
910
  className: "border-0",
911
911
  children: [
912
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEJZV4QGUcjs.AccordionTrigger, { className: "w-full p-0 hover:no-underline [&>svg]:ml-auto [&>svg]:h-5 [&>svg]:w-5 [&>svg]:shrink-0 [&>svg]:text-ods-text-secondary", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3", children: [
912
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVZMST7BDcjs.AccordionTrigger, { className: "w-full p-0 hover:no-underline [&>svg]:ml-auto [&>svg]:h-5 [&>svg]:w-5 [&>svg]:shrink-0 [&>svg]:text-ods-text-secondary", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3", children: [
913
913
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
914
914
  "h3",
915
915
  {
@@ -939,7 +939,7 @@ function RoadmapGrid({
939
939
  }
940
940
  )
941
941
  ] }) }),
942
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEJZV4QGUcjs.AccordionContent, { className: "overflow-hidden pb-0 pt-4 data-[state=closed]:animate-none data-[state=open]:animate-none", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
942
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVZMST7BDcjs.AccordionContent, { className: "overflow-hidden pb-0 pt-4 data-[state=closed]:animate-none data-[state=open]:animate-none", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
943
943
  RoadmapGridSingle,
944
944
  {
945
945
  items: itemsByQuarter[quarter],
@@ -991,8 +991,8 @@ function RoadmapGridSkeleton({ count = 4, showLeftMargin = true }) {
991
991
 
992
992
 
993
993
  var DEFAULT_ENDPOINT3 = "/api/roadmap";
994
- var DEFAULT_SEARCH_PARAM_KEY2 = _chunkEJZV4QGUcjs.DEV_SECTION_PARAM_KEYS.search;
995
- var DEFAULT_STATUS_PARAM_KEY2 = _chunkEJZV4QGUcjs.DEV_SECTION_PARAM_KEYS.status;
994
+ var DEFAULT_SEARCH_PARAM_KEY2 = _chunkVZMST7BDcjs.DEV_SECTION_PARAM_KEYS.search;
995
+ var DEFAULT_STATUS_PARAM_KEY2 = _chunkVZMST7BDcjs.DEV_SECTION_PARAM_KEYS.status;
996
996
  function RoadmapView({
997
997
  endpoint = DEFAULT_ENDPOINT3,
998
998
  initialItems,
@@ -1015,7 +1015,7 @@ function RoadmapView({
1015
1015
  const items = _nullishCoalesce(_optionalChain([data, 'optionalAccess', _22 => _22.items]), () => ( []));
1016
1016
  _chunkRCLYHHB3cjs.useScrollToHash.call(void 0, data, { headerOffset: _chunkILAHSBZIcjs.STICKY_HEADER_OFFSET_PX });
1017
1017
  if (error) {
1018
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEJZV4QGUcjs.LoadError, { message: "Failed to load roadmap.", onRetry: reload });
1018
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVZMST7BDcjs.LoadError, { message: "Failed to load roadmap.", onRetry: reload });
1019
1019
  }
1020
1020
  if (isLoading && !data) {
1021
1021
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RoadmapGridSkeleton, { showLeftMargin });
@@ -1068,7 +1068,7 @@ function DeliveryTable({ items, isLoading = false }) {
1068
1068
  // → `#delivery-<external_id>`; `useScrollToHash` in
1069
1069
  // `delivery-lists.tsx` finds the row by id and scrolls. The
1070
1070
  // outer wrapper here ONLY exists for the row separators.
1071
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "border-b border-ods-border last:border-b-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkL7PO6NSDcjs.DeliveryRow, { item, id: _chunkEJZV4QGUcjs.devSectionAnchorId.call(void 0, "delivery", item.id) }) }, item.id)
1071
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "border-b border-ods-border last:border-b-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXJMADFIKcjs.DeliveryRow, { item, id: _chunkVZMST7BDcjs.devSectionAnchorId.call(void 0, "delivery", item.id) }) }, item.id)
1072
1072
  )) }) });
1073
1073
  }
1074
1074
 
@@ -1077,8 +1077,8 @@ function DeliveryTable({ items, isLoading = false }) {
1077
1077
 
1078
1078
  var DEFAULT_COMPLETED_ENDPOINT = "/api/delivery/completed";
1079
1079
  var DEFAULT_IN_PROGRESS_ENDPOINT = "/api/delivery/in-progress";
1080
- var DEFAULT_SEARCH_PARAM_KEY3 = _chunkEJZV4QGUcjs.DEV_SECTION_PARAM_KEYS.search;
1081
- var DEFAULT_TASK_TYPE_PARAM_KEY = _chunkEJZV4QGUcjs.DEV_SECTION_PARAM_KEYS.deliveryTaskType;
1080
+ var DEFAULT_SEARCH_PARAM_KEY3 = _chunkVZMST7BDcjs.DEV_SECTION_PARAM_KEYS.search;
1081
+ var DEFAULT_TASK_TYPE_PARAM_KEY = _chunkVZMST7BDcjs.DEV_SECTION_PARAM_KEYS.deliveryTaskType;
1082
1082
  function DeliveryLists({
1083
1083
  completedApiEndpoint = DEFAULT_COMPLETED_ENDPOINT,
1084
1084
  inProgressApiEndpoint = DEFAULT_IN_PROGRESS_ENDPOINT,
@@ -1145,11 +1145,11 @@ function DeliveryLists({
1145
1145
  const hasActiveFilters = searchQuery !== "" || taskTypeFilter !== "all";
1146
1146
  const hasResults = showCompleted && filteredCompleted.length > 0 || showInProgress && filteredInProgress.length > 0;
1147
1147
  if (error) {
1148
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEJZV4QGUcjs.LoadError, { message: error, onRetry: () => window.location.reload() }) });
1148
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVZMST7BDcjs.LoadError, { message: error, onRetry: () => window.location.reload() }) });
1149
1149
  }
1150
1150
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex w-full flex-col gap-[40px]", children: [
1151
1151
  !isLoading && !hasResults && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1152
- _chunkL7PO6NSDcjs.ListEmptyState,
1152
+ _chunkXJMADFIKcjs.ListEmptyState,
1153
1153
  {
1154
1154
  isFiltered: hasActiveFilters,
1155
1155
  filtered: {
@@ -1303,7 +1303,7 @@ function LegalDocumentPage({
1303
1303
  initialData = null,
1304
1304
  initialLastUpdatedLabel = null,
1305
1305
  apiEndpoint,
1306
- MarkdownRenderer = _chunkEJZV4QGUcjs.RichMarkdownRenderer,
1306
+ MarkdownRenderer = _chunkVZMST7BDcjs.RichMarkdownRenderer,
1307
1307
  backButton,
1308
1308
  shell = true
1309
1309
  }) {
@@ -1316,7 +1316,7 @@ function LegalDocumentPage({
1316
1316
  const fallbackLastUpdatedLabel = _optionalChain([data, 'optionalAccess', _27 => _27.lastSynced]) != null ? _chunkQRUW4UXBcjs.formatLegalDate.call(void 0, data.lastSynced) : null;
1317
1317
  const effectiveLastUpdatedLabel = _nullishCoalesce(initialLastUpdatedLabel, () => ( fallbackLastUpdatedLabel));
1318
1318
  const subtitle = effectiveLastUpdatedLabel ? `Last Updated: ${effectiveLastUpdatedLabel}` : fallbackDescription;
1319
- const inner = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkEJZV4QGUcjs.PageLayout, { title, subtitle, backButton: backCfg, titleSize: "h1", titleWrap: true, children: [
1319
+ const inner = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkVZMST7BDcjs.PageLayout, { title, subtitle, backButton: backCfg, titleSize: "h1", titleWrap: true, children: [
1320
1320
  _optionalChain([data, 'optionalAccess', _28 => _28.sourceFile]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: "text-ods-text-secondary opacity-75 text-h6", children: [
1321
1321
  "Source: ",
1322
1322
  data.sourceFile
@@ -1356,7 +1356,7 @@ function LegalDocumentPage({
1356
1356
  ] })
1357
1357
  ] }) }) }) }) })
1358
1358
  ] });
1359
- return shell ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEJZV4QGUcjs.PageShell, { children: inner }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "page-shell-content", children: inner });
1359
+ return shell ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkVZMST7BDcjs.PageShell, { children: inner }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "page-shell-content", children: inner });
1360
1360
  }
1361
1361
 
1362
1362
 
@@ -1373,4 +1373,4 @@ function LegalDocumentPage({
1373
1373
 
1374
1374
 
1375
1375
  exports.ProductReleasesView = ProductReleasesView; exports.MediaGalleryStrip = MediaGalleryStrip; exports.ReleaseDetailPage = ReleaseDetailPage; exports.ReleaseDetailSkeleton = ReleaseDetailSkeleton; exports.useRoadmapVoting = useRoadmapVoting; exports.RoadmapGrid = RoadmapGrid; exports.RoadmapGridSkeleton = RoadmapGridSkeleton; exports.RoadmapView = RoadmapView; exports.DeliveryTable = DeliveryTable; exports.DeliveryLists = DeliveryLists; exports.useLegalDocs = useLegalDocs; exports.LegalDocumentPage = LegalDocumentPage;
1376
- //# sourceMappingURL=chunk-MRT6DZG5.cjs.map
1376
+ //# sourceMappingURL=chunk-GU5JW5MX.cjs.map