@flamingo-stack/openframe-frontend-core 0.0.285 → 0.0.286

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 (211) hide show
  1. package/dist/chunk-3MCHAFHB.js +89 -0
  2. package/dist/chunk-3MCHAFHB.js.map +1 -0
  3. package/dist/{chunk-IMNGGLKL.js → chunk-3ZXUQQL4.js} +2 -2
  4. package/dist/{chunk-44ZFLMYC.cjs → chunk-4WACBTZU.cjs} +30 -30
  5. package/dist/{chunk-44ZFLMYC.cjs.map → chunk-4WACBTZU.cjs.map} +1 -1
  6. package/dist/{chunk-23UOJUDF.js → chunk-5BTZOVDQ.js} +4 -4
  7. package/dist/chunk-5KD3S25X.cjs +312 -0
  8. package/dist/chunk-5KD3S25X.cjs.map +1 -0
  9. package/dist/chunk-6N26CURS.cjs +2417 -0
  10. package/dist/chunk-6N26CURS.cjs.map +1 -0
  11. package/dist/{chunk-XX7P4IL2.js → chunk-7NM7DEUK.js} +4 -143
  12. package/dist/chunk-7NM7DEUK.js.map +1 -0
  13. package/dist/chunk-BBZ7AX5H.cjs +290 -0
  14. package/dist/chunk-BBZ7AX5H.cjs.map +1 -0
  15. package/dist/chunk-C6SCWXDP.js +290 -0
  16. package/dist/chunk-C6SCWXDP.js.map +1 -0
  17. package/dist/{chunk-GVSTRN36.cjs → chunk-D3LEFMOA.cjs} +3 -3
  18. package/dist/{chunk-GVSTRN36.cjs.map → chunk-D3LEFMOA.cjs.map} +1 -1
  19. package/dist/{chunk-P45Q4QCU.cjs → chunk-D5YY5U6J.cjs} +19 -15
  20. package/dist/chunk-D5YY5U6J.cjs.map +1 -0
  21. package/dist/chunk-DDAT4RKX.js +2417 -0
  22. package/dist/chunk-DDAT4RKX.js.map +1 -0
  23. package/dist/{chunk-PVXCVPJD.cjs → chunk-EI4WALN2.cjs} +67 -1626
  24. package/dist/chunk-EI4WALN2.cjs.map +1 -0
  25. package/dist/{chunk-ZIODAAFY.cjs → chunk-EL5GCMPU.cjs} +20 -159
  26. package/dist/chunk-EL5GCMPU.cjs.map +1 -0
  27. package/dist/{chunk-VQW7CEGS.js → chunk-FSBDVT6R.js} +1831 -3672
  28. package/dist/chunk-FSBDVT6R.js.map +1 -0
  29. package/dist/{chunk-DPKUSBQH.cjs → chunk-GDF2R2ER.cjs} +1073 -2914
  30. package/dist/chunk-GDF2R2ER.cjs.map +1 -0
  31. package/dist/chunk-HLQW7MWJ.cjs +1594 -0
  32. package/dist/chunk-HLQW7MWJ.cjs.map +1 -0
  33. package/dist/chunk-I6ZPGKZ2.cjs +151 -0
  34. package/dist/chunk-I6ZPGKZ2.cjs.map +1 -0
  35. package/dist/{chunk-J66U3LPZ.cjs → chunk-KBKZYJRI.cjs} +33 -332
  36. package/dist/chunk-KBKZYJRI.cjs.map +1 -0
  37. package/dist/{chunk-USPATRSC.js → chunk-N6ZM5PYZ.js} +45 -344
  38. package/dist/chunk-N6ZM5PYZ.js.map +1 -0
  39. package/dist/{chunk-RGALV4UX.js → chunk-POKKCWKF.js} +3 -82
  40. package/dist/chunk-POKKCWKF.js.map +1 -0
  41. package/dist/{chunk-XDI5JSWB.cjs → chunk-QCKN37OP.cjs} +45 -41
  42. package/dist/chunk-QCKN37OP.cjs.map +1 -0
  43. package/dist/{chunk-KNCDUWY2.js → chunk-QF2X6PTD.js} +10 -6
  44. package/dist/{chunk-KNCDUWY2.js.map → chunk-QF2X6PTD.js.map} +1 -1
  45. package/dist/{chunk-Z3V2SGQZ.js → chunk-R2KT5GDD.js} +324 -1883
  46. package/dist/chunk-R2KT5GDD.js.map +1 -0
  47. package/dist/{chunk-RJUGNL2A.cjs → chunk-RQ6RTBKF.cjs} +16 -12
  48. package/dist/chunk-RQ6RTBKF.cjs.map +1 -0
  49. package/dist/chunk-TFSYSWPS.cjs +89 -0
  50. package/dist/chunk-TFSYSWPS.cjs.map +1 -0
  51. package/dist/chunk-TYZEMPPH.js +312 -0
  52. package/dist/chunk-TYZEMPPH.js.map +1 -0
  53. package/dist/{chunk-O5N57CRV.js → chunk-VCQ3CTYK.js} +12 -8
  54. package/dist/{chunk-O5N57CRV.js.map → chunk-VCQ3CTYK.js.map} +1 -1
  55. package/dist/chunk-VRSXJ5QJ.js +1599 -0
  56. package/dist/chunk-VRSXJ5QJ.js.map +1 -0
  57. package/dist/{chunk-53CFL7PH.js → chunk-XQL4WDML.js} +11 -7
  58. package/dist/{chunk-53CFL7PH.js.map → chunk-XQL4WDML.js.map} +1 -1
  59. package/dist/chunk-Y4JNA4W6.cjs +1599 -0
  60. package/dist/chunk-Y4JNA4W6.cjs.map +1 -0
  61. package/dist/{chunk-ZSUNQJRO.cjs → chunk-YETA25JW.cjs} +2 -81
  62. package/dist/chunk-YETA25JW.cjs.map +1 -0
  63. package/dist/chunk-YVB3VDIQ.js +1594 -0
  64. package/dist/chunk-YVB3VDIQ.js.map +1 -0
  65. package/dist/chunk-ZLN6SM2U.js +151 -0
  66. package/dist/chunk-ZLN6SM2U.js.map +1 -0
  67. package/dist/components/chat/chat-attachment-bar.d.ts.map +1 -1
  68. package/dist/components/chat/index.cjs +12 -6
  69. package/dist/components/chat/index.cjs.map +1 -1
  70. package/dist/components/chat/index.js +45 -39
  71. package/dist/components/contact/index.cjs +11 -7
  72. package/dist/components/contact/index.cjs.map +1 -1
  73. package/dist/components/contact/index.js +10 -6
  74. package/dist/components/docs/doc-navigation-context.d.ts +39 -0
  75. package/dist/components/docs/doc-navigation-context.d.ts.map +1 -0
  76. package/dist/components/docs/doc-viewer.d.ts +66 -0
  77. package/dist/components/docs/doc-viewer.d.ts.map +1 -0
  78. package/dist/components/docs/index.cjs +34 -0
  79. package/dist/components/docs/index.cjs.map +1 -0
  80. package/dist/components/docs/index.d.ts +8 -0
  81. package/dist/components/docs/index.d.ts.map +1 -0
  82. package/dist/components/docs/index.js +34 -0
  83. package/dist/components/docs/index.js.map +1 -0
  84. package/dist/components/docs/use-document-tree.d.ts +41 -0
  85. package/dist/components/docs/use-document-tree.d.ts.map +1 -0
  86. package/dist/components/docs/use-scroll-spy.d.ts +16 -0
  87. package/dist/components/docs/use-scroll-spy.d.ts.map +1 -0
  88. package/dist/components/embeds/embed-iframe.d.ts +29 -0
  89. package/dist/components/embeds/embed-iframe.d.ts.map +1 -0
  90. package/dist/components/embeds/figma-embed.d.ts +27 -0
  91. package/dist/components/embeds/figma-embed.d.ts.map +1 -0
  92. package/dist/components/embeds/google-sheets-viewer.d.ts +8 -0
  93. package/dist/components/embeds/google-sheets-viewer.d.ts.map +1 -0
  94. package/dist/components/embeds/index.cjs +37 -0
  95. package/dist/components/embeds/index.cjs.map +1 -0
  96. package/dist/components/embeds/index.d.ts +9 -0
  97. package/dist/components/embeds/index.d.ts.map +1 -0
  98. package/dist/components/embeds/index.js +37 -0
  99. package/dist/components/embeds/index.js.map +1 -0
  100. package/dist/components/embeds/pdf-viewer.d.ts +10 -0
  101. package/dist/components/embeds/pdf-viewer.d.ts.map +1 -0
  102. package/dist/components/faq/index.cjs +12 -8
  103. package/dist/components/faq/index.cjs.map +1 -1
  104. package/dist/components/faq/index.js +11 -7
  105. package/dist/components/features/index.cjs +10 -6
  106. package/dist/components/features/index.cjs.map +1 -1
  107. package/dist/components/features/index.js +9 -5
  108. package/dist/components/index.cjs +247 -1120
  109. package/dist/components/index.cjs.map +1 -1
  110. package/dist/components/index.d.ts +2 -0
  111. package/dist/components/index.d.ts.map +1 -1
  112. package/dist/components/index.js +645 -1518
  113. package/dist/components/index.js.map +1 -1
  114. package/dist/components/navigation/index.cjs +15 -6
  115. package/dist/components/navigation/index.cjs.map +1 -1
  116. package/dist/components/navigation/index.d.ts +2 -0
  117. package/dist/components/navigation/index.d.ts.map +1 -1
  118. package/dist/components/navigation/index.js +15 -6
  119. package/dist/components/navigation/multi-level-navigation.d.ts +28 -0
  120. package/dist/components/navigation/multi-level-navigation.d.ts.map +1 -0
  121. package/dist/components/onboarding-guides/index.cjs +34 -29
  122. package/dist/components/onboarding-guides/index.cjs.map +1 -1
  123. package/dist/components/onboarding-guides/index.js +13 -8
  124. package/dist/components/onboarding-guides/index.js.map +1 -1
  125. package/dist/components/related-content/index.cjs +12 -8
  126. package/dist/components/related-content/index.cjs.map +1 -1
  127. package/dist/components/related-content/index.js +11 -7
  128. package/dist/components/tickets/index.cjs +75 -70
  129. package/dist/components/tickets/index.cjs.map +1 -1
  130. package/dist/components/tickets/index.js +16 -11
  131. package/dist/components/tickets/index.js.map +1 -1
  132. package/dist/components/ui/index.cjs +12 -6
  133. package/dist/components/ui/index.cjs.map +1 -1
  134. package/dist/components/ui/index.js +65 -59
  135. package/dist/embed-shims/index.cjs +3 -3
  136. package/dist/embed-shims/index.cjs.map +1 -1
  137. package/dist/embed-shims/index.js +8 -8
  138. package/dist/hooks/index.cjs +6 -3
  139. package/dist/hooks/index.cjs.map +1 -1
  140. package/dist/hooks/index.js +7 -4
  141. package/dist/index.cjs +62 -6
  142. package/dist/index.cjs.map +1 -1
  143. package/dist/index.js +257 -201
  144. package/dist/types/doc-source.cjs +4 -0
  145. package/dist/types/doc-source.cjs.map +1 -0
  146. package/dist/types/doc-source.d.ts +86 -0
  147. package/dist/types/doc-source.d.ts.map +1 -0
  148. package/dist/types/doc-source.js +3 -0
  149. package/dist/types/doc-source.js.map +1 -0
  150. package/dist/types/index.d.ts +1 -0
  151. package/dist/types/index.d.ts.map +1 -1
  152. package/dist/utils/doc-path-utils.d.ts +24 -0
  153. package/dist/utils/doc-path-utils.d.ts.map +1 -0
  154. package/dist/utils/doc-tree-nav.d.ts +35 -0
  155. package/dist/utils/doc-tree-nav.d.ts.map +1 -0
  156. package/dist/utils/embed-url-converters.d.ts +16 -0
  157. package/dist/utils/embed-url-converters.d.ts.map +1 -0
  158. package/dist/utils/format.d.ts +9 -0
  159. package/dist/utils/format.d.ts.map +1 -1
  160. package/dist/utils/index.cjs +297 -0
  161. package/dist/utils/index.cjs.map +1 -1
  162. package/dist/utils/index.d.ts +7 -1
  163. package/dist/utils/index.d.ts.map +1 -1
  164. package/dist/utils/index.js +276 -1
  165. package/dist/utils/index.js.map +1 -1
  166. package/dist/utils/markdown-section-extractor.d.ts +23 -0
  167. package/dist/utils/markdown-section-extractor.d.ts.map +1 -0
  168. package/dist/utils/markdown-to-plain.d.ts +32 -0
  169. package/dist/utils/markdown-to-plain.d.ts.map +1 -0
  170. package/dist/utils/tree-builder.d.ts +30 -0
  171. package/dist/utils/tree-builder.d.ts.map +1 -0
  172. package/package.json +19 -1
  173. package/src/components/chat/chat-attachment-bar.tsx +6 -11
  174. package/src/components/docs/doc-navigation-context.tsx +123 -0
  175. package/src/components/docs/doc-viewer.tsx +345 -0
  176. package/src/components/docs/index.ts +12 -0
  177. package/src/components/docs/use-document-tree.ts +427 -0
  178. package/src/components/docs/use-scroll-spy.ts +93 -0
  179. package/src/components/embeds/embed-iframe.tsx +103 -0
  180. package/src/components/embeds/figma-embed.tsx +147 -0
  181. package/src/components/embeds/google-sheets-viewer.tsx +54 -0
  182. package/src/components/embeds/index.ts +11 -0
  183. package/src/components/embeds/pdf-viewer.tsx +64 -0
  184. package/src/components/index.ts +2 -0
  185. package/src/components/navigation/index.ts +5 -0
  186. package/src/components/navigation/multi-level-navigation.tsx +358 -0
  187. package/src/types/doc-source.ts +88 -0
  188. package/src/types/index.ts +4 -0
  189. package/src/utils/doc-path-utils.ts +47 -0
  190. package/src/utils/doc-tree-nav.ts +111 -0
  191. package/src/utils/embed-url-converters.ts +77 -0
  192. package/src/utils/format.ts +16 -0
  193. package/src/utils/index.ts +11 -0
  194. package/src/utils/markdown-section-extractor.ts +106 -0
  195. package/src/utils/markdown-to-plain.ts +69 -0
  196. package/src/utils/tree-builder.ts +114 -0
  197. package/dist/chunk-DPKUSBQH.cjs.map +0 -1
  198. package/dist/chunk-J66U3LPZ.cjs.map +0 -1
  199. package/dist/chunk-P45Q4QCU.cjs.map +0 -1
  200. package/dist/chunk-PVXCVPJD.cjs.map +0 -1
  201. package/dist/chunk-RGALV4UX.js.map +0 -1
  202. package/dist/chunk-RJUGNL2A.cjs.map +0 -1
  203. package/dist/chunk-USPATRSC.js.map +0 -1
  204. package/dist/chunk-VQW7CEGS.js.map +0 -1
  205. package/dist/chunk-XDI5JSWB.cjs.map +0 -1
  206. package/dist/chunk-XX7P4IL2.js.map +0 -1
  207. package/dist/chunk-Z3V2SGQZ.js.map +0 -1
  208. package/dist/chunk-ZIODAAFY.cjs.map +0 -1
  209. package/dist/chunk-ZSUNQJRO.cjs.map +0 -1
  210. /package/dist/{chunk-IMNGGLKL.js.map → chunk-3ZXUQQL4.js.map} +0 -0
  211. /package/dist/{chunk-23UOJUDF.js.map → chunk-5BTZOVDQ.js.map} +0 -0
