@salesmind-ai/design-system 0.2.1 → 0.3.0

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 (121) hide show
  1. package/dist/AppearancePanel-UT57J69V.d.cts +51 -0
  2. package/dist/AppearancePanel-UT57J69V.d.ts +51 -0
  3. package/dist/AppearanceProvider-C36a8-eb.d.cts +45 -0
  4. package/dist/AppearanceProvider-C36a8-eb.d.ts +45 -0
  5. package/dist/Breadcrumb-RX-B_gDV.d.cts +44 -0
  6. package/dist/Breadcrumb-RX-B_gDV.d.ts +44 -0
  7. package/dist/ExportMenu-A2TLFiVv.d.cts +311 -0
  8. package/dist/ExportMenu-C8qck5AT.d.ts +311 -0
  9. package/dist/SectionShell-BfBw5q0Y.d.cts +18 -0
  10. package/dist/SectionShell-BfBw5q0Y.d.ts +18 -0
  11. package/dist/Select-BdZmK0Lt.d.cts +66 -0
  12. package/dist/Select-BdZmK0Lt.d.ts +66 -0
  13. package/dist/admin/index.cjs +2941 -0
  14. package/dist/admin/index.cjs.map +1 -0
  15. package/dist/admin/index.css +4145 -0
  16. package/dist/admin/index.css.map +1 -0
  17. package/dist/admin/index.d.cts +491 -0
  18. package/dist/admin/index.d.ts +491 -0
  19. package/dist/admin/index.js +2918 -0
  20. package/dist/admin/index.js.map +1 -0
  21. package/dist/{audit-CiyPkxk1.d.cts → audit-BS2fn7M4.d.ts} +2 -51
  22. package/dist/{audit-CiyPkxk1.d.ts → audit-DwCmg32J.d.cts} +2 -51
  23. package/dist/blog/index.cjs +1074 -0
  24. package/dist/blog/index.cjs.map +1 -0
  25. package/dist/blog/index.css +1422 -0
  26. package/dist/blog/index.css.map +1 -0
  27. package/dist/blog/index.d.cts +233 -0
  28. package/dist/blog/index.d.ts +233 -0
  29. package/dist/blog/index.js +1056 -0
  30. package/dist/blog/index.js.map +1 -0
  31. package/dist/chart-types-BGVVO-zl.d.cts +208 -0
  32. package/dist/chart-types-BGVVO-zl.d.ts +208 -0
  33. package/dist/charts/index.cjs +2698 -0
  34. package/dist/charts/index.cjs.map +1 -0
  35. package/dist/charts/index.css +1167 -0
  36. package/dist/charts/index.css.map +1 -0
  37. package/dist/charts/index.d.cts +453 -0
  38. package/dist/charts/index.d.ts +453 -0
  39. package/dist/charts/index.js +2682 -0
  40. package/dist/charts/index.js.map +1 -0
  41. package/dist/core/index.cjs +526 -395
  42. package/dist/core/index.cjs.map +1 -1
  43. package/dist/core/index.css +294 -0
  44. package/dist/core/index.css.map +1 -1
  45. package/dist/core/index.d.cts +7 -982
  46. package/dist/core/index.d.ts +7 -982
  47. package/dist/core/index.js +476 -351
  48. package/dist/core/index.js.map +1 -1
  49. package/dist/i18n/index.cjs +585 -0
  50. package/dist/i18n/index.cjs.map +1 -0
  51. package/dist/i18n/index.d.cts +855 -0
  52. package/dist/i18n/index.d.ts +855 -0
  53. package/dist/i18n/index.js +547 -0
  54. package/dist/i18n/index.js.map +1 -0
  55. package/dist/index.d.cts +22 -1290
  56. package/dist/index.d.ts +22 -1290
  57. package/dist/marketing/index.cjs +2144 -3023
  58. package/dist/marketing/index.cjs.map +1 -1
  59. package/dist/marketing/index.css +3729 -4824
  60. package/dist/marketing/index.css.map +1 -1
  61. package/dist/marketing/index.d.cts +1351 -4
  62. package/dist/marketing/index.d.ts +1351 -4
  63. package/dist/marketing/index.js +2190 -3054
  64. package/dist/marketing/index.js.map +1 -1
  65. package/dist/motion/index.cjs +1230 -0
  66. package/dist/motion/index.cjs.map +1 -0
  67. package/dist/motion/index.css +699 -0
  68. package/dist/motion/index.css.map +1 -0
  69. package/dist/motion/index.d.cts +68 -0
  70. package/dist/motion/index.d.ts +68 -0
  71. package/dist/motion/index.js +1218 -0
  72. package/dist/motion/index.js.map +1 -0
  73. package/dist/nav/index.cjs +1533 -0
  74. package/dist/nav/index.cjs.map +1 -0
  75. package/dist/nav/index.css +1984 -0
  76. package/dist/nav/index.css.map +1 -0
  77. package/dist/nav/index.d.cts +279 -0
  78. package/dist/nav/index.d.ts +279 -0
  79. package/dist/nav/index.js +1501 -0
  80. package/dist/nav/index.js.map +1 -0
  81. package/dist/report/index.cjs +26 -1649
  82. package/dist/report/index.cjs.map +1 -1
  83. package/dist/report/index.css +0 -963
  84. package/dist/report/index.css.map +1 -1
  85. package/dist/report/index.d.cts +4 -2
  86. package/dist/report/index.d.ts +4 -2
  87. package/dist/report/index.js +27 -1640
  88. package/dist/report/index.js.map +1 -1
  89. package/dist/sections/index.cjs +385 -0
  90. package/dist/sections/index.cjs.map +1 -0
  91. package/dist/sections/index.css +818 -0
  92. package/dist/sections/index.css.map +1 -0
  93. package/dist/sections/index.d.cts +69 -0
  94. package/dist/sections/index.d.ts +69 -0
  95. package/dist/sections/index.js +374 -0
  96. package/dist/sections/index.js.map +1 -0
  97. package/dist/social-proof/index.cjs +1254 -0
  98. package/dist/social-proof/index.cjs.map +1 -0
  99. package/dist/social-proof/index.css +1416 -0
  100. package/dist/social-proof/index.css.map +1 -0
  101. package/dist/social-proof/index.d.cts +258 -0
  102. package/dist/social-proof/index.d.ts +258 -0
  103. package/dist/social-proof/index.js +1237 -0
  104. package/dist/social-proof/index.js.map +1 -0
  105. package/dist/theme/index.cjs +573 -0
  106. package/dist/theme/index.cjs.map +1 -0
  107. package/dist/theme/index.css +464 -0
  108. package/dist/theme/index.css.map +1 -0
  109. package/dist/theme/index.d.cts +48 -0
  110. package/dist/theme/index.d.ts +48 -0
  111. package/dist/theme/index.js +558 -0
  112. package/dist/theme/index.js.map +1 -0
  113. package/dist/types-DAlgDGzw.d.cts +52 -0
  114. package/dist/types-DAlgDGzw.d.ts +52 -0
  115. package/dist/web/index.d.cts +3 -2
  116. package/dist/web/index.d.ts +3 -2
  117. package/package.json +68 -9
  118. package/dist/ExportMenu-hEe5MhLq.d.cts +0 -1027
  119. package/dist/ExportMenu-hEe5MhLq.d.ts +0 -1027
  120. package/dist/index-B64suAAc.d.cts +0 -1498
  121. package/dist/index-B64suAAc.d.ts +0 -1498
@@ -0,0 +1,1074 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var clsx = require('clsx');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var reactIntl = require('react-intl');
7
+ var lucideReact = require('lucide-react');
8
+
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var React__default = /*#__PURE__*/_interopDefault(React);
12
+ var clsx__default = /*#__PURE__*/_interopDefault(clsx);
13
+
14
+ // src/components/AuthorBio/AuthorBio.tsx
15
+ var AvatarContext = React__default.default.createContext({
16
+ hasImage: false,
17
+ imageError: false,
18
+ onImageError: () => {
19
+ }
20
+ });
21
+ var Avatar = React__default.default.forwardRef(
22
+ ({ size = "md", className, children, ...props }, ref) => {
23
+ const [imageError, setImageError] = React__default.default.useState(false);
24
+ const [hasImage, setHasImage] = React__default.default.useState(false);
25
+ React__default.default.useEffect(() => {
26
+ let found = false;
27
+ React__default.default.Children.forEach(children, (child) => {
28
+ if (React__default.default.isValidElement(child) && child.type === AvatarImage) {
29
+ found = true;
30
+ }
31
+ });
32
+ setHasImage(found);
33
+ }, [children]);
34
+ const onImageError = React__default.default.useCallback(() => {
35
+ setImageError(true);
36
+ }, []);
37
+ return /* @__PURE__ */ jsxRuntime.jsx(AvatarContext.Provider, { value: { hasImage, imageError, onImageError }, children: /* @__PURE__ */ jsxRuntime.jsx(
38
+ "span",
39
+ {
40
+ ref,
41
+ className: clsx__default.default("ds-avatar", `ds-avatar--${size}`, className),
42
+ ...props,
43
+ children
44
+ }
45
+ ) });
46
+ }
47
+ );
48
+ Avatar.displayName = "Avatar";
49
+ var AvatarImage = React__default.default.forwardRef(({ className, onError, ...props }, ref) => {
50
+ const { imageError, onImageError } = React__default.default.useContext(AvatarContext);
51
+ const handleError = (e) => {
52
+ onImageError();
53
+ onError?.(e);
54
+ };
55
+ if (imageError) return null;
56
+ return /* @__PURE__ */ jsxRuntime.jsx(
57
+ "img",
58
+ {
59
+ ref,
60
+ className: clsx__default.default("ds-avatar__image", className),
61
+ onError: handleError,
62
+ ...props
63
+ }
64
+ );
65
+ });
66
+ AvatarImage.displayName = "AvatarImage";
67
+ var AvatarFallback = React__default.default.forwardRef(({ className, ...props }, ref) => {
68
+ const { hasImage, imageError } = React__default.default.useContext(AvatarContext);
69
+ if (hasImage && !imageError) return null;
70
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: clsx__default.default("ds-avatar__fallback", className), ...props });
71
+ });
72
+ AvatarFallback.displayName = "AvatarFallback";
73
+ var UtmContext = React.createContext(null);
74
+
75
+ // src/web/utm/useUtmDefaults.ts
76
+ function useUtmDefaults() {
77
+ return React.useContext(UtmContext);
78
+ }
79
+
80
+ // src/web/utm/builders.ts
81
+ var PLACEHOLDER_ORIGIN = "https://__placeholder__.internal";
82
+ function buildUtmUrl(baseUrl, params) {
83
+ const isRelative = baseUrl.startsWith("/");
84
+ let url;
85
+ try {
86
+ url = isRelative ? new URL(baseUrl, PLACEHOLDER_ORIGIN) : new URL(baseUrl);
87
+ } catch {
88
+ return baseUrl;
89
+ }
90
+ const existingParams = [];
91
+ url.searchParams.forEach((value, key) => {
92
+ existingParams.push([key, value]);
93
+ });
94
+ for (const [key] of existingParams) {
95
+ url.searchParams.delete(key);
96
+ }
97
+ for (const [key, value] of existingParams) {
98
+ if (!key.startsWith("utm_")) {
99
+ url.searchParams.set(key, value);
100
+ }
101
+ }
102
+ url.searchParams.set("utm_source", params.source);
103
+ url.searchParams.set("utm_medium", params.medium);
104
+ url.searchParams.set("utm_campaign", params.campaign);
105
+ if (params.term !== void 0) {
106
+ url.searchParams.set("utm_term", params.term);
107
+ }
108
+ if (params.content !== void 0) {
109
+ url.searchParams.set("utm_content", params.content);
110
+ }
111
+ if (isRelative) {
112
+ return url.href.replace(PLACEHOLDER_ORIGIN, "");
113
+ }
114
+ return url.href;
115
+ }
116
+
117
+ // src/web/utm/classifiers.ts
118
+ var INTERNAL_PATTERNS = [
119
+ /^\/(?!\/)/,
120
+ // Relative paths
121
+ /^https?:\/\/(www\.)?sales-mind\.ai/i,
122
+ // Marketing site
123
+ /^https?:\/\/app\.sales-mind\.ai/i,
124
+ // Web app
125
+ /^https?:\/\/apps\.sales-mind\.ai/i,
126
+ // Web app (legacy)
127
+ /^https?:\/\/meet\.sales-mind\.ai/i,
128
+ // Booking
129
+ /^https?:\/\/docs\.sales-mind\.ai/i
130
+ // Docs
131
+ ];
132
+ var SYSTEM_PATTERNS = [
133
+ /^https?:\/\/.*\/api\//i,
134
+ // API endpoints
135
+ /^https?:\/\/.*\/webhook/i,
136
+ // Webhooks
137
+ /^https?:\/\/.*\/oauth/i,
138
+ // OAuth callbacks
139
+ /^https?:\/\/.*\/callback/i,
140
+ // Callbacks
141
+ /^https?:\/\/.*\.supabase\.(co|com)/i,
142
+ // Supabase
143
+ /^https?:\/\/.*\.firebaseapp\.com/i,
144
+ // Firebase
145
+ /^https?:\/\/.*\.cloudfunctions\.net/i
146
+ // Cloud Functions
147
+ ];
148
+ var ASSET_PATTERNS = [
149
+ /\.(css|js|mjs|map|woff2?|ttf|eot|svg|png|jpe?g|gif|webp|avif|ico|pdf)(\?.*)?$/i
150
+ ];
151
+ var CONVERSION_PATTERNS = [
152
+ /^https?:\/\/(www\.)?calendly\.com/i,
153
+ /^https?:\/\/(checkout\.)?stripe\.com/i,
154
+ /^https?:\/\/buy\.stripe\.com/i,
155
+ /^https?:\/\/chromewebstore\.google\.com/i,
156
+ /^https?:\/\/meet\.sales-mind\.ai/i
157
+ ];
158
+ var PROTOCOL_EXEMPT = [
159
+ /^mailto:/i,
160
+ /^tel:/i,
161
+ /^#/,
162
+ /^javascript:/i
163
+ ];
164
+ function classifyUrl(url) {
165
+ if (PROTOCOL_EXEMPT.some((p) => p.test(url))) return "protocol";
166
+ if (ASSET_PATTERNS.some((p) => p.test(url))) return "asset";
167
+ if (SYSTEM_PATTERNS.some((p) => p.test(url))) return "system";
168
+ if (CONVERSION_PATTERNS.some((p) => p.test(url))) return "conversion";
169
+ if (INTERNAL_PATTERNS.some((p) => p.test(url))) return "internal";
170
+ return "external";
171
+ }
172
+
173
+ // src/components/OutboundLink/outbound-link-utils.ts
174
+ var LEGACY_UTM_SOURCE = "salesmind";
175
+ var EXEMPT_PATTERNS = [
176
+ /^https?:\/\/(www\.)?(stripe\.com|checkout\.stripe\.com|paypal\.com)/i,
177
+ /^https?:\/\/(www\.)?github\.com\/login\/oauth/i
178
+ ];
179
+ var isExemptUrl = (urlStr) => {
180
+ if (urlStr.startsWith("mailto:") || urlStr.startsWith("tel:")) return true;
181
+ const classification = classifyUrl(urlStr);
182
+ if (classification === "system" || classification === "protocol" || classification === "asset") {
183
+ return true;
184
+ }
185
+ return EXEMPT_PATTERNS.some((pattern) => pattern.test(urlStr));
186
+ };
187
+ var appendGovernedUTMs = (href, params, preserveExisting = true) => {
188
+ try {
189
+ const url = new URL(href);
190
+ if (preserveExisting) {
191
+ const hasAll = url.searchParams.has("utm_source") && url.searchParams.has("utm_medium") && url.searchParams.has("utm_campaign");
192
+ if (hasAll) return href;
193
+ }
194
+ return buildUtmUrl(href, params);
195
+ } catch {
196
+ return href;
197
+ }
198
+ };
199
+ var appendUTMs = (href, context, pageSlug, options) => {
200
+ try {
201
+ const url = new URL(href);
202
+ const { mediumOverride = "outbound_link", campaignOverride, preserveExisting = true } = options;
203
+ const utms = {
204
+ utm_source: LEGACY_UTM_SOURCE,
205
+ utm_medium: mediumOverride,
206
+ utm_campaign: campaignOverride || pageSlug,
207
+ utm_content: context
208
+ };
209
+ Object.entries(utms).forEach(([key, value]) => {
210
+ if (value) {
211
+ if (preserveExisting && url.searchParams.has(key)) {
212
+ return;
213
+ }
214
+ url.searchParams.set(key, value);
215
+ }
216
+ });
217
+ return url.toString();
218
+ } catch {
219
+ return href;
220
+ }
221
+ };
222
+ var OutboundLink = React.forwardRef(
223
+ ({
224
+ href,
225
+ context,
226
+ campaignOverride,
227
+ mediumOverride = "outbound_link",
228
+ preserveExistingUTM = true,
229
+ openInNewTab = true,
230
+ disableTracking = false,
231
+ utmParams,
232
+ onClick,
233
+ children,
234
+ ...props
235
+ }, ref) => {
236
+ const contextParams = useUtmDefaults();
237
+ const resolvedUtmParams = utmParams ?? contextParams;
238
+ let hostname = "";
239
+ try {
240
+ const url = new URL(href);
241
+ hostname = url.hostname;
242
+ } catch {
243
+ }
244
+ const [finalHref, setFinalHref] = React.useState(href);
245
+ React.useEffect(() => {
246
+ let isExternal = false;
247
+ let currentMedium = mediumOverride;
248
+ try {
249
+ const url = new URL(href);
250
+ const currentHost = window.location.hostname;
251
+ isExternal = url.hostname !== currentHost;
252
+ if (isExternal && currentHost.includes("sales-mind.ai") && url.hostname.includes("sales-mind.ai")) {
253
+ if (currentMedium === "outbound_link") {
254
+ currentMedium = "cross_subdomain";
255
+ }
256
+ }
257
+ } catch {
258
+ isExternal = false;
259
+ }
260
+ const isExempt = isExemptUrl(href) || disableTracking;
261
+ if (isExternal && !isExempt) {
262
+ if (resolvedUtmParams) {
263
+ setFinalHref(appendGovernedUTMs(href, resolvedUtmParams, preserveExistingUTM));
264
+ } else {
265
+ const pageSlug = window.location.pathname.replace(/^\/|\/$/g, "") || "home";
266
+ setFinalHref(appendUTMs(href, context, pageSlug, {
267
+ mediumOverride: currentMedium,
268
+ campaignOverride,
269
+ preserveExisting: preserveExistingUTM
270
+ }));
271
+ }
272
+ } else {
273
+ setFinalHref(href);
274
+ }
275
+ }, [href, context, mediumOverride, campaignOverride, preserveExistingUTM, disableTracking, resolvedUtmParams]);
276
+ const handleClick = (e) => {
277
+ if (typeof window === "undefined" || disableTracking) {
278
+ onClick?.(e);
279
+ return;
280
+ }
281
+ let clickExternal = false;
282
+ let clickCrossSubdomain = false;
283
+ let clickMedium = mediumOverride;
284
+ try {
285
+ const url = new URL(href);
286
+ const currentHost = window.location.hostname;
287
+ clickExternal = url.hostname !== currentHost;
288
+ if (clickExternal && currentHost.includes("sales-mind.ai") && url.hostname.includes("sales-mind.ai")) {
289
+ clickCrossSubdomain = true;
290
+ if (clickMedium === "outbound_link") {
291
+ clickMedium = "cross_subdomain";
292
+ }
293
+ }
294
+ } catch {
295
+ }
296
+ if (clickExternal) {
297
+ const detail = {
298
+ destination_domain: hostname,
299
+ destination_url: finalHref,
300
+ utm_medium_type: clickMedium,
301
+ page_slug: window.location.pathname,
302
+ component_location: context,
303
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
304
+ is_cross_subdomain: clickCrossSubdomain
305
+ };
306
+ const event = new CustomEvent("outbound_click", { detail });
307
+ window.dispatchEvent(event);
308
+ }
309
+ onClick?.(e);
310
+ };
311
+ const relParts = [];
312
+ let shouldOpenNewTab = openInNewTab;
313
+ try {
314
+ const url = new URL(href);
315
+ if (typeof window !== "undefined") {
316
+ const currentHost = window.location.hostname;
317
+ if (url.hostname !== currentHost && currentHost.includes("sales-mind.ai") && url.hostname.includes("sales-mind.ai")) {
318
+ shouldOpenNewTab = false;
319
+ }
320
+ }
321
+ } catch {
322
+ }
323
+ if (shouldOpenNewTab) relParts.push("noopener", "noreferrer");
324
+ if (mediumOverride === "citation") relParts.push("nofollow");
325
+ const rel = relParts.length > 0 ? relParts.join(" ") : void 0;
326
+ return (
327
+ // eslint-disable-next-line no-restricted-syntax
328
+ /* @__PURE__ */ jsxRuntime.jsx(
329
+ "a",
330
+ {
331
+ ref,
332
+ href: finalHref,
333
+ target: shouldOpenNewTab ? "_blank" : void 0,
334
+ rel,
335
+ onClick: handleClick,
336
+ ...props,
337
+ children
338
+ }
339
+ )
340
+ );
341
+ }
342
+ );
343
+ OutboundLink.displayName = "OutboundLink";
344
+ var AuthorBio = React.forwardRef(
345
+ ({
346
+ name,
347
+ role,
348
+ avatar,
349
+ bio,
350
+ links,
351
+ variant = "card",
352
+ className,
353
+ ...props
354
+ }, ref) => {
355
+ const initials = name.split(" ").map((n) => n[0]).join("").slice(0, 2);
356
+ return /* @__PURE__ */ jsxRuntime.jsxs(
357
+ "div",
358
+ {
359
+ ref,
360
+ className: clsx__default.default("ds-author-bio", `ds-author-bio--${variant}`, className),
361
+ ...props,
362
+ children: [
363
+ /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { size: variant === "compact" ? "sm" : variant === "longform" ? "lg" : "md", className: "ds-author-bio__avatar", children: [
364
+ avatar && /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: avatar, alt: name }),
365
+ /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { children: initials })
366
+ ] }),
367
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-author-bio__info", children: [
368
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-author-bio__name", children: name }),
369
+ role && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-author-bio__role", children: role }),
370
+ bio && variant !== "compact" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ds-author-bio__bio", children: bio }),
371
+ links && links.length > 0 && variant !== "compact" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-author-bio__links", children: links.map((link, i) => /* @__PURE__ */ jsxRuntime.jsxs(
372
+ OutboundLink,
373
+ {
374
+ href: link.href,
375
+ context: "author-bio-link",
376
+ className: "ds-author-bio__link",
377
+ children: [
378
+ link.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-author-bio__link-icon", children: link.icon }),
379
+ link.label
380
+ ]
381
+ },
382
+ i
383
+ )) })
384
+ ] })
385
+ ]
386
+ }
387
+ );
388
+ }
389
+ );
390
+ AuthorBio.displayName = "AuthorBio";
391
+ function useMessage() {
392
+ const intl = reactIntl.useIntl();
393
+ const formatMessage = React.useCallback(
394
+ (descriptor, values) => {
395
+ return intl.formatMessage(descriptor, values);
396
+ },
397
+ [intl]
398
+ );
399
+ return formatMessage;
400
+ }
401
+ var TableOfContents = React.forwardRef(
402
+ ({
403
+ items,
404
+ activeId: controlledActiveId,
405
+ position = "sidebar",
406
+ label,
407
+ onItemClick,
408
+ className,
409
+ ...props
410
+ }, ref) => {
411
+ const t = useMessage();
412
+ const defaultLabel = t({ id: "ds.toc.label", defaultMessage: "On this page" });
413
+ const finalLabel = label || defaultLabel;
414
+ const [observedActiveId, setObservedActiveId] = React.useState("");
415
+ const activeId = controlledActiveId ?? observedActiveId;
416
+ React.useEffect(() => {
417
+ if (controlledActiveId !== void 0) return;
418
+ if (items.length === 0) return;
419
+ const handleScroll = () => {
420
+ const headingElements = items.map((item) => ({
421
+ id: item.id,
422
+ el: document.getElementById(item.id)
423
+ })).filter((h) => !!h.el);
424
+ if (headingElements.length === 0) return;
425
+ const topOffset = 120;
426
+ const firstBelowIndex = headingElements.findIndex((h) => {
427
+ const rect = h.el.getBoundingClientRect();
428
+ return rect.top > topOffset;
429
+ });
430
+ let newActiveId = "";
431
+ if (firstBelowIndex === -1) {
432
+ newActiveId = headingElements[headingElements.length - 1].id;
433
+ } else if (firstBelowIndex === 0) {
434
+ newActiveId = "";
435
+ } else {
436
+ newActiveId = headingElements[firstBelowIndex - 1].id;
437
+ }
438
+ setObservedActiveId(newActiveId);
439
+ };
440
+ window.addEventListener("scroll", handleScroll, { passive: true });
441
+ handleScroll();
442
+ return () => window.removeEventListener("scroll", handleScroll);
443
+ }, [items, controlledActiveId]);
444
+ const handleClick = (id) => {
445
+ const el = document.getElementById(id);
446
+ if (el) {
447
+ el.scrollIntoView({ behavior: "smooth", block: "start" });
448
+ }
449
+ if (onItemClick) onItemClick(id);
450
+ };
451
+ if (items.length === 0) return null;
452
+ return /* @__PURE__ */ jsxRuntime.jsxs(
453
+ "nav",
454
+ {
455
+ ref,
456
+ className: clsx__default.default("ds-toc", `ds-toc--${position}`, className),
457
+ "aria-label": finalLabel,
458
+ ...props,
459
+ children: [
460
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-toc__label", children: finalLabel }),
461
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "ds-toc__list", children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "ds-toc__item", style: { paddingLeft: `${(item.level - 2) * 12}px` }, children: /* @__PURE__ */ jsxRuntime.jsx(
462
+ "button",
463
+ {
464
+ type: "button",
465
+ className: clsx__default.default(
466
+ "ds-toc__link",
467
+ activeId === item.id && "ds-toc__link--active"
468
+ ),
469
+ onClick: () => handleClick(item.id),
470
+ children: item.title
471
+ }
472
+ ) }, item.id)) })
473
+ ]
474
+ }
475
+ );
476
+ }
477
+ );
478
+ TableOfContents.displayName = "TableOfContents";
479
+ var ReadingProgress = React__default.default.forwardRef(
480
+ ({ targetRef, className, ...props }, ref) => {
481
+ const [progress, setProgress] = React.useState(0);
482
+ const frameRef = React.useRef(null);
483
+ React.useEffect(() => {
484
+ const handleScroll = () => {
485
+ if (frameRef.current) cancelAnimationFrame(frameRef.current);
486
+ frameRef.current = requestAnimationFrame(() => {
487
+ let percentage = 0;
488
+ if (targetRef && targetRef.current) {
489
+ const el = targetRef.current;
490
+ const rect = el.getBoundingClientRect();
491
+ const viewportHeight = window.innerHeight;
492
+ if (rect.top > viewportHeight) {
493
+ percentage = 0;
494
+ } else if (rect.bottom < 0) {
495
+ percentage = 100;
496
+ } else {
497
+ const scrollableDistance = rect.height - viewportHeight;
498
+ if (scrollableDistance <= 0) {
499
+ percentage = 100;
500
+ } else {
501
+ const scrolled = viewportHeight - rect.top;
502
+ percentage = Math.max(0, Math.min(100, scrolled / scrollableDistance * 100));
503
+ }
504
+ }
505
+ } else {
506
+ const scrollPosition = window.scrollY;
507
+ const scrollHeight = document.body.scrollHeight - window.innerHeight;
508
+ percentage = scrollHeight > 0 ? scrollPosition / scrollHeight * 100 : 0;
509
+ percentage = Math.max(0, Math.min(100, percentage));
510
+ }
511
+ setProgress(percentage);
512
+ });
513
+ };
514
+ window.addEventListener("scroll", handleScroll, { passive: true });
515
+ window.addEventListener("resize", handleScroll, { passive: true });
516
+ handleScroll();
517
+ return () => {
518
+ if (frameRef.current) cancelAnimationFrame(frameRef.current);
519
+ window.removeEventListener("scroll", handleScroll);
520
+ window.removeEventListener("resize", handleScroll);
521
+ };
522
+ }, [targetRef]);
523
+ return /* @__PURE__ */ jsxRuntime.jsx(
524
+ "div",
525
+ {
526
+ ref,
527
+ className: clsx__default.default("ds-reading-progress", className),
528
+ ...props,
529
+ children: /* @__PURE__ */ jsxRuntime.jsx(
530
+ "div",
531
+ {
532
+ className: "ds-reading-progress__bar",
533
+ style: { transform: `scaleX(${progress / 100})` }
534
+ }
535
+ )
536
+ }
537
+ );
538
+ }
539
+ );
540
+ ReadingProgress.displayName = "ReadingProgress";
541
+ var LongFormLayout = React__default.default.forwardRef(
542
+ ({ children, sidebar, className, ...props }, ref) => {
543
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: clsx__default.default("ds-longform-layout", className), ...props, children: [
544
+ /* @__PURE__ */ jsxRuntime.jsx("article", { className: "ds-longform-layout__main", children }),
545
+ sidebar && /* @__PURE__ */ jsxRuntime.jsx("aside", { className: "ds-longform-layout__sidebar", children: sidebar })
546
+ ] });
547
+ }
548
+ );
549
+ LongFormLayout.displayName = "LongFormLayout";
550
+ var InsightCallout = React__default.default.forwardRef(
551
+ ({ children, icon, title, className, ...props }, ref) => {
552
+ return /* @__PURE__ */ jsxRuntime.jsxs("aside", { ref, className: clsx__default.default("ds-insight-callout", className), ...props, children: [
553
+ icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-insight-callout__icon", children: icon }),
554
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-insight-callout__content", children: [
555
+ title && /* @__PURE__ */ jsxRuntime.jsx("h5", { className: "ds-insight-callout__title", children: title }),
556
+ children
557
+ ] })
558
+ ] });
559
+ }
560
+ );
561
+ InsightCallout.displayName = "InsightCallout";
562
+ var DataHighlight = React__default.default.forwardRef(
563
+ ({ stat, label, children, className, ...props }, ref) => {
564
+ return /* @__PURE__ */ jsxRuntime.jsxs("figure", { ref, className: clsx__default.default("ds-data-highlight", className), ...props, children: [
565
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-data-highlight__stat-group", children: [
566
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-data-highlight__stat", children: stat }),
567
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-data-highlight__label", children: label })
568
+ ] }),
569
+ children && /* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: "ds-data-highlight__caption", children })
570
+ ] });
571
+ }
572
+ );
573
+ DataHighlight.displayName = "DataHighlight";
574
+ var AnalyticsContext = React.createContext(null);
575
+
576
+ // src/web/analytics/use-analytics.tsx
577
+ var NOOP_VALUE = {
578
+ track: () => {
579
+ }
580
+ };
581
+ function useAnalytics() {
582
+ return React.useContext(AnalyticsContext) ?? NOOP_VALUE;
583
+ }
584
+ var ArticleCard = React.forwardRef(
585
+ ({
586
+ href,
587
+ title,
588
+ excerpt,
589
+ imageUrl,
590
+ imageAlt = "",
591
+ category,
592
+ date,
593
+ readingTime,
594
+ author,
595
+ variant = "vertical",
596
+ className,
597
+ onClick,
598
+ ...props
599
+ }, ref) => {
600
+ const { track } = useAnalytics();
601
+ const handleClick = (e) => {
602
+ track("article_click", { url: href, title, category });
603
+ if (onClick) onClick(e);
604
+ };
605
+ return /* @__PURE__ */ jsxRuntime.jsxs(
606
+ OutboundLink,
607
+ {
608
+ ref,
609
+ href,
610
+ context: "article-card",
611
+ className: clsx__default.default(
612
+ "ds-article-card",
613
+ `ds-article-card--${variant}`,
614
+ !imageUrl && "ds-article-card--no-image",
615
+ className
616
+ ),
617
+ onClick: handleClick,
618
+ ...props,
619
+ children: [
620
+ imageUrl ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-article-card__image-wrapper", children: [
621
+ /* @__PURE__ */ jsxRuntime.jsx(
622
+ "img",
623
+ {
624
+ src: imageUrl,
625
+ alt: imageAlt,
626
+ className: "ds-article-card__image",
627
+ loading: "lazy"
628
+ }
629
+ ),
630
+ category && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-article-card__category-badge", children: category })
631
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-article-card__placeholder", children: [
632
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "ds-article-card__placeholder-icon", "aria-hidden": "true" }),
633
+ category && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-article-card__category-badge", children: category })
634
+ ] }),
635
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-article-card__content", children: [
636
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "ds-article-card__title", children: title }),
637
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ds-article-card__excerpt", children: excerpt }),
638
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-article-card__meta", children: [
639
+ (date || author) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-article-card__meta-primary", children: [
640
+ author && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-article-card__author", children: author }),
641
+ author && date && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-article-card__dot", "aria-hidden": "true", children: "\u2022" }),
642
+ date && /* @__PURE__ */ jsxRuntime.jsx("time", { dateTime: date, className: "ds-article-card__date", children: date })
643
+ ] }),
644
+ readingTime && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-article-card__meta-secondary", children: [
645
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { size: 14, "aria-hidden": "true" }),
646
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
647
+ readingTime,
648
+ " min read"
649
+ ] })
650
+ ] })
651
+ ] }),
652
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-article-card__footer", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-article-card__read-more", children: [
653
+ "Read article",
654
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { size: 16, className: "ds-article-card__arrow" })
655
+ ] }) })
656
+ ] })
657
+ ]
658
+ }
659
+ );
660
+ }
661
+ );
662
+ ArticleCard.displayName = "ArticleCard";
663
+ var ArticleLayout = React.forwardRef(
664
+ ({
665
+ children,
666
+ title,
667
+ author,
668
+ date,
669
+ heroImage,
670
+ sidebar,
671
+ className,
672
+ ...props
673
+ }, ref) => {
674
+ const { track } = useAnalytics();
675
+ React__default.default.useEffect(() => {
676
+ let maxScroll = 0;
677
+ const handleScroll = () => {
678
+ const docHeight = document.documentElement.scrollHeight - window.innerHeight;
679
+ if (docHeight > 0) {
680
+ const scrollPercent = Math.round(window.scrollY / docHeight * 100);
681
+ if (scrollPercent > maxScroll) {
682
+ maxScroll = scrollPercent;
683
+ if (maxScroll === 25) track("article_scroll", { milestone: 25 });
684
+ if (maxScroll === 50) track("article_scroll", { milestone: 50 });
685
+ if (maxScroll === 75) track("article_scroll", { milestone: 75 });
686
+ if (maxScroll === 100) track("article_scroll", { milestone: 100 });
687
+ }
688
+ }
689
+ };
690
+ window.addEventListener("scroll", handleScroll, { passive: true });
691
+ return () => window.removeEventListener("scroll", handleScroll);
692
+ }, [track]);
693
+ return /* @__PURE__ */ jsxRuntime.jsxs(
694
+ "article",
695
+ {
696
+ ref,
697
+ className: clsx__default.default("ds-article-layout", className),
698
+ ...props,
699
+ children: [
700
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "ds-article-layout__header", children: [
701
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "ds-article-layout__title", children: title }),
702
+ (author || date) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-article-layout__meta", children: [
703
+ author && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-article-layout__author", children: author }),
704
+ author && date && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-article-layout__dot", "aria-hidden": "true", children: "\u2022" }),
705
+ date && /* @__PURE__ */ jsxRuntime.jsx("time", { className: "ds-article-layout__date", children: date })
706
+ ] })
707
+ ] }),
708
+ heroImage && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-article-layout__hero", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: heroImage, alt: "", "aria-hidden": "true" }) }),
709
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx__default.default(
710
+ "ds-article-layout__body",
711
+ sidebar && "ds-article-layout__body--with-sidebar"
712
+ ), children: [
713
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-article-layout__content ds-prose", children }),
714
+ sidebar && /* @__PURE__ */ jsxRuntime.jsx("aside", { className: "ds-article-layout__sidebar", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-article-layout__sidebar-inner", children: sidebar }) })
715
+ ] })
716
+ ]
717
+ }
718
+ );
719
+ }
720
+ );
721
+ ArticleLayout.displayName = "ArticleLayout";
722
+
723
+ // src/tokens/spacing.ts
724
+ var SPACING = {
725
+ 1: "var(--space-1)",
726
+ 2: "var(--space-2)",
727
+ 3: "var(--space-3)",
728
+ 4: "var(--space-4)",
729
+ 5: "var(--space-5)",
730
+ 6: "var(--space-6)",
731
+ 8: "var(--space-8)",
732
+ 10: "var(--space-10)",
733
+ 12: "var(--space-12)",
734
+ 16: "var(--space-16)",
735
+ 20: "var(--space-20)"
736
+ };
737
+
738
+ // src/components/LayoutPrimitives/utils.ts
739
+ var SPACING_ALIASES = {
740
+ xs: "var(--space-2)",
741
+ sm: "var(--space-3)",
742
+ md: "var(--space-4)",
743
+ lg: "var(--space-6)",
744
+ xl: "var(--space-8)",
745
+ "2xl": "var(--space-12)"
746
+ };
747
+ function resolveSpacing(value) {
748
+ if (value === void 0) return void 0;
749
+ if (typeof value === "number" && SPACING[value]) {
750
+ return SPACING[value];
751
+ }
752
+ if (typeof value === "string" && value in SPACING_ALIASES) {
753
+ return SPACING_ALIASES[value];
754
+ }
755
+ return String(value);
756
+ }
757
+ function extractSpacingStyles(props) {
758
+ const styles = {};
759
+ if (props.m !== void 0) styles.margin = resolveSpacing(props.m);
760
+ if (props.mt !== void 0) styles.marginTop = resolveSpacing(props.mt);
761
+ if (props.mb !== void 0) styles.marginBottom = resolveSpacing(props.mb);
762
+ if (props.ml !== void 0) styles.marginLeft = resolveSpacing(props.ml);
763
+ if (props.mr !== void 0) styles.marginRight = resolveSpacing(props.mr);
764
+ if (props.mx !== void 0) {
765
+ styles.marginLeft = resolveSpacing(props.mx);
766
+ styles.marginRight = resolveSpacing(props.mx);
767
+ }
768
+ if (props.my !== void 0) {
769
+ styles.marginTop = resolveSpacing(props.my);
770
+ styles.marginBottom = resolveSpacing(props.my);
771
+ }
772
+ if (props.p !== void 0) styles.padding = resolveSpacing(props.p);
773
+ if (props.pt !== void 0) styles.paddingTop = resolveSpacing(props.pt);
774
+ if (props.pb !== void 0) styles.paddingBottom = resolveSpacing(props.pb);
775
+ if (props.pl !== void 0) styles.paddingLeft = resolveSpacing(props.pl);
776
+ if (props.pr !== void 0) styles.paddingRight = resolveSpacing(props.pr);
777
+ if (props.px !== void 0) {
778
+ styles.paddingLeft = resolveSpacing(props.px);
779
+ styles.paddingRight = resolveSpacing(props.px);
780
+ }
781
+ if (props.py !== void 0) {
782
+ styles.paddingTop = resolveSpacing(props.py);
783
+ styles.paddingBottom = resolveSpacing(props.py);
784
+ }
785
+ if (props.gap !== void 0) styles.gap = resolveSpacing(props.gap);
786
+ return styles;
787
+ }
788
+ var Box = React.forwardRef(
789
+ ({ as: Component = "div", className, style, children, ...props }, ref) => {
790
+ const spacingStyles = extractSpacingStyles(props);
791
+ const { m, mt, mb, ml, mr, mx, my, p, pt, pb, pl, pr, px, py, gap, ...domProps } = props;
792
+ return /* @__PURE__ */ jsxRuntime.jsx(
793
+ Component,
794
+ {
795
+ ref,
796
+ className: clsx__default.default("ds-box", className),
797
+ style: { ...spacingStyles, ...style },
798
+ ...domProps,
799
+ children
800
+ }
801
+ );
802
+ }
803
+ );
804
+ Box.displayName = "Box";
805
+ var CONTAINER_SIZE_MAP = {
806
+ sm: "768px",
807
+ // 48rem — max-w-3xl
808
+ md: "1024px",
809
+ // 64rem — max-w-5xl
810
+ lg: "1152px",
811
+ // 72rem — max-w-6xl
812
+ xl: "1280px",
813
+ // 80rem — max-w-7xl
814
+ full: "100%"
815
+ };
816
+ var Container = React.forwardRef(
817
+ ({ size, fluid, maxWidth, className, style, ...props }, ref) => {
818
+ let resolvedMaxWidth;
819
+ if (fluid) {
820
+ resolvedMaxWidth = "100%";
821
+ } else if (size) {
822
+ resolvedMaxWidth = CONTAINER_SIZE_MAP[size];
823
+ } else {
824
+ resolvedMaxWidth = maxWidth || "var(--container-default-max, 1200px)";
825
+ }
826
+ return /* @__PURE__ */ jsxRuntime.jsx(
827
+ Box,
828
+ {
829
+ ref,
830
+ className: clsx__default.default("ds-container", className),
831
+ style: {
832
+ maxWidth: resolvedMaxWidth,
833
+ ...style
834
+ },
835
+ ...props
836
+ }
837
+ );
838
+ }
839
+ );
840
+ Container.displayName = "Container";
841
+ var SectionHeader = React.forwardRef(
842
+ ({ title, subtitle, eyebrow, align = "center", className, ...props }, ref) => {
843
+ if (!title && !subtitle && !eyebrow) return null;
844
+ return /* @__PURE__ */ jsxRuntime.jsxs(
845
+ "header",
846
+ {
847
+ ref,
848
+ className: clsx__default.default("ds-section-header", `ds-section-header--${align}`, className),
849
+ ...props,
850
+ children: [
851
+ eyebrow && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-section-header__eyebrow", children: eyebrow }),
852
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "ds-section-header__title", children: title }),
853
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "ds-section-header__subtitle", children: subtitle })
854
+ ]
855
+ }
856
+ );
857
+ }
858
+ );
859
+ SectionHeader.displayName = "SectionHeader";
860
+ var SectionShell = React.forwardRef(
861
+ ({
862
+ className,
863
+ children,
864
+ background = "default",
865
+ padding = "md",
866
+ containerSize,
867
+ containerFluid = false,
868
+ ...props
869
+ }, ref) => {
870
+ return /* @__PURE__ */ jsxRuntime.jsx(
871
+ "section",
872
+ {
873
+ ref,
874
+ className: clsx__default.default(
875
+ "ds-section",
876
+ `ds-section--bg-${background}`,
877
+ `ds-section--padding-${padding}`,
878
+ className
879
+ ),
880
+ ...props,
881
+ children: /* @__PURE__ */ jsxRuntime.jsx(
882
+ Container,
883
+ {
884
+ size: containerSize === "fluid" ? "full" : containerSize,
885
+ fluid: containerFluid || containerSize === "fluid",
886
+ children
887
+ }
888
+ )
889
+ }
890
+ );
891
+ }
892
+ );
893
+ SectionShell.displayName = "SectionShell";
894
+ var RelatedContent = React.forwardRef(
895
+ ({
896
+ eyebrow,
897
+ title = "Related Articles",
898
+ items,
899
+ maxVisible,
900
+ className,
901
+ ...props
902
+ }, ref) => {
903
+ const visibleItems = maxVisible ? items.slice(0, maxVisible) : items;
904
+ if (visibleItems.length === 0) return null;
905
+ return /* @__PURE__ */ jsxRuntime.jsxs(
906
+ SectionShell,
907
+ {
908
+ ref,
909
+ className: clsx__default.default("ds-related-content", className),
910
+ background: "muted",
911
+ ...props,
912
+ children: [
913
+ /* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { eyebrow, title }),
914
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-related-content__grid", children: visibleItems.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(ArticleCard, { ...item }, i)) })
915
+ ]
916
+ }
917
+ );
918
+ }
919
+ );
920
+ RelatedContent.displayName = "RelatedContent";
921
+ var VersionedUpgradeAlert = React__default.default.forwardRef(
922
+ ({ seriesName, viewedYear, latestYear, latestUrl, deltaSummary, className, ...props }, ref) => {
923
+ const [dismissed, setDismissed] = React.useState(false);
924
+ if (dismissed) return null;
925
+ return /* @__PURE__ */ jsxRuntime.jsxs(
926
+ "div",
927
+ {
928
+ ref,
929
+ className: clsx__default.default("ds-versioned-alert", className),
930
+ role: "alert",
931
+ ...props,
932
+ children: [
933
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-versioned-alert__content", children: [
934
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-versioned-alert__icon", children: "\u26A0\uFE0F" }),
935
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-versioned-alert__text", children: [
936
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Outdated Edition:" }),
937
+ " You are viewing the ",
938
+ viewedYear,
939
+ " edition of ",
940
+ seriesName,
941
+ ". The ",
942
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
943
+ latestYear,
944
+ " edition"
945
+ ] }),
946
+ " is now available.",
947
+ deltaSummary && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ds-versioned-alert__delta", children: [
948
+ " ",
949
+ deltaSummary
950
+ ] })
951
+ ] })
952
+ ] }),
953
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-versioned-alert__actions", children: [
954
+ /* @__PURE__ */ jsxRuntime.jsxs(OutboundLink, { href: latestUrl, context: "versioned-alert-view-latest", className: "ds-versioned-alert__button ds-button ds-button--primary ds-button--sm", openInNewTab: false, children: [
955
+ "View ",
956
+ latestYear,
957
+ " Edition"
958
+ ] }),
959
+ /* @__PURE__ */ jsxRuntime.jsx(
960
+ "button",
961
+ {
962
+ className: "ds-versioned-alert__close",
963
+ onClick: () => setDismissed(true),
964
+ "aria-label": "Dismiss alert",
965
+ children: "\xD7"
966
+ }
967
+ )
968
+ ] })
969
+ ]
970
+ }
971
+ );
972
+ }
973
+ );
974
+ VersionedUpgradeAlert.displayName = "VersionedUpgradeAlert";
975
+ var VersionedSeriesNavigator = React__default.default.forwardRef(
976
+ ({ seriesName, hubUrl, editions, className, ...props }, ref) => {
977
+ const sortedEditions = [...editions].sort((a, b) => a.year - b.year);
978
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: clsx__default.default("ds-versioned-navigator", className), ...props, children: [
979
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-versioned-navigator__header", children: [
980
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-versioned-navigator__label", children: "Series" }),
981
+ /* @__PURE__ */ jsxRuntime.jsxs(OutboundLink, { href: hubUrl, context: "versioned-navigator-hub", className: "ds-versioned-navigator__title", openInNewTab: false, children: [
982
+ seriesName,
983
+ " Hub"
984
+ ] })
985
+ ] }),
986
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-versioned-navigator__timeline", children: sortedEditions.map((edition, idx) => /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
987
+ idx > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-versioned-navigator__connector" }),
988
+ /* @__PURE__ */ jsxRuntime.jsx(
989
+ OutboundLink,
990
+ {
991
+ href: edition.url,
992
+ context: "versioned-navigator-edition",
993
+ className: clsx__default.default(
994
+ "ds-versioned-navigator__node",
995
+ edition.isCurrent && "ds-versioned-navigator__node--active"
996
+ ),
997
+ "aria-current": edition.isCurrent ? "page" : void 0,
998
+ openInNewTab: false,
999
+ children: edition.year
1000
+ }
1001
+ )
1002
+ ] }, edition.year)) })
1003
+ ] });
1004
+ }
1005
+ );
1006
+ VersionedSeriesNavigator.displayName = "VersionedSeriesNavigator";
1007
+ var BrowserFrame = React.forwardRef(
1008
+ ({
1009
+ variant = "browser",
1010
+ children,
1011
+ url,
1012
+ showControls,
1013
+ withGlow = false,
1014
+ aspectRatio = "16/9",
1015
+ className,
1016
+ ...props
1017
+ }, ref) => {
1018
+ const hasControls = showControls ?? (variant === "browser" || variant === "app");
1019
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1020
+ "div",
1021
+ {
1022
+ ref,
1023
+ className: clsx__default.default(
1024
+ "ds-browser-frame",
1025
+ `ds-browser-frame--${variant}`,
1026
+ withGlow && "ds-browser-frame--glow",
1027
+ className
1028
+ ),
1029
+ ...props,
1030
+ children: [
1031
+ variant !== "minimal" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-browser-frame__chrome", children: [
1032
+ hasControls && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-browser-frame__controls", "aria-hidden": "true", children: [
1033
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-browser-frame__dot ds-browser-frame__dot--red" }),
1034
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-browser-frame__dot ds-browser-frame__dot--yellow" }),
1035
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-browser-frame__dot ds-browser-frame__dot--green" })
1036
+ ] }),
1037
+ variant === "browser" && url && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ds-browser-frame__url-bar", children: [
1038
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", "aria-hidden": "true", className: "ds-browser-frame__lock", children: [
1039
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 5V4a3 3 0 116 0v1", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
1040
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "5", width: "8", height: "6", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" })
1041
+ ] }),
1042
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ds-browser-frame__url-text", children: url })
1043
+ ] })
1044
+ ] }),
1045
+ /* @__PURE__ */ jsxRuntime.jsx(
1046
+ "div",
1047
+ {
1048
+ className: "ds-browser-frame__content",
1049
+ style: aspectRatio !== "auto" ? { aspectRatio } : void 0,
1050
+ children
1051
+ }
1052
+ ),
1053
+ variant === "mobile" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ds-browser-frame__notch", "aria-hidden": "true" })
1054
+ ]
1055
+ }
1056
+ );
1057
+ }
1058
+ );
1059
+ BrowserFrame.displayName = "BrowserFrame";
1060
+
1061
+ exports.ArticleCard = ArticleCard;
1062
+ exports.ArticleLayout = ArticleLayout;
1063
+ exports.AuthorBio = AuthorBio;
1064
+ exports.BrowserFrame = BrowserFrame;
1065
+ exports.DataHighlight = DataHighlight;
1066
+ exports.InsightCallout = InsightCallout;
1067
+ exports.LongFormLayout = LongFormLayout;
1068
+ exports.ReadingProgress = ReadingProgress;
1069
+ exports.RelatedContent = RelatedContent;
1070
+ exports.TableOfContents = TableOfContents;
1071
+ exports.VersionedSeriesNavigator = VersionedSeriesNavigator;
1072
+ exports.VersionedUpgradeAlert = VersionedUpgradeAlert;
1073
+ //# sourceMappingURL=out.js.map
1074
+ //# sourceMappingURL=index.cjs.map