@@ -0,0 +1,312 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
2
+
3
+
4
+
5
+
6
+
7
+ var _chunkLGLPNWS6cjs = require('./chunk-LGLPNWS6.cjs');
8
+
9
+ // src/utils/platform-config.tsx
10
+ var _lucidereact = require('lucide-react');
11
+ var _jsxruntime = require('react/jsx-runtime');
12
+ var platformIcons = {
13
+ openframe: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.OpenFrameLogo, { className: "h-5 w-5", lowerPathColor: "#FFC008", upperPathColor: "#ffffff" }),
14
+ openmsp: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.OpenmspLogo, { className: "h-5 w-5" }),
15
+ flamingo: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className: "h-5 w-5", fill: "#EC4899" }),
16
+ "flamingo-teaser": /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className: "h-5 w-5", fill: "#EC4899" }),
17
+ "marketing-hub": /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className: "h-5 w-5", fill: "#F357BB" }),
18
+ "product-hub": /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className: "h-5 w-5", fill: "#5EA62E" }),
19
+ "revenue-hub": /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className: "h-5 w-5", fill: "#FFC008" }),
20
+ "people-hub": /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className: "h-5 w-5", fill: "#5EFAF0" }),
21
+ "company-hub": /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className: "h-5 w-5", fill: "#f36666" }),
22
+ tmcg: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.MiamiCyberGangLogoFaceOnly, { className: "h-5 w-5" }),
23
+ universal: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Globe, { className: "h-5 w-5 text-[#10B981]" })
24
+ };
25
+ var platformColors = {
26
+ openmsp: "bg-[#3B82F6]",
27
+ openframe: "bg-[#8B5CF6]",
28
+ flamingo: "bg-[#EC4899]",
29
+ "flamingo-teaser": "bg-[#F59E0B]",
30
+ "marketing-hub": "bg-[#F357BB]",
31
+ "product-hub": "bg-[#5EA62E]",
32
+ "revenue-hub": "bg-[#FFC008]",
33
+ "people-hub": "bg-[#5EFAF0]",
34
+ "company-hub": "bg-[#f36666]",
35
+ tmcg: "bg-[#FF6B6B]",
36
+ universal: "bg-[#10B981]"
37
+ };
38
+ var platformDisplayNames = {
39
+ openmsp: "OpenMSP",
40
+ openframe: "OpenFrame",
41
+ flamingo: "Flamingo",
42
+ "flamingo-teaser": "Flamingo Teaser",
43
+ "marketing-hub": "Flamingo Marketing Hub",
44
+ "product-hub": "Flamingo Product Hub",
45
+ "revenue-hub": "Flamingo Revenue Hub",
46
+ "people-hub": "Flamingo People Hub",
47
+ "company-hub": "Flamingo Company Hub",
48
+ tmcg: "TMCG",
49
+ universal: "Universal"
50
+ };
51
+ var platformDescriptions = {
52
+ openmsp: "Comprehensive directory and comparison platform for managed service providers (MSPs) and technology vendors. Reduce vendor costs and discover open-source alternatives.",
53
+ openframe: "AI-driven open-source security operations center (SOC) and endpoint detection platform for MSPs.",
54
+ flamingo: "AI-driven open-source OS for MSPs. Swap bloated vendor tools for open ones. Automate the boring crap. Take your margin back.",
55
+ "flamingo-teaser": "Preview of Flamingo - the AI-driven open-source OS for MSPs.",
56
+ tmcg: "The Miami Cyber Gang - A cybersecurity community focused on education and collaboration.",
57
+ universal: "Cross-platform universal content."
58
+ };
59
+ var platformSlogans = {
60
+ openmsp: "Find Your Perfect MSP Partner",
61
+ openframe: "Open-Source Security Operations",
62
+ flamingo: "Open-Source OS for MSPs",
63
+ "flamingo-teaser": "Coming Soon: Open-Source OS for MSPs",
64
+ tmcg: "Miami Cyber Community",
65
+ universal: "Universal Platform"
66
+ };
67
+ var platformHexColors = {
68
+ openmsp: "#FFC008",
69
+ openframe: "#FFC008",
70
+ flamingo: "#FF6B9D",
71
+ universal: "#FFC008",
72
+ "flamingo-teaser": "#F59E0B",
73
+ "marketing-hub": "#F357BB",
74
+ "product-hub": "#5EA62E",
75
+ "revenue-hub": "#FFC008",
76
+ "people-hub": "#5EFAF0",
77
+ "company-hub": "#f36666",
78
+ tmcg: "#FF6B6B"
79
+ };
80
+ var platformIconNames = {
81
+ openmsp: "openmsp-logo",
82
+ openframe: "openframe-logo",
83
+ flamingo: "flamingo-logo",
84
+ universal: "globe",
85
+ "flamingo-teaser": "flamingo-logo",
86
+ "marketing-hub": "flamingo-logo",
87
+ "product-hub": "flamingo-logo",
88
+ "revenue-hub": "flamingo-logo",
89
+ "people-hub": "flamingo-logo",
90
+ "company-hub": "flamingo-logo",
91
+ tmcg: "tmcg-logo"
92
+ };
93
+ function getDefaultColorForPlatform(platformName) {
94
+ return platformHexColors[platformName] || platformHexColors.universal;
95
+ }
96
+ function getDefaultIconForPlatform(platformName) {
97
+ return platformIconNames[platformName] || platformIconNames.universal;
98
+ }
99
+ function transformPlatformConfigsToOptions(platformConfigs) {
100
+ return platformConfigs.map((platform) => ({
101
+ id: platform.id,
102
+ // Database UUID for matching
103
+ name: platform.name,
104
+ // Platform name enum
105
+ displayName: platform.display_name,
106
+ // Human-readable name
107
+ description: platform.description,
108
+ icon: platformIcons[platform.name] || platformIcons.universal,
109
+ color: platformColors[platform.name] || platformColors.universal
110
+ }));
111
+ }
112
+ function getPlatformIcon(platformName) {
113
+ return platformIcons[platformName] || platformIcons.universal;
114
+ }
115
+ function getPlatformColor(platformName) {
116
+ return platformColors[platformName] || platformColors.universal;
117
+ }
118
+ function getPlatformDisplayName(platformName) {
119
+ return platformDisplayNames[platformName] || platformName;
120
+ }
121
+ function getPlatformDescription(platformName) {
122
+ return platformDescriptions[platformName] || platformName;
123
+ }
124
+ function getPlatformSlogan(platformName) {
125
+ return platformSlogans[platformName] || platformName;
126
+ }
127
+ function getSmallPlatformIcon(platformName) {
128
+ const className = "h-4 w-4 flex-shrink-0";
129
+ switch (platformName) {
130
+ case "openframe":
131
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.OpenFrameLogo, { className, lowerPathColor: "#FFC008", upperPathColor: "#ffffff" });
132
+ case "openmsp":
133
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.OpenmspLogo, { className, frontBubbleColor: "#f1f1f1", innerFrontBubbleColor: "#000000", backBubbleColor: "#FFC008" });
134
+ case "flamingo":
135
+ case "flamingo-teaser":
136
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className: `${className}`, fill: "#EC4899" });
137
+ case "marketing-hub":
138
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className, fill: "var(--ods-flamingo-pink-base)" });
139
+ case "product-hub":
140
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className, fill: "var(--ods-attention-green-success)" });
141
+ case "revenue-hub":
142
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className, fill: "var(--ods-attention-yellow-warning)" });
143
+ case "people-hub":
144
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className, fill: "var(--ods-flamingo-cyan-base)" });
145
+ case "company-hub":
146
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className, fill: "var(--ods-attention-red-error)" });
147
+ case "tmcg":
148
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.MiamiCyberGangLogoFaceOnly, { className });
149
+ case "universal":
150
+ default:
151
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Globe, { className });
152
+ }
153
+ }
154
+ function getPlatformIconComponent(platformName, className = "h-6 w-6") {
155
+ switch (platformName) {
156
+ case "openframe":
157
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.OpenFrameLogo, { className });
158
+ case "openmsp":
159
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.OpenmspLogo, { className, color: "#f1f1f1" });
160
+ case "flamingo":
161
+ case "flamingo-teaser":
162
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className: `${className} text-white` });
163
+ case "marketing-hub":
164
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className, fill: "var(--ods-flamingo-pink-base)" });
165
+ case "product-hub":
166
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className, fill: "var(--ods-attention-green-success)" });
167
+ case "revenue-hub":
168
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className, fill: "var(--ods-attention-yellow-warning)" });
169
+ case "people-hub":
170
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className, fill: "var(--ods-flamingo-cyan-base)" });
171
+ case "company-hub":
172
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.FlamingoLogo, { className, fill: "var(--ods-attention-red-error)" });
173
+ case "tmcg":
174
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGLPNWS6cjs.MiamiCyberGangLogoFaceOnly, { size: 24, className });
175
+ case "universal":
176
+ default:
177
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Globe, { className });
178
+ }
179
+ }
180
+
181
+ // src/types/tool.types.ts
182
+ var ToolTypeValues = {
183
+ TACTICAL_RMM: "TACTICAL_RMM",
184
+ FLEET_MDM: "FLEET_MDM",
185
+ MESHCENTRAL: "MESHCENTRAL",
186
+ AUTHENTIK: "AUTHENTIK",
187
+ OPENFRAME: "OPENFRAME",
188
+ OPENFRAME_CHAT: "OPENFRAME_CHAT",
189
+ OPENFRAME_CLIENT: "OPENFRAME_CLIENT",
190
+ OSQUERY: "OSQUERY",
191
+ SYSTEM: "SYSTEM"
192
+ };
193
+ var toolLabels = {
194
+ TACTICAL_RMM: "Tactical",
195
+ FLEET_MDM: "Fleet",
196
+ MESHCENTRAL: "MeshCentral",
197
+ AUTHENTIK: "Authentik",
198
+ OPENFRAME: "OpenFrame",
199
+ OPENFRAME_CHAT: "OpenFrame Chat",
200
+ OPENFRAME_CLIENT: "OpenFrame Client",
201
+ OSQUERY: "Osquery",
202
+ SYSTEM: "System"
203
+ };
204
+
205
+ // src/utils/access-code-client.ts
206
+ async function validateAccessCode(email, code, endpoints) {
207
+ try {
208
+ const response = await fetch(endpoints.validateUrl, {
209
+ method: "POST",
210
+ headers: {
211
+ "Content-Type": "application/json"
212
+ },
213
+ body: JSON.stringify({ email, code })
214
+ });
215
+ if (!response.ok) {
216
+ const error = await response.json().catch(() => ({}));
217
+ throw new Error(error.error || "Validation request failed");
218
+ }
219
+ return await response.json();
220
+ } catch (error) {
221
+ return {
222
+ valid: false,
223
+ message: error instanceof Error ? error.message : "Validation failed"
224
+ };
225
+ }
226
+ }
227
+ async function consumeAccessCode(email, code, endpoints) {
228
+ try {
229
+ const response = await fetch(endpoints.consumeUrl, {
230
+ method: "POST",
231
+ headers: {
232
+ "Content-Type": "application/json"
233
+ },
234
+ body: JSON.stringify({ email, code })
235
+ });
236
+ if (!response.ok) {
237
+ const error = await response.json().catch(() => ({}));
238
+ throw new Error(error.error || "Consumption request failed");
239
+ }
240
+ return await response.json();
241
+ } catch (error) {
242
+ return {
243
+ success: false,
244
+ consumed: false,
245
+ message: error instanceof Error ? error.message : "Consumption failed"
246
+ };
247
+ }
248
+ }
249
+ async function validateAndConsumeAccessCode(email, code, endpoints) {
250
+ const validation = await validateAccessCode(email, code, endpoints);
251
+ if (!validation.valid) {
252
+ return validation;
253
+ }
254
+ const consumption = await consumeAccessCode(email, code, endpoints);
255
+ return {
256
+ ...validation,
257
+ consumed: consumption.consumed,
258
+ message: consumption.consumed ? `Access granted for ${validation.cohort_name}` : consumption.message || validation.message
259
+ };
260
+ }
261
+
262
+ // src/utils/humanity-signals.ts
263
+ var HONEYPOT_FIELD = "contact_url_confirm";
264
+ var ELAPSED_MS_FIELD = "form_elapsed_ms";
265
+ var DEFAULT_MIN_FILL_MS = 700;
266
+ function extractHumanitySignals(body) {
267
+ const b = _nullishCoalesce(body, () => ( {}));
268
+ const rawHp = b[HONEYPOT_FIELD];
269
+ const honeypot = rawHp == null ? "" : String(rawHp);
270
+ const rawMs = b[ELAPSED_MS_FIELD];
271
+ const elapsedMs = typeof rawMs === "number" && Number.isFinite(rawMs) ? rawMs : null;
272
+ return { honeypot, elapsedMs };
273
+ }
274
+ function evaluateHumanitySignals(body, opts) {
275
+ const { honeypot, elapsedMs } = extractHumanitySignals(body);
276
+ if (honeypot.trim() !== "") return { ok: false, reason: "honeypot" };
277
+ if (elapsedMs !== null && elapsedMs < opts.minFillMs) return { ok: false, reason: "too_fast" };
278
+ return { ok: true };
279
+ }
280
+ var splitCsvEnv = (s) => _nullishCoalesce(_optionalChain([s, 'optionalAccess', _ => _.split, 'call', _2 => _2(","), 'access', _3 => _3.map, 'call', _4 => _4((t) => t.trim()), 'access', _5 => _5.filter, 'call', _6 => _6(Boolean)]), () => ( []));
281
+
282
+
283
+
284
+
285
+
286
+
287
+
288
+
289
+
290
+
291
+
292
+
293
+
294
+
295
+
296
+
297
+
298
+
299
+
300
+
301
+
302
+
303
+
304
+
305
+
306
+
307
+
308
+
309
+
310
+
311
+ exports.platformIcons = platformIcons; exports.platformColors = platformColors; exports.platformDisplayNames = platformDisplayNames; exports.platformDescriptions = platformDescriptions; exports.platformSlogans = platformSlogans; exports.platformHexColors = platformHexColors; exports.platformIconNames = platformIconNames; exports.getDefaultColorForPlatform = getDefaultColorForPlatform; exports.getDefaultIconForPlatform = getDefaultIconForPlatform; exports.transformPlatformConfigsToOptions = transformPlatformConfigsToOptions; exports.getPlatformIcon = getPlatformIcon; exports.getPlatformColor = getPlatformColor; exports.getPlatformDisplayName = getPlatformDisplayName; exports.getPlatformDescription = getPlatformDescription; exports.getPlatformSlogan = getPlatformSlogan; exports.getSmallPlatformIcon = getSmallPlatformIcon; exports.getPlatformIconComponent = getPlatformIconComponent; exports.ToolTypeValues = ToolTypeValues; exports.toolLabels = toolLabels; exports.validateAccessCode = validateAccessCode; exports.consumeAccessCode = consumeAccessCode; exports.validateAndConsumeAccessCode = validateAndConsumeAccessCode; exports.HONEYPOT_FIELD = HONEYPOT_FIELD; exports.ELAPSED_MS_FIELD = ELAPSED_MS_FIELD; exports.DEFAULT_MIN_FILL_MS = DEFAULT_MIN_FILL_MS; exports.extractHumanitySignals = extractHumanitySignals; exports.evaluateHumanitySignals = evaluateHumanitySignals; exports.splitCsvEnv = splitCsvEnv;
312
+ //# sourceMappingURL=chunk-5KD3S25X.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-5KD3S25X.cjs","../src/utils/platform-config.tsx","../src/types/tool.types.ts","../src/utils/access-code-client.ts","../src/utils/humanity-signals.ts"],"names":[],"mappings":"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A;AACA,EAAA;AACK,EAAA;AACE,EAAA;AACT,EAAA;AACD,EAAA;AACV;AFyK6D;AACA;AG1JpB;AACnC,EAAA;AACkD,IAAA;AAC1C,MAAA;AACC,MAAA;AACS,QAAA;AAClB,MAAA;AAC4D,MAAA;AAC7D,IAAA;AAEiB,IAAA;AACoC,MAAA;AACrB,MAAA;AACjC,IAAA;AAE2B,IAAA;AACb,EAAA;AACP,IAAA;AACE,MAAA;AAC2C,MAAA;AACpD,IAAA;AACF,EAAA;AACF;AAyB0C;AACpC,EAAA;AACiD,IAAA;AACzC,MAAA;AACC,MAAA;AACS,QAAA;AAClB,MAAA;AAC4D,MAAA;AAC7D,IAAA;AAEiB,IAAA;AACoC,MAAA;AACrB,MAAA;AACjC,IAAA;AAE2B,IAAA;AACb,EAAA;AACP,IAAA;AACI,MAAA;AACC,MAAA;AACwC,MAAA;AACpD,IAAA;AACF,EAAA;AACF;AAyBE;AAGyD,EAAA;AAElC,EAAA;AACd,IAAA;AACT,EAAA;AAGyD,EAAA;AAElD,EAAA;AACF,IAAA;AACmB,IAAA;AAEI,IAAA;AAE5B,EAAA;AACF;AHgG6D;AACA;AIrP/B;AAEE;AAEG;AASmE;AAChF,EAAA;AACU,EAAA;AAKoB,EAAA;AAClB,EAAA;AACsB,EAAA;AACzB,EAAA;AAC/B;AAOqG;AACxC,EAAA;AACH,EAAA;AACF,EAAA;AACpC,EAAA;AACpB;AAIqC;AJgOwB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/openframe-oss-lib/openframe-oss-lib/openframe-frontend-core/dist/chunk-5KD3S25X.cjs","sourcesContent":[null,"import React from 'react';\nimport { OpenmspLogo, FlamingoLogo, OpenFrameLogo, MiamiCyberGangLogoFaceOnly } from '../components/icons';\nimport { Globe } from 'lucide-react';\nimport type { SelectableOption } from '../components/features';\nimport type { PlatformConfig } from '../types/platform';\n\n// Platform icons mapping with consistent colors matching app theme\nexport const platformIcons = {\n openframe: <OpenFrameLogo className=\"h-5 w-5\" lowerPathColor=\"#FFC008\" upperPathColor=\"#ffffff\" />,\n openmsp: <OpenmspLogo className=\"h-5 w-5\" />,\n flamingo: <FlamingoLogo className=\"h-5 w-5\" fill=\"#EC4899\" />,\n 'flamingo-teaser': <FlamingoLogo className=\"h-5 w-5\" fill=\"#EC4899\" />,\n 'marketing-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#F357BB\" />,\n 'product-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#5EA62E\" />,\n 'revenue-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#FFC008\" />,\n 'people-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#5EFAF0\" />,\n 'company-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#f36666\" />,\n tmcg: <MiamiCyberGangLogoFaceOnly className=\"h-5 w-5\" />,\n universal: <Globe className=\"h-5 w-5 text-[#10B981]\" />\n};\n\n// Platform colors mapping\nexport const platformColors = {\n openmsp: 'bg-[#3B82F6]',\n openframe: 'bg-[#8B5CF6]',\n flamingo: 'bg-[#EC4899]',\n 'flamingo-teaser': 'bg-[#F59E0B]',\n 'marketing-hub': 'bg-[#F357BB]',\n 'product-hub': 'bg-[#5EA62E]',\n 'revenue-hub': 'bg-[#FFC008]',\n 'people-hub': 'bg-[#5EFAF0]',\n 'company-hub': 'bg-[#f36666]',\n tmcg: 'bg-[#FF6B6B]',\n universal: 'bg-[#10B981]'\n};\n\n// Platform display names for consistent naming across the app\nexport const platformDisplayNames = {\n openmsp: 'OpenMSP',\n openframe: 'OpenFrame',\n flamingo: 'Flamingo',\n 'flamingo-teaser': 'Flamingo Teaser',\n 'marketing-hub': 'Flamingo Marketing Hub',\n 'product-hub': 'Flamingo Product Hub',\n 'revenue-hub': 'Flamingo Revenue Hub',\n 'people-hub': 'Flamingo People Hub',\n 'company-hub': 'Flamingo Company Hub',\n tmcg: 'TMCG',\n universal: 'Universal'\n};\n\n// Platform descriptions for consistent messaging across the app\nexport const platformDescriptions = {\n openmsp: 'Comprehensive directory and comparison platform for managed service providers (MSPs) and technology vendors. Reduce vendor costs and discover open-source alternatives.',\n openframe: 'AI-driven open-source security operations center (SOC) and endpoint detection platform for MSPs.',\n flamingo: 'AI-driven open-source OS for MSPs. Swap bloated vendor tools for open ones. Automate the boring crap. Take your margin back.',\n 'flamingo-teaser': 'Preview of Flamingo - the AI-driven open-source OS for MSPs.',\n tmcg: 'The Miami Cyber Gang - A cybersecurity community focused on education and collaboration.',\n universal: 'Cross-platform universal content.'\n};\n\n// Platform slogans for branding consistency\nexport const platformSlogans = {\n openmsp: 'Find Your Perfect MSP Partner',\n openframe: 'Open-Source Security Operations',\n flamingo: 'Open-Source OS for MSPs',\n 'flamingo-teaser': 'Coming Soon: Open-Source OS for MSPs',\n tmcg: 'Miami Cyber Community',\n universal: 'Universal Platform'\n};\n\n// Platform hex colors for default configuration\nexport const platformHexColors = {\n openmsp: '#FFC008',\n openframe: '#FFC008',\n flamingo: '#FF6B9D',\n universal: '#FFC008',\n 'flamingo-teaser': '#F59E0B',\n 'marketing-hub': '#F357BB',\n 'product-hub': '#5EA62E',\n 'revenue-hub': '#FFC008',\n 'people-hub': '#5EFAF0',\n 'company-hub': '#f36666',\n tmcg: '#FF6B6B'\n};\n\n// Platform icon names for default configuration\nexport const platformIconNames = {\n openmsp: 'openmsp-logo',\n openframe: 'openframe-logo',\n flamingo: 'flamingo-logo',\n universal: 'globe',\n 'flamingo-teaser': 'flamingo-logo',\n 'marketing-hub': 'flamingo-logo',\n 'product-hub': 'flamingo-logo',\n 'revenue-hub': 'flamingo-logo',\n 'people-hub': 'flamingo-logo',\n 'company-hub': 'flamingo-logo',\n tmcg: 'tmcg-logo'\n};\n\n/**\n * Get default color for platform\n */\nexport function getDefaultColorForPlatform(platformName: string): string {\n return platformHexColors[platformName as keyof typeof platformHexColors] || platformHexColors.universal;\n}\n\n/**\n * Get default icon name for platform\n */\nexport function getDefaultIconForPlatform(platformName: string): string {\n return platformIconNames[platformName as keyof typeof platformIconNames] || platformIconNames.universal;\n}\n\nexport function transformPlatformConfigsToOptions(platformConfigs: PlatformConfig[]): SelectableOption[] {\n return platformConfigs.map((platform: PlatformConfig) => ({\n id: platform.id, // Database UUID for matching\n name: platform.name, // Platform name enum\n displayName: platform.display_name, // Human-readable name\n description: platform.description,\n icon: platformIcons[platform.name as keyof typeof platformIcons] || platformIcons.universal,\n color: platformColors[platform.name as keyof typeof platformColors] || platformColors.universal\n }));\n}\n\n/**\n * Get platform icon by name\n */\nexport function getPlatformIcon(platformName: string) {\n return platformIcons[platformName as keyof typeof platformIcons] || platformIcons.universal;\n}\n\n/**\n * Get platform color by name\n */\nexport function getPlatformColor(platformName: string) {\n return platformColors[platformName as keyof typeof platformColors] || platformColors.universal;\n}\n\n/**\n * Get platform display name by name\n */\nexport function getPlatformDisplayName(platformName: string): string {\n return platformDisplayNames[platformName as keyof typeof platformDisplayNames] || platformName;\n}\n\n/**\n * Get platform description by name\n */\nexport function getPlatformDescription(platformName: string): string {\n return platformDescriptions[platformName as keyof typeof platformDescriptions] || platformName;\n}\n\n/**\n * Get platform slogan by name\n */\nexport function getPlatformSlogan(platformName: string): string {\n return platformSlogans[platformName as keyof typeof platformSlogans] || platformName;\n}\n\n/**\n * Get small platform icon for filter buttons with white colors (4x4 size)\n */\nexport function getSmallPlatformIcon(platformName: string): React.ReactNode {\n const className = \"h-4 w-4 flex-shrink-0\";\n\n switch (platformName) {\n case 'openframe':\n return <OpenFrameLogo className={className} lowerPathColor=\"#FFC008\" upperPathColor=\"#ffffff\" />;\n case 'openmsp':\n return <OpenmspLogo className={className} frontBubbleColor=\"#f1f1f1\" innerFrontBubbleColor=\"#000000\" backBubbleColor=\"#FFC008\" />;\n case 'flamingo':\n case 'flamingo-teaser':\n return <FlamingoLogo className={`${className}`} fill=\"#EC4899\" />;\n case 'marketing-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-flamingo-pink-base)\" />;\n case 'product-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-green-success)\" />;\n case 'revenue-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-yellow-warning)\" />;\n case 'people-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-flamingo-cyan-base)\" />;\n case 'company-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-red-error)\" />;\n case 'tmcg':\n return <MiamiCyberGangLogoFaceOnly className={className} />;\n case 'universal':\n default:\n return <Globe className={className} />;\n }\n}\n\n/**\n * Get platform icon for admin/selector components (standard 6x6 size)\n */\nexport function getPlatformIconComponent(platformName: string, className: string = \"h-6 w-6\"): React.ReactNode {\n switch (platformName) {\n case 'openframe':\n return <OpenFrameLogo className={className} />;\n case 'openmsp':\n return <OpenmspLogo className={className} color=\"#f1f1f1\" />;\n case 'flamingo':\n case 'flamingo-teaser':\n return <FlamingoLogo className={`${className} text-white`} />;\n case 'marketing-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-flamingo-pink-base)\" />;\n case 'product-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-green-success)\" />;\n case 'revenue-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-yellow-warning)\" />;\n case 'people-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-flamingo-cyan-base)\" />;\n case 'company-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-red-error)\" />;\n case 'tmcg':\n return <MiamiCyberGangLogoFaceOnly size={24} className={className} />;\n case 'universal':\n default:\n return <Globe className={className} />;\n }\n}","/**\n * Centralized Tool Types\n *\n * Single source of truth for all tool-related types across the entire platform.\n * Used by ToolBadge, ToolIcon, and any component that needs tool type information.\n */\n\nexport const ToolTypeValues = {\n TACTICAL_RMM: 'TACTICAL_RMM',\n FLEET_MDM: 'FLEET_MDM',\n MESHCENTRAL: 'MESHCENTRAL',\n AUTHENTIK: 'AUTHENTIK',\n OPENFRAME: 'OPENFRAME',\n OPENFRAME_CHAT: 'OPENFRAME_CHAT',\n OPENFRAME_CLIENT: 'OPENFRAME_CLIENT',\n OSQUERY: 'OSQUERY',\n SYSTEM: 'SYSTEM'\n} as const\n\nexport type ToolType = (typeof ToolTypeValues)[keyof typeof ToolTypeValues]\n\n/**\n * Maps tool types to display labels\n */\nexport const toolLabels: Record<ToolType, string> = {\n TACTICAL_RMM: 'Tactical',\n FLEET_MDM: 'Fleet',\n MESHCENTRAL: 'MeshCentral',\n AUTHENTIK: 'Authentik',\n OPENFRAME: 'OpenFrame',\n OPENFRAME_CHAT: 'OpenFrame Chat',\n OPENFRAME_CLIENT: 'OpenFrame Client',\n OSQUERY: 'Osquery',\n SYSTEM: 'System'\n}\n","/**\n * Access Code Client Utilities — pure standalone functions.\n *\n * Endpoint paths are NOT hardcoded — every function takes an\n * `endpoints` argument. The React-side wrapper that binds them from\n * `EndpointsRuntimeContext` lives separately at\n * `hooks/use-access-code-integration.ts` (`useAccessCodeIntegration`).\n *\n * Keep this file **free of React imports** — it lives in the\n * server-safe `utils/index` tsup bundle. Any module-top-level call\n * into `createContext()` (which the runtime context file does) would\n * be pulled into the server bundle and crash SSR with\n * `createContext is not a function`.\n */\n\nimport {\n AccessCodeValidation,\n AccessCodeValidationResponse,\n AccessCodeConsumptionResponse\n} from '../types/access-code-cohorts';\n\n/** Endpoints required by the standalone client utilities. The\n * `useAccessCodeIntegration` hook (in `hooks/`) resolves these from\n * `EndpointsRuntimeContext.accessCode` automatically. */\nexport interface AccessCodeEndpoints {\n validateUrl: string\n consumeUrl: string\n}\n\n/**\n * Validate an access code for a given email\n *\n * @param email - User's email address\n * @param code - Access code to validate\n * @returns Promise with validation result\n *\n * @example\n * const result = await validateAccessCode('user@example.com', 'ABC123XY');\n * if (result.valid) {\n * // Allow user to proceed with registration\n * console.log(`Welcome to ${result.cohort_name}!`);\n * } else {\n * // Show error message\n * console.error(result.message);\n * }\n */\nexport async function validateAccessCode(\n email: string,\n code: string,\n endpoints: AccessCodeEndpoints,\n): Promise<AccessCodeValidationResponse> {\n try {\n const response = await fetch(endpoints.validateUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ email, code } as AccessCodeValidation),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.error || 'Validation request failed');\n }\n\n return await response.json() as AccessCodeValidationResponse;\n } catch (error) {\n return {\n valid: false,\n message: error instanceof Error ? error.message : 'Validation failed',\n };\n }\n}\n\n/**\n * Consume an access code after successful registration\n *\n * Call this ONLY after the user has successfully completed registration.\n * This marks the code as used and prevents further usage.\n *\n * @param email - User's email address\n * @param code - Access code to consume\n * @returns Promise with consumption result\n *\n * @example\n * // After successful registration\n * const result = await consumeAccessCode('user@example.com', 'ABC123XY');\n * if (result.consumed) {\n * console.log('Access code consumed successfully');\n * } else {\n * console.warn('Failed to consume access code:', result.message);\n * }\n */\nexport async function consumeAccessCode(\n email: string,\n code: string,\n endpoints: AccessCodeEndpoints,\n): Promise<AccessCodeConsumptionResponse> {\n try {\n const response = await fetch(endpoints.consumeUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ email, code } as AccessCodeValidation),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.error || 'Consumption request failed');\n }\n\n return await response.json() as AccessCodeConsumptionResponse;\n } catch (error) {\n return {\n success: false,\n consumed: false,\n message: error instanceof Error ? error.message : 'Consumption failed',\n };\n }\n}\n\n/**\n * Complete access code flow: validate then consume\n *\n * This is a convenience function that validates an access code and,\n * if valid, immediately consumes it. Use this when you want to\n * validate and consume in one step during registration.\n *\n * @param email - User's email address\n * @param code - Access code to validate and consume\n * @returns Promise with validation and consumption results\n *\n * @example\n * const result = await validateAndConsumeAccessCode('user@example.com', 'ABC123XY');\n * if (result.valid && result.consumed) {\n * // Registration successful\n * console.log(`Welcome to ${result.cohort_name}!`);\n * } else {\n * console.error(result.message);\n * }\n */\nexport async function validateAndConsumeAccessCode(\n email: string,\n code: string,\n endpoints: AccessCodeEndpoints,\n): Promise<AccessCodeValidationResponse & { consumed?: boolean }> {\n // First validate\n const validation = await validateAccessCode(email, code, endpoints);\n\n if (!validation.valid) {\n return validation;\n }\n\n // If valid, consume the code\n const consumption = await consumeAccessCode(email, code, endpoints);\n\n return {\n ...validation,\n consumed: consumption.consumed,\n message: consumption.consumed\n ? `Access granted for ${validation.cohort_name}`\n : consumption.message || validation.message,\n };\n}\n\n// `useAccessCodeIntegration` (the React-side wrapper) lives in\n// `hooks/use-access-code-integration.ts`. It binds the endpoints from\n// `EndpointsRuntimeContext` so React callers don't have to plumb URLs.\n","/**\n * Humanity signals — invisible bot-protection primitives shared by the lib's\n * public forms (client) and the hub's per-route `verifyHuman` gate (server).\n *\n * PURE + React-free on purpose: this module is a tsup SERVER entry (no\n * \"use client\" banner) so the hub can import it server-side without pulling a\n * client-reference boundary — same pattern as `schemas/contact-schema` and\n * `components/features/mux-origins`.\n *\n * Two origin-independent signals travel in the POST body: a honeypot (a hidden\n * field real users never fill) and timing (ms from form mount to submit).\n * `evaluateHumanitySignals` is the SINGLE source of truth for the block/allow\n * decision — the hub imports + calls it rather than re-implementing the rules.\n */\n\n/** Hidden honeypot field name. Innocuous + autofill-resistant (deliberately NOT name/email). */\nexport const HONEYPOT_FIELD = 'contact_url_confirm'\n/** Client-measured ms between form mount and submit. */\nexport const ELAPSED_MS_FIELD = 'form_elapsed_ms'\n/** Default minimum fill time (ms). A submit faster than this is treated as a bot. */\nexport const DEFAULT_MIN_FILL_MS = 700\n\n/** Keyed wire object produced by `useHumanitySignals().getSignals()` and spread into the POST body. */\nexport type HumanitySignals = Record<string, string | number>\n\n/** Result of {@link evaluateHumanitySignals}. */\nexport type HumanityVerdict = { ok: true } | { ok: false; reason: 'honeypot' | 'too_fast' }\n\n/** Tolerant reader — never throws; missing/garbage timing → null. */\nexport function extractHumanitySignals(body: unknown): { honeypot: string; elapsedMs: number | null } {\n const b = (body ?? {}) as Record<string, unknown>\n const rawHp = b[HONEYPOT_FIELD]\n // A legit client always sends a STRING here (getSignals → ref.value ?? ''),\n // so ANY present non-string value is a bot filling the decoy with a non-string\n // to dodge the empty-check — coerce to a (non-empty) string so it still trips.\n // null/undefined → '' = the correct \"field absent / unfilled\" allow case.\n const honeypot = rawHp == null ? '' : String(rawHp)\n const rawMs = b[ELAPSED_MS_FIELD]\n const elapsedMs = typeof rawMs === 'number' && Number.isFinite(rawMs) ? rawMs : null\n return { honeypot, elapsedMs }\n}\n\n/**\n * SINGLE decision fn for honeypot + timing (the hub's `verifyHuman` imports + calls this):\n * - honeypot non-empty → bot (real users never fill the off-screen field)\n * - elapsed below `minFillMs` → bot (humans take time; a MISSING timing value never blocks)\n */\nexport function evaluateHumanitySignals(body: unknown, opts: { minFillMs: number }): HumanityVerdict {\n const { honeypot, elapsedMs } = extractHumanitySignals(body)\n if (honeypot.trim() !== '') return { ok: false, reason: 'honeypot' }\n if (elapsedMs !== null && elapsedMs < opts.minFillMs) return { ok: false, reason: 'too_fast' }\n return { ok: true }\n}\n\n/** Parse a comma-separated env string → trimmed, non-empty entries (undefined → []). */\nexport const splitCsvEnv = (s?: string): string[] =>\n s?.split(',').map((t) => t.trim()).filter(Boolean) ?? []\n"]}