@salesmind-ai/design-system 1.7.0 → 1.9.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.
- package/dist/ChangeEmail-BuUhjW0o.d.cts +226 -0
- package/dist/ChangeEmail-BuUhjW0o.d.ts +226 -0
- package/dist/{chunk-3NS6X2R4.cjs → chunk-5EIBL6DQ.cjs} +133 -38
- package/dist/chunk-5EIBL6DQ.cjs.map +1 -0
- package/dist/chunk-AI2YEYT4.js +1368 -0
- package/dist/chunk-AI2YEYT4.js.map +1 -0
- package/dist/{chunk-4QQKREVH.cjs → chunk-LM3UJILC.cjs} +3 -3
- package/dist/{chunk-4QQKREVH.cjs.map → chunk-LM3UJILC.cjs.map} +1 -1
- package/dist/{chunk-K7NQ7TQG.cjs → chunk-M4MLGT4B.cjs} +84 -27
- package/dist/chunk-M4MLGT4B.cjs.map +1 -0
- package/dist/{chunk-6BUS7RMS.js → chunk-Q3YVBUKQ.js} +133 -38
- package/dist/chunk-Q3YVBUKQ.js.map +1 -0
- package/dist/{chunk-25TUCNN6.js → chunk-QVGDMAZY.js} +84 -27
- package/dist/chunk-QVGDMAZY.js.map +1 -0
- package/dist/{chunk-2TC5EVSJ.js → chunk-TPZ3PKSF.js} +3 -3
- package/dist/{chunk-2TC5EVSJ.js.map → chunk-TPZ3PKSF.js.map} +1 -1
- package/dist/chunk-YWJKSY5C.cjs +1381 -0
- package/dist/chunk-YWJKSY5C.cjs.map +1 -0
- package/dist/index.cjs +57 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +2426 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/marketing/index.cjs +27 -27
- package/dist/marketing/index.js +1 -1
- package/dist/nav/index.cjs +10 -10
- package/dist/nav/index.css +54 -0
- package/dist/nav/index.css.map +1 -1
- package/dist/nav/index.d.cts +9 -0
- package/dist/nav/index.d.ts +9 -0
- package/dist/nav/index.js +1 -1
- package/dist/onboarding/index.cjs +5870 -0
- package/dist/onboarding/index.cjs.map +1 -0
- package/dist/onboarding/index.css +557 -0
- package/dist/onboarding/index.css.map +1 -0
- package/dist/onboarding/index.d.cts +1589 -0
- package/dist/onboarding/index.d.ts +1589 -0
- package/dist/onboarding/index.js +5736 -0
- package/dist/onboarding/index.js.map +1 -0
- package/dist/styles/styles.css +2593 -0
- package/dist/v2-auth/index.cjs +59 -0
- package/dist/v2-auth/index.cjs.map +1 -0
- package/dist/v2-auth/index.css +3360 -0
- package/dist/v2-auth/index.css.map +1 -0
- package/dist/v2-auth/index.d.cts +76 -0
- package/dist/v2-auth/index.d.ts +76 -0
- package/dist/v2-auth/index.js +24 -0
- package/dist/v2-auth/index.js.map +1 -0
- package/dist/web/index.cjs +7 -7
- package/dist/web/index.d.cts +1 -1
- package/dist/web/index.d.ts +1 -1
- package/dist/web/index.js +1 -1
- package/dist/web/server/index.cjs +7 -7
- package/dist/web/server/index.d.cts +91 -27
- package/dist/web/server/index.d.ts +91 -27
- package/dist/web/server/index.js +1 -1
- package/package.json +14 -2
- package/dist/chunk-25TUCNN6.js.map +0 -1
- package/dist/chunk-3NS6X2R4.cjs.map +0 -1
- package/dist/chunk-6BUS7RMS.js.map +0 -1
- package/dist/chunk-K7NQ7TQG.cjs.map +0 -1
|
@@ -59,8 +59,15 @@ function createEntityIds(brand) {
|
|
|
59
59
|
function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"]) {
|
|
60
60
|
const ENTITY_IDS = createEntityIds(brand);
|
|
61
61
|
return {
|
|
62
|
-
/**
|
|
63
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Organization schema — Homepage + About page.
|
|
64
|
+
*
|
|
65
|
+
* Note: schema.org does NOT allow `inLanguage` or `availableLanguage` on
|
|
66
|
+
* Organization. The multilingual signal is carried by `knowsLanguage`
|
|
67
|
+
* (valid on Organization, BCP-47 codes). The `locale` param is retained
|
|
68
|
+
* for call-site signature stability but no longer emitted here.
|
|
69
|
+
*/
|
|
70
|
+
organization(_locale = "en") {
|
|
64
71
|
return {
|
|
65
72
|
"@context": "https://schema.org",
|
|
66
73
|
"@type": "Organization",
|
|
@@ -72,8 +79,7 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
72
79
|
url: `${brand.url}/logo.svg`
|
|
73
80
|
},
|
|
74
81
|
description: brand.description,
|
|
75
|
-
|
|
76
|
-
availableLanguage: [...supportedLanguages],
|
|
82
|
+
knowsLanguage: [...supportedLanguages],
|
|
77
83
|
founder: {
|
|
78
84
|
"@type": "Person",
|
|
79
85
|
name: brand.founder
|
|
@@ -124,7 +130,17 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
124
130
|
name: title,
|
|
125
131
|
description,
|
|
126
132
|
inLanguage: locale,
|
|
127
|
-
|
|
133
|
+
// Reference stub to the site-wide WebSite node. `url`/`name` are
|
|
134
|
+
// included (when the brand provides them) so the reference stands as a
|
|
135
|
+
// complete WebSite on pages rendered independently of the WebSite node,
|
|
136
|
+
// per schema.org @id-linking guidance. Guarded so a brand without
|
|
137
|
+
// `url`/`name` never emits `undefined`.
|
|
138
|
+
isPartOf: {
|
|
139
|
+
"@type": "WebSite",
|
|
140
|
+
"@id": ENTITY_IDS.website,
|
|
141
|
+
...brand.url ? { url: brand.url } : {},
|
|
142
|
+
...brand.name ? { name: brand.name } : {}
|
|
143
|
+
},
|
|
128
144
|
breadcrumb: { "@id": ENTITY_IDS.breadcrumb(path) },
|
|
129
145
|
potentialAction: {
|
|
130
146
|
"@type": "ReadAction",
|
|
@@ -136,6 +152,7 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
136
152
|
/** SoftwareApplication schema — Platform Hub, Platform Feature, Pricing. */
|
|
137
153
|
softwareApplication(name, description, url, locale = "en", options = {}) {
|
|
138
154
|
const aggregateRating = options.aggregateRating ?? brand.aggregateRating;
|
|
155
|
+
const offers = options.offers ?? brand.softwareApplicationOffers;
|
|
139
156
|
return {
|
|
140
157
|
"@context": "https://schema.org",
|
|
141
158
|
"@type": "SoftwareApplication",
|
|
@@ -145,8 +162,21 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
145
162
|
url: url || brand.url,
|
|
146
163
|
applicationCategory: "BusinessApplication",
|
|
147
164
|
operatingSystem: "Web",
|
|
165
|
+
// `inLanguage` is valid — SoftwareApplication is a CreativeWork subtype.
|
|
166
|
+
// `availableLanguage` is NOT valid on SoftwareApplication and is dropped.
|
|
148
167
|
inLanguage: locale,
|
|
149
|
-
|
|
168
|
+
// Google requires `offers` with a price. We expose only the price floor
|
|
169
|
+
// via AggregateOffer so A/B-tested tier prices stay hidden.
|
|
170
|
+
...offers ? {
|
|
171
|
+
offers: {
|
|
172
|
+
"@type": "AggregateOffer",
|
|
173
|
+
lowPrice: offers.lowPrice,
|
|
174
|
+
priceCurrency: offers.priceCurrency,
|
|
175
|
+
offerCount: offers.offerCount,
|
|
176
|
+
url: offers.url ?? `${brand.url}/pricing`,
|
|
177
|
+
availability: "https://schema.org/InStock"
|
|
178
|
+
}
|
|
179
|
+
} : {},
|
|
150
180
|
...aggregateRating ? {
|
|
151
181
|
aggregateRating: {
|
|
152
182
|
"@type": "AggregateRating",
|
|
@@ -226,15 +256,18 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
226
256
|
}))
|
|
227
257
|
};
|
|
228
258
|
},
|
|
229
|
-
/**
|
|
230
|
-
|
|
259
|
+
/**
|
|
260
|
+
* BreadcrumbList schema — Every public page.
|
|
261
|
+
* `inLanguage` is NOT valid on BreadcrumbList and is not emitted. The
|
|
262
|
+
* `locale` param is retained for call-site signature stability.
|
|
263
|
+
*/
|
|
264
|
+
breadcrumb(items, _locale = "en") {
|
|
231
265
|
const lastUrl = items.length > 0 ? items[items.length - 1].url : "/";
|
|
232
266
|
const path = lastUrl.startsWith("http") ? new URL(lastUrl).pathname : lastUrl;
|
|
233
267
|
return {
|
|
234
268
|
"@context": "https://schema.org",
|
|
235
269
|
"@type": "BreadcrumbList",
|
|
236
270
|
"@id": ENTITY_IDS.breadcrumb(path),
|
|
237
|
-
inLanguage: locale,
|
|
238
271
|
itemListElement: items.map((item, index) => ({
|
|
239
272
|
"@type": "ListItem",
|
|
240
273
|
position: index + 1,
|
|
@@ -243,8 +276,12 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
243
276
|
}))
|
|
244
277
|
};
|
|
245
278
|
},
|
|
246
|
-
/**
|
|
247
|
-
|
|
279
|
+
/**
|
|
280
|
+
* Person schema — Team page, Blog author, Comparison author.
|
|
281
|
+
* `inLanguage` is NOT valid on Person (Person is not a CreativeWork) and is
|
|
282
|
+
* not emitted. The `locale` param is retained for signature stability.
|
|
283
|
+
*/
|
|
284
|
+
person(person, _locale = "en") {
|
|
248
285
|
const slug = person.slug || person.name.toLowerCase().replace(/\s+/g, "-");
|
|
249
286
|
return {
|
|
250
287
|
"@context": "https://schema.org",
|
|
@@ -254,7 +291,6 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
254
291
|
jobTitle: person.jobTitle,
|
|
255
292
|
url: person.url,
|
|
256
293
|
image: person.image,
|
|
257
|
-
inLanguage: locale,
|
|
258
294
|
worksFor: person.worksFor || {
|
|
259
295
|
"@type": "Organization",
|
|
260
296
|
"@id": ENTITY_IDS.organization,
|
|
@@ -298,8 +334,12 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
298
334
|
} : {}
|
|
299
335
|
};
|
|
300
336
|
},
|
|
301
|
-
/**
|
|
302
|
-
|
|
337
|
+
/**
|
|
338
|
+
* Product + multiple Offers schema — Pricing page.
|
|
339
|
+
* `inLanguage` is NOT valid on Product and is not emitted. The `locale`
|
|
340
|
+
* param is retained for call-site signature stability.
|
|
341
|
+
*/
|
|
342
|
+
productWithOffers(plans, testimonials = [], _locale = "en") {
|
|
303
343
|
return {
|
|
304
344
|
"@context": "https://schema.org",
|
|
305
345
|
"@type": "Product",
|
|
@@ -311,7 +351,6 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
311
351
|
"@id": ENTITY_IDS.organization,
|
|
312
352
|
name: brand.name
|
|
313
353
|
},
|
|
314
|
-
inLanguage: locale,
|
|
315
354
|
...testimonials.length > 0 ? { aggregateRating: aggregateRatingFromTestimonials(testimonials) } : {},
|
|
316
355
|
offers: plans.map((plan) => ({
|
|
317
356
|
"@type": "Offer",
|
|
@@ -355,7 +394,12 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
355
394
|
...transcript.transcript_text ? { transcript: transcript.transcript_text } : {}
|
|
356
395
|
};
|
|
357
396
|
},
|
|
358
|
-
/**
|
|
397
|
+
/**
|
|
398
|
+
* CustomerOrganization schema — Customer's company for Success Story pages.
|
|
399
|
+
* `industry` is NOT valid on Organization (schema.org allows only the coded
|
|
400
|
+
* `naics` / `isicV4`, plus free-text `keywords`). The free-text industry
|
|
401
|
+
* value is carried by `keywords`.
|
|
402
|
+
*/
|
|
359
403
|
customerOrganization(meta) {
|
|
360
404
|
return {
|
|
361
405
|
"@context": "https://schema.org",
|
|
@@ -365,7 +409,7 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
365
409
|
...meta.url ? { url: meta.url } : {},
|
|
366
410
|
...meta.logo ? { logo: meta.logo } : {},
|
|
367
411
|
...meta.description ? { description: meta.description } : {},
|
|
368
|
-
...meta.industry ? {
|
|
412
|
+
...meta.industry ? { keywords: meta.industry } : {},
|
|
369
413
|
...meta.sameAs && meta.sameAs.length > 0 ? { sameAs: meta.sameAs } : {}
|
|
370
414
|
};
|
|
371
415
|
},
|
|
@@ -408,8 +452,12 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
408
452
|
}))
|
|
409
453
|
};
|
|
410
454
|
},
|
|
411
|
-
/**
|
|
412
|
-
|
|
455
|
+
/**
|
|
456
|
+
* Service schema — Growth motion service offerings.
|
|
457
|
+
* Neither `inLanguage` nor `availableLanguage` is valid on Service, so both
|
|
458
|
+
* are dropped. The `locale` param is retained for signature stability.
|
|
459
|
+
*/
|
|
460
|
+
service(motion, _locale = "en") {
|
|
413
461
|
return {
|
|
414
462
|
"@context": "https://schema.org",
|
|
415
463
|
"@type": "Service",
|
|
@@ -422,8 +470,6 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
422
470
|
"@id": ENTITY_IDS.organization,
|
|
423
471
|
name: brand.name
|
|
424
472
|
},
|
|
425
|
-
inLanguage: locale,
|
|
426
|
-
availableLanguage: [...supportedLanguages],
|
|
427
473
|
areaServed: "Worldwide",
|
|
428
474
|
...motion.price ? {
|
|
429
475
|
offers: {
|
|
@@ -436,8 +482,12 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
436
482
|
termsOfService: `${brand.url}/legal/terms`
|
|
437
483
|
};
|
|
438
484
|
},
|
|
439
|
-
/**
|
|
440
|
-
|
|
485
|
+
/**
|
|
486
|
+
* JobPosting schema — Career detail pages.
|
|
487
|
+
* `inLanguage` is NOT valid on JobPosting and is not emitted. The `locale`
|
|
488
|
+
* param is retained for call-site signature stability.
|
|
489
|
+
*/
|
|
490
|
+
jobPosting(job, _locale = "en") {
|
|
441
491
|
return {
|
|
442
492
|
"@context": "https://schema.org",
|
|
443
493
|
"@type": "JobPosting",
|
|
@@ -462,8 +512,7 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
462
512
|
}
|
|
463
513
|
} : {
|
|
464
514
|
jobLocationType: "TELECOMMUTE"
|
|
465
|
-
}
|
|
466
|
-
inLanguage: locale
|
|
515
|
+
}
|
|
467
516
|
};
|
|
468
517
|
},
|
|
469
518
|
/** ItemList schema — Hub/listing pages. */
|
|
@@ -499,9 +548,17 @@ function createSchemaGenerators(brand, supportedLanguages = ["en", "fr", "es"])
|
|
|
499
548
|
}))
|
|
500
549
|
};
|
|
501
550
|
},
|
|
502
|
-
/**
|
|
551
|
+
/**
|
|
552
|
+
* Speakable — marks content sections suitable for voice assistant reading.
|
|
553
|
+
*
|
|
554
|
+
* Includes its own `@context` so it is valid when rendered as a standalone
|
|
555
|
+
* top-level JSON-LD node. When embedded inside another schema (e.g. as the
|
|
556
|
+
* `speakable` value on WebPage/Article), the surrounding `buildPageGraph`
|
|
557
|
+
* strips the redundant `@context`, so the nested case is unaffected.
|
|
558
|
+
*/
|
|
503
559
|
speakable(cssSelectors) {
|
|
504
560
|
return {
|
|
561
|
+
"@context": "https://schema.org",
|
|
505
562
|
"@type": "SpeakableSpecification",
|
|
506
563
|
cssSelector: cssSelectors
|
|
507
564
|
};
|
|
@@ -569,4 +626,4 @@ exports.canonicalUrl = canonicalUrl;
|
|
|
569
626
|
exports.createEntityIds = createEntityIds;
|
|
570
627
|
exports.createSchemaGenerators = createSchemaGenerators;
|
|
571
628
|
//# sourceMappingURL=out.js.map
|
|
572
|
-
//# sourceMappingURL=chunk-
|
|
629
|
+
//# sourceMappingURL=chunk-M4MLGT4B.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/web/seo/schema-generators.ts","../src/web/seo/JsonLd.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * Schema.org Generator System\n *\n * Pure functions that generate structured data objects for SEO.\n * Each generator accepts a `BrandConfig` and an optional `locale`. `inLanguage`\n * is emitted ONLY on schema types where schema.org permits it (CreativeWork\n * subtypes: WebPage, WebSite, Article, FAQPage, VideoObject, DefinedTermSet,\n * HowTo, SoftwareApplication). Types that forbid it (Organization, Person,\n * BreadcrumbList, Product, Service, JobPosting) accept `locale` for signature\n * stability but do not emit it.\n *\n * Architecture:\n * - Each generator returns an object with its own `@context` (standalone-safe).\n * - `buildPageGraph()` strips individual `@context` and wraps all schemas\n * in a single `{\"@context\": \"...\", \"@graph\": [...]}` for unified output.\n * - Use `JsonLd` React component to render the @graph into a single <script> tag.\n *\n * @example\n * ```ts\n * import { createSchemaGenerators, buildPageGraph } from '@salesmind-ai/design-system/web';\n *\n * const seo = createSchemaGenerators({\n * name: 'SalesMind AI',\n * url: 'https://sales-mind.ai',\n * description: 'AI sales automation',\n * tagline: 'AI-powered sales',\n * founder: 'Julien Gadea',\n * });\n *\n * const graph = buildPageGraph(\n * seo.organization(),\n * seo.website(),\n * seo.webPage('/pricing', 'Pricing', '...'),\n * );\n * ```\n */\n\nimport type {\n BrandConfig,\n ArticleMeta,\n BreadcrumbItem,\n CareerForSchema,\n CustomerOrganizationMeta,\n FAQItem,\n GlossaryTermForSchema,\n HowToMeta,\n HowToStep,\n ItemForList,\n PersonMeta,\n PricingPlan,\n ServiceMotion,\n SoftwareApplicationSchemaOptions,\n TestimonialForSchema,\n TranscriptForSchema,\n VideoObjectMeta,\n} from './types';\n\n// ─── Internal Helpers ────────────────────────────────────────────────────────\n\n/** Convert \"MM:SS\" or \"HH:MM:SS\" to ISO 8601 duration \"PT…\" */\nfunction toISO8601Duration(duration: string): string {\n if (duration.startsWith('PT')) return duration;\n const parts = duration.split(':').map(Number);\n if (parts.some(isNaN)) return duration;\n if (parts.length === 3) return `PT${parts[0]}H${parts[1]}M${parts[2]}S`;\n if (parts.length === 2) return `PT${parts[0]}M${parts[1]}S`;\n return `PT${parts[0]}S`;\n}\n\n/** Convert YouTube watch URL to embed URL */\nfunction toEmbedUrl(url: string): string | undefined {\n try {\n const parsed = new URL(url);\n if (parsed.hostname.includes('youtube.com') && parsed.searchParams.has('v')) {\n return `https://www.youtube.com/embed/${parsed.searchParams.get('v')}`;\n }\n if (parsed.hostname === 'youtu.be') {\n return `https://www.youtube.com/embed${parsed.pathname}`;\n }\n return url;\n } catch {\n return undefined;\n }\n}\n\n/** Map career type string to Schema.org employmentType */\nfunction mapEmploymentType(type?: string | null): string {\n if (!type) return 'FULL_TIME';\n const lower = type.toLowerCase();\n if (lower.includes('part')) return 'PART_TIME';\n if (lower.includes('contract')) return 'CONTRACTOR';\n if (lower.includes('intern')) return 'INTERN';\n if (lower.includes('temporary') || lower.includes('temp')) return 'TEMPORARY';\n return 'FULL_TIME';\n}\n\n// ─── Entity ID Factory ──────────────────────────────────────────────────────\n\n/**\n * Create stable entity ID anchors for @graph cross-referencing.\n * Every entity in the knowledge graph gets a permanent @id.\n * Google resolves @id references across the entire site.\n */\n// Returns either `pathOrUrl` as-is (when it is an absolute http(s) URL) or\n// concatenated to `brand.url`. Defensive against callers that pass an absolute\n// URL where a relative path is expected — prevents the doubled-prefix bug\n// `https://brand.aihttps://brand.ai/page#anchor`.\nfunction normalizeEntityPath(brandUrl: string, pathOrUrl: string): string {\n if (/^https?:\\/\\//i.test(pathOrUrl)) return pathOrUrl;\n return `${brandUrl}${pathOrUrl}`;\n}\n\nexport function createEntityIds(brand: BrandConfig) {\n return {\n organization: `${brand.url}/#organization`,\n website: `${brand.url}/#website`,\n software: `${brand.url}/#software`,\n product: `${brand.url}/pricing#product`,\n webpage: (path: string) => `${normalizeEntityPath(brand.url, path)}#webpage`,\n article: (path: string) => `${normalizeEntityPath(brand.url, path)}#article`,\n faq: (path: string) => `${normalizeEntityPath(brand.url, path)}#faq`,\n breadcrumb: (path: string) => `${normalizeEntityPath(brand.url, path)}#breadcrumb`,\n person: (slug: string) => `${brand.url}/company/team#person-${slug}`,\n video: (path: string) => `${normalizeEntityPath(brand.url, path)}#video`,\n review: (id: string) => `${brand.url}/#review-${id}`,\n service: (slug: string) => `${brand.url}/#service-${slug}`,\n customerOrganization: (slug: string) => `${brand.url}/#customer-org-${slug}`,\n customerPerson: (slug: string) => `${brand.url}/#customer-person-${slug}`,\n } as const;\n}\n\n// ─── Schema Generator Factory ───────────────────────────────────────────────\n\n/**\n * Create all schema generators bound to a specific brand configuration.\n * Returns an object with methods for each schema type.\n */\nexport function createSchemaGenerators(\n brand: BrandConfig,\n supportedLanguages: readonly string[] = ['en', 'fr', 'es'],\n) {\n const ENTITY_IDS = createEntityIds(brand);\n\n return {\n /**\n * Organization schema — Homepage + About page.\n *\n * Note: schema.org does NOT allow `inLanguage` or `availableLanguage` on\n * Organization. The multilingual signal is carried by `knowsLanguage`\n * (valid on Organization, BCP-47 codes). The `locale` param is retained\n * for call-site signature stability but no longer emitted here.\n */\n organization(_locale: string = 'en') {\n void _locale;\n return {\n '@context': 'https://schema.org',\n '@type': 'Organization',\n '@id': ENTITY_IDS.organization,\n name: brand.name,\n url: brand.url,\n logo: {\n '@type': 'ImageObject',\n url: `${brand.url}/logo.svg`,\n },\n description: brand.description,\n knowsLanguage: [...supportedLanguages],\n founder: {\n '@type': 'Person',\n name: brand.founder,\n },\n ...(brand.sameAs && brand.sameAs.length > 0 ? { sameAs: brand.sameAs } : {}),\n contactPoint: [] as Record<string, unknown>[],\n areaServed: 'Worldwide',\n };\n },\n\n /** WebSite schema — Homepage only (with SearchAction). */\n website(locale: string = 'en') {\n return {\n '@context': 'https://schema.org',\n '@type': 'WebSite',\n '@id': ENTITY_IDS.website,\n name: brand.name,\n url: brand.url,\n description: brand.tagline,\n inLanguage: locale,\n publisher: {\n '@type': 'Organization',\n '@id': ENTITY_IDS.organization,\n name: brand.name,\n },\n potentialAction: [\n {\n '@type': 'SearchAction',\n target: {\n '@type': 'EntryPoint',\n urlTemplate: `${brand.url}/blog?q={search_term_string}`,\n },\n 'query-input': 'required name=search_term_string',\n },\n {\n '@type': 'ReadAction',\n target: brand.url,\n },\n ],\n };\n },\n\n /** WebPage schema — Every public page. Links to WebSite + Breadcrumb via @id. */\n webPage(path: string, title: string, description: string, locale: string = 'en', speakable?: Record<string, unknown>) {\n return {\n '@context': 'https://schema.org',\n '@type': 'WebPage',\n '@id': ENTITY_IDS.webpage(path),\n url: `${brand.url}${path}`,\n name: title,\n description,\n inLanguage: locale,\n // Reference stub to the site-wide WebSite node. `url`/`name` are\n // included (when the brand provides them) so the reference stands as a\n // complete WebSite on pages rendered independently of the WebSite node,\n // per schema.org @id-linking guidance. Guarded so a brand without\n // `url`/`name` never emits `undefined`.\n isPartOf: {\n '@type': 'WebSite',\n '@id': ENTITY_IDS.website,\n ...(brand.url ? { url: brand.url } : {}),\n ...(brand.name ? { name: brand.name } : {}),\n },\n breadcrumb: { '@id': ENTITY_IDS.breadcrumb(path) },\n potentialAction: {\n '@type': 'ReadAction',\n target: `${brand.url}${path}`,\n },\n ...(speakable ? { speakable } : {}),\n };\n },\n\n /** SoftwareApplication schema — Platform Hub, Platform Feature, Pricing. */\n softwareApplication(\n name?: string,\n description?: string,\n url?: string,\n locale: string = 'en',\n options: SoftwareApplicationSchemaOptions = {},\n ) {\n const aggregateRating = options.aggregateRating ?? brand.aggregateRating;\n const offers = options.offers ?? brand.softwareApplicationOffers;\n\n return {\n '@context': 'https://schema.org',\n '@type': 'SoftwareApplication',\n '@id': ENTITY_IDS.software,\n name: name || brand.name,\n description: description || brand.description,\n url: url || brand.url,\n applicationCategory: 'BusinessApplication',\n operatingSystem: 'Web',\n // `inLanguage` is valid — SoftwareApplication is a CreativeWork subtype.\n // `availableLanguage` is NOT valid on SoftwareApplication and is dropped.\n inLanguage: locale,\n // Google requires `offers` with a price. We expose only the price floor\n // via AggregateOffer so A/B-tested tier prices stay hidden.\n ...(offers\n ? {\n offers: {\n '@type': 'AggregateOffer',\n lowPrice: offers.lowPrice,\n priceCurrency: offers.priceCurrency,\n offerCount: offers.offerCount,\n url: offers.url ?? `${brand.url}/pricing`,\n availability: 'https://schema.org/InStock',\n },\n }\n : {}),\n ...(aggregateRating\n ? {\n aggregateRating: {\n '@type': 'AggregateRating',\n ratingValue: String(aggregateRating.ratingValue),\n ratingCount: String(aggregateRating.reviewCount),\n bestRating: String(aggregateRating.bestRating ?? 5),\n worstRating: String(aggregateRating.worstRating ?? 1),\n },\n }\n : {}),\n author: {\n '@type': 'Organization',\n '@id': ENTITY_IDS.organization,\n name: brand.name,\n },\n };\n },\n\n /** Article schema — Blog posts, Comparison pages. */\n article(meta: ArticleMeta, locale: string = 'en') {\n let path: string;\n try {\n path = new URL(meta.url).pathname;\n } catch {\n path = meta.url.startsWith('/') ? meta.url : `/${meta.url}`;\n }\n\n return {\n '@context': 'https://schema.org',\n '@type': 'Article',\n '@id': ENTITY_IDS.article(path),\n headline: meta.title,\n description: meta.description,\n url: meta.url.startsWith('http') ? meta.url : `${brand.url}${meta.url}`,\n image: meta.image || `${brand.url}/og-default.png`,\n datePublished: meta.publishedTime,\n dateModified: meta.modifiedTime,\n inLanguage: locale,\n author: meta.authorSlug\n ? { '@id': ENTITY_IDS.person(meta.authorSlug) }\n : {\n '@type': 'Person',\n name: meta.authorName,\n url: meta.authorUrl || `${brand.url}/company/team`,\n },\n publisher: {\n '@type': 'Organization',\n '@id': ENTITY_IDS.organization,\n name: brand.name,\n logo: {\n '@type': 'ImageObject',\n url: `${brand.url}/logo.svg`,\n },\n },\n isPartOf: { '@type': 'WebSite', '@id': ENTITY_IDS.website },\n mainEntityOfPage: { '@id': ENTITY_IDS.webpage(path) },\n articleSection: meta.section,\n keywords: meta.tags?.join(', '),\n speakable: {\n '@type': 'SpeakableSpecification',\n cssSelector: meta.speakableCssSelectors || ['article h1', 'article .summary', 'article .lead'],\n },\n ...(meta.about ? { about: meta.about } : {}),\n ...(meta.video ? { video: meta.video } : {}),\n };\n },\n\n /** FAQPage schema — FAQ hub, Solutions, Platform Features, Comparisons, Integrations. */\n faqPage(items: FAQItem[], pageUrl: string, locale: string = 'en') {\n return {\n '@context': 'https://schema.org',\n '@type': 'FAQPage',\n '@id': ENTITY_IDS.faq(pageUrl),\n inLanguage: locale,\n mainEntity: items.map((item) => ({\n '@type': 'Question',\n name: item.question,\n acceptedAnswer: {\n '@type': 'Answer',\n text: item.answer,\n inLanguage: locale,\n },\n })),\n };\n },\n\n /**\n * BreadcrumbList schema — Every public page.\n * `inLanguage` is NOT valid on BreadcrumbList and is not emitted. The\n * `locale` param is retained for call-site signature stability.\n */\n breadcrumb(items: BreadcrumbItem[], _locale: string = 'en') {\n void _locale;\n const lastUrl = items.length > 0 ? items[items.length - 1].url : '/';\n const path = lastUrl.startsWith('http') ? new URL(lastUrl).pathname : lastUrl;\n\n return {\n '@context': 'https://schema.org',\n '@type': 'BreadcrumbList',\n '@id': ENTITY_IDS.breadcrumb(path),\n itemListElement: items.map((item, index) => ({\n '@type': 'ListItem',\n position: index + 1,\n name: item.name,\n item: item.url.startsWith('http') ? item.url : `${brand.url}${item.url}`,\n })),\n };\n },\n\n /**\n * Person schema — Team page, Blog author, Comparison author.\n * `inLanguage` is NOT valid on Person (Person is not a CreativeWork) and is\n * not emitted. The `locale` param is retained for signature stability.\n */\n person(person: PersonMeta, _locale: string = 'en') {\n void _locale;\n const slug = person.slug || person.name.toLowerCase().replace(/\\s+/g, '-');\n\n return {\n '@context': 'https://schema.org',\n '@type': 'Person',\n '@id': person.entityIdOverride || ENTITY_IDS.person(slug),\n name: person.name,\n jobTitle: person.jobTitle,\n url: person.url,\n image: person.image,\n worksFor: person.worksFor || {\n '@type': 'Organization',\n '@id': ENTITY_IDS.organization,\n name: brand.name,\n },\n sameAs: person.sameAs || [],\n };\n },\n\n /** Review schema — Generated from testimonials. */\n review(testimonial: TestimonialForSchema) {\n return {\n '@context': 'https://schema.org',\n '@type': 'Review',\n '@id': ENTITY_IDS.review(testimonial.id),\n author: {\n '@type': 'Person',\n ...(testimonial.authorEntityId ? { '@id': testimonial.authorEntityId } : {}),\n name: testimonial.customer_name,\n ...(testimonial.occupation ? { jobTitle: testimonial.occupation } : {}),\n },\n reviewBody: testimonial.quote || '',\n ...(testimonial.star_rating\n ? {\n reviewRating: {\n '@type': 'Rating',\n ratingValue: String(testimonial.star_rating),\n bestRating: '5',\n worstRating: '1',\n },\n }\n : {}),\n ...(testimonial.review_date ? { datePublished: testimonial.review_date } : {}),\n itemReviewed: {\n '@type': 'SoftwareApplication',\n '@id': ENTITY_IDS.software,\n name: brand.name,\n },\n ...(testimonial.review_source\n ? {\n publisher: {\n '@type': 'Organization',\n name: testimonial.review_source,\n },\n }\n : {}),\n };\n },\n\n /**\n * Product + multiple Offers schema — Pricing page.\n * `inLanguage` is NOT valid on Product and is not emitted. The `locale`\n * param is retained for call-site signature stability.\n */\n productWithOffers(\n plans: PricingPlan[],\n testimonials: TestimonialForSchema[] = [],\n _locale: string = 'en',\n ) {\n void _locale;\n return {\n '@context': 'https://schema.org',\n '@type': 'Product',\n '@id': ENTITY_IDS.product,\n name: brand.name,\n description: brand.description,\n brand: {\n '@type': 'Organization',\n '@id': ENTITY_IDS.organization,\n name: brand.name,\n },\n ...(testimonials.length > 0\n ? { aggregateRating: aggregateRatingFromTestimonials(testimonials) }\n : {}),\n offers: plans.map((plan) => ({\n '@type': 'Offer',\n name: plan.name,\n description: plan.description,\n price: plan.price.replace(/[^0-9.]/g, '') || '0',\n priceCurrency: plan.priceCurrency || 'USD',\n availability: 'https://schema.org/InStock',\n url: `${brand.url}/pricing`,\n ...(plan.billingPeriod\n ? {\n priceSpecification: {\n '@type': 'UnitPriceSpecification',\n price: plan.price.replace(/[^0-9.]/g, '') || '0',\n priceCurrency: plan.priceCurrency || 'USD',\n billingDuration: plan.billingPeriod,\n },\n }\n : {}),\n })),\n };\n },\n\n /** VideoObject schema — Transcript detail pages. */\n videoObject(transcript: TranscriptForSchema, locale: string = 'en') {\n const path = transcript.path || `/resources/transcripts/${transcript.slug}`;\n\n return {\n '@context': 'https://schema.org',\n '@type': 'VideoObject',\n '@id': ENTITY_IDS.video(path),\n name: transcript.title,\n description: transcript.summary || transcript.title,\n ...(transcript.video_link ? { contentUrl: transcript.video_link } : {}),\n ...(transcript.video_link ? { embedUrl: toEmbedUrl(transcript.video_link) } : {}),\n ...(transcript.duration\n ? { duration: toISO8601Duration(transcript.duration) }\n : {}),\n ...(transcript.published_at ? { uploadDate: transcript.published_at } : {}),\n ...(transcript.thumbnailUrl ? { thumbnailUrl: transcript.thumbnailUrl } : {}),\n inLanguage: locale,\n publisher: {\n '@type': 'Organization',\n '@id': ENTITY_IDS.organization,\n name: brand.name,\n },\n ...(transcript.transcript_text ? { transcript: transcript.transcript_text } : {}),\n };\n },\n\n /**\n * CustomerOrganization schema — Customer's company for Success Story pages.\n * `industry` is NOT valid on Organization (schema.org allows only the coded\n * `naics` / `isicV4`, plus free-text `keywords`). The free-text industry\n * value is carried by `keywords`.\n */\n customerOrganization(meta: CustomerOrganizationMeta) {\n return {\n '@context': 'https://schema.org',\n '@type': 'Organization',\n '@id': ENTITY_IDS.customerOrganization(meta.slug),\n name: meta.name,\n ...(meta.url ? { url: meta.url } : {}),\n ...(meta.logo ? { logo: meta.logo } : {}),\n ...(meta.description ? { description: meta.description } : {}),\n ...(meta.industry ? { keywords: meta.industry } : {}),\n ...(meta.sameAs && meta.sameAs.length > 0 ? { sameAs: meta.sameAs } : {}),\n };\n },\n\n /** Generic VideoObject — Success story main video and shorts. */\n videoObjectGeneric(meta: VideoObjectMeta, locale: string = 'en') {\n const videoId = meta.fragment\n ? `${brand.url}${meta.path}#${meta.fragment}`\n : ENTITY_IDS.video(meta.path);\n return {\n '@context': 'https://schema.org',\n '@type': 'VideoObject',\n '@id': videoId,\n name: meta.title,\n ...(meta.description ? { description: meta.description } : {}),\n ...(meta.videoUrl ? { contentUrl: meta.videoUrl } : {}),\n ...(meta.embedUrl ? { embedUrl: meta.embedUrl } : {}),\n ...(meta.thumbnailUrl ? { thumbnailUrl: meta.thumbnailUrl } : {}),\n ...(meta.duration ? { duration: meta.duration } : {}),\n ...(meta.uploadDate ? { uploadDate: meta.uploadDate } : {}),\n ...(meta.transcript ? { transcript: meta.transcript } : {}),\n inLanguage: locale,\n publisher: { '@id': ENTITY_IDS.organization },\n };\n },\n\n /** HowTo schema — Solution pages, tutorial blog posts. */\n howTo(steps: HowToStep[], meta: HowToMeta, locale: string = 'en') {\n return {\n '@context': 'https://schema.org',\n '@type': 'HowTo',\n name: meta.name,\n description: meta.description,\n inLanguage: locale,\n ...(meta.totalTime ? { totalTime: meta.totalTime } : {}),\n ...(meta.image ? { image: meta.image } : {}),\n step: steps.map((step, index) => ({\n '@type': 'HowToStep',\n position: index + 1,\n name: step.name,\n text: step.text,\n ...(step.url ? { url: step.url } : {}),\n ...(step.image ? { image: step.image } : {}),\n })),\n };\n },\n\n /**\n * Service schema — Growth motion service offerings.\n * Neither `inLanguage` nor `availableLanguage` is valid on Service, so both\n * are dropped. The `locale` param is retained for signature stability.\n */\n service(motion: ServiceMotion, _locale: string = 'en') {\n void _locale;\n return {\n '@context': 'https://schema.org',\n '@type': 'Service',\n '@id': ENTITY_IDS.service(motion.slug),\n name: motion.name,\n description: motion.description,\n url: motion.url.startsWith('http') ? motion.url : `${brand.url}${motion.url}`,\n provider: {\n '@type': 'Organization',\n '@id': ENTITY_IDS.organization,\n name: brand.name,\n },\n areaServed: 'Worldwide',\n ...(motion.price\n ? {\n offers: {\n '@type': 'Offer',\n price: motion.price.replace(/[^0-9.]/g, '') || '0',\n priceCurrency: motion.priceCurrency || 'USD',\n availability: 'https://schema.org/InStock',\n },\n }\n : {}),\n termsOfService: `${brand.url}/legal/terms`,\n };\n },\n\n /**\n * JobPosting schema — Career detail pages.\n * `inLanguage` is NOT valid on JobPosting and is not emitted. The `locale`\n * param is retained for call-site signature stability.\n */\n jobPosting(job: CareerForSchema, _locale: string = 'en') {\n void _locale;\n return {\n '@context': 'https://schema.org',\n '@type': 'JobPosting',\n '@id': `${brand.url}/careers/${job.slug}#jobposting`,\n title: job.title,\n description: job.description || '',\n datePosted: job.published_at || job.created_at,\n employmentType: mapEmploymentType(job.type),\n hiringOrganization: {\n '@type': 'Organization',\n '@id': ENTITY_IDS.organization,\n name: brand.name,\n sameAs: brand.url,\n },\n ...(job.location\n ? {\n jobLocation: {\n '@type': 'Place',\n address: {\n '@type': 'PostalAddress',\n addressLocality: job.location,\n },\n },\n }\n : {\n jobLocationType: 'TELECOMMUTE',\n }),\n };\n },\n\n /** ItemList schema — Hub/listing pages. */\n itemList(items: ItemForList[], listName: string) {\n return {\n '@context': 'https://schema.org',\n '@type': 'ItemList',\n name: listName,\n numberOfItems: items.length,\n itemListElement: items.map((item, index) => ({\n '@type': 'ListItem',\n position: item.position ?? index + 1,\n name: item.name,\n url: item.url.startsWith('http') ? item.url : `${brand.url}${item.url}`,\n ...(item.description ? { description: item.description } : {}),\n ...(item.image ? { image: item.image } : {}),\n })),\n };\n },\n\n /** DefinedTermSet schema — Glossary page. */\n definedTermSet(terms: GlossaryTermForSchema[], locale: string = 'en') {\n return {\n '@context': 'https://schema.org',\n '@type': 'DefinedTermSet',\n '@id': `${brand.url}/resources/glossary#termset`,\n name: 'AI Sales Glossary',\n inLanguage: locale,\n hasDefinedTerm: terms.map((term) => ({\n '@type': 'DefinedTerm',\n name: term.term,\n description: term.definition,\n url: term.url || `${brand.url}/resources/glossary#${term.slug}`,\n })),\n };\n },\n\n /**\n * Speakable — marks content sections suitable for voice assistant reading.\n *\n * Includes its own `@context` so it is valid when rendered as a standalone\n * top-level JSON-LD node. When embedded inside another schema (e.g. as the\n * `speakable` value on WebPage/Article), the surrounding `buildPageGraph`\n * strips the redundant `@context`, so the nested case is unaffected.\n */\n speakable(cssSelectors: string[]): Record<string, unknown> {\n return {\n '@context': 'https://schema.org',\n '@type': 'SpeakableSpecification',\n cssSelector: cssSelectors,\n };\n },\n\n /** Access the entity IDs for cross-referencing */\n entityIds: ENTITY_IDS,\n };\n}\n\n// ─── Standalone Utilities ───────────────────────────────────────────────────\n\n/**\n * Compute AggregateRating from real testimonial data.\n * Falls back to hardcoded 4.7/150 when no rated testimonials exist.\n * Returns a fragment (no @context) — meant to be embedded in Product/SoftwareApp.\n */\nexport function aggregateRatingFromTestimonials(testimonials: TestimonialForSchema[]) {\n const rated = testimonials.filter((t) => t.star_rating != null && t.star_rating > 0);\n\n if (rated.length === 0) {\n return {\n '@type': 'AggregateRating',\n ratingValue: '4.7',\n ratingCount: '150',\n bestRating: '5',\n worstRating: '1',\n };\n }\n\n const sum = rated.reduce((acc, t) => acc + (t.star_rating || 0), 0);\n const avg = (sum / rated.length).toFixed(1);\n\n return {\n '@type': 'AggregateRating',\n ratingValue: avg,\n ratingCount: String(rated.length),\n bestRating: '5',\n worstRating: '1',\n };\n}\n\n/**\n * Assemble multiple schema entities into a single @graph array.\n * Strips individual `@context` from each schema — the wrapper provides it once.\n *\n * @example\n * ```ts\n * const graph = buildPageGraph(\n * seo.organization(),\n * seo.website(),\n * seo.webPage('/pricing', 'Pricing', '...'),\n * seo.breadcrumb(crumbs),\n * );\n * ```\n */\nexport function buildPageGraph(\n ...schemas: Record<string, unknown>[]\n): Record<string, unknown> {\n const graph = schemas.map((schema) => {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { '@context': _, ...rest } = schema;\n return rest;\n });\n\n return {\n '@context': 'https://schema.org',\n '@graph': graph,\n };\n}\n\n/**\n * Build canonical URL from pathname.\n * Removes trailing slash (except root) and query params.\n *\n * @param baseUrl - The site's base URL (e.g. \"https://sales-mind.ai\")\n * @param pathname - The route path (e.g. \"/pricing\", \"/blog/post/foo\")\n * @param locale - BCP-47 locale code. 'en' = no prefix (default). Others get /{locale}/ prefix.\n */\nexport function canonicalUrl(baseUrl: string, pathname: string, locale?: string): string {\n const clean = pathname === '/' ? '/' : pathname.replace(/\\/+$/, '');\n\n if (locale && locale !== 'en') {\n const stripped = clean.replace(new RegExp(`^/${locale}(/|$)`), '$1') || '/';\n const path = stripped === '/' ? '' : stripped;\n return `${baseUrl}/${locale}${path}`;\n }\n\n return `${baseUrl}${clean}`;\n}\n","/**\n * JsonLd — Renders structured data as a `<script type=\"application/ld+json\">` tag.\n *\n * Framework-agnostic: works with any React-based framework (Next.js, Vite, Remix, etc.).\n * Safely serializes the data object and escapes `</script>` sequences.\n *\n * @example\n * ```tsx\n * import { JsonLd, buildPageGraph } from '@salesmind-ai/design-system/web';\n *\n * <JsonLd data={buildPageGraph(seo.organization(), seo.website())} />\n * ```\n */\nexport interface JsonLdProps {\n /** The structured data object (schema.org format) */\n data: Record<string, unknown>;\n /** Optional nonce for CSP headers */\n nonce?: string;\n}\n\nexport function JsonLd({ data, nonce }: JsonLdProps) {\n const json = JSON.stringify(data).replace(/<\\/script>/gi, '<\\\\/script>');\n\n return (\n <script\n type=\"application/ld+json\"\n nonce={nonce}\n dangerouslySetInnerHTML={{ __html: json }}\n />\n );\n}\n"]}
|
|
@@ -636,6 +636,24 @@ var CheckIcon = () => /* @__PURE__ */ jsx(
|
|
|
636
636
|
children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
|
|
637
637
|
}
|
|
638
638
|
);
|
|
639
|
+
var SearchIcon = () => /* @__PURE__ */ jsxs(
|
|
640
|
+
"svg",
|
|
641
|
+
{
|
|
642
|
+
width: "14",
|
|
643
|
+
height: "14",
|
|
644
|
+
viewBox: "0 0 24 24",
|
|
645
|
+
fill: "none",
|
|
646
|
+
stroke: "currentColor",
|
|
647
|
+
strokeWidth: "2",
|
|
648
|
+
strokeLinecap: "round",
|
|
649
|
+
strokeLinejoin: "round",
|
|
650
|
+
"aria-hidden": "true",
|
|
651
|
+
children: [
|
|
652
|
+
/* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "8" }),
|
|
653
|
+
/* @__PURE__ */ jsx("path", { d: "m21 21-4.3-4.3" })
|
|
654
|
+
]
|
|
655
|
+
}
|
|
656
|
+
);
|
|
639
657
|
var LocaleDropdown = forwardRef(
|
|
640
658
|
({
|
|
641
659
|
locales,
|
|
@@ -645,16 +663,29 @@ var LocaleDropdown = forwardRef(
|
|
|
645
663
|
getHref,
|
|
646
664
|
className,
|
|
647
665
|
direction = "down",
|
|
648
|
-
align = "right"
|
|
666
|
+
align = "right",
|
|
667
|
+
searchable = false,
|
|
668
|
+
searchPlaceholder = "Search languages",
|
|
669
|
+
searchEmptyLabel = "No languages found"
|
|
649
670
|
}, ref) => {
|
|
650
671
|
const [isOpen, setIsOpen] = useState(false);
|
|
651
672
|
const [focusIndex, setFocusIndex] = useState(-1);
|
|
673
|
+
const [query, setQuery] = useState("");
|
|
652
674
|
const containerRef = useRef(null);
|
|
653
675
|
const triggerRef = useRef(null);
|
|
654
676
|
const listRef = useRef(null);
|
|
677
|
+
const searchInputRef = useRef(null);
|
|
655
678
|
const instanceId = useId();
|
|
656
679
|
const listboxId = `locale-dropdown-${instanceId}`;
|
|
657
680
|
const currentLocale = locales.find((l) => l.code === activeLocale) ?? locales[0];
|
|
681
|
+
const filteredLocales = useMemo(() => {
|
|
682
|
+
if (!searchable) return locales;
|
|
683
|
+
const q = query.trim().toLowerCase();
|
|
684
|
+
if (!q) return locales;
|
|
685
|
+
return locales.filter(
|
|
686
|
+
(l) => l.label.toLowerCase().includes(q) || l.code.toLowerCase().includes(q)
|
|
687
|
+
);
|
|
688
|
+
}, [locales, query, searchable]);
|
|
658
689
|
const handleToggle = useCallback(() => {
|
|
659
690
|
setIsOpen((prev) => {
|
|
660
691
|
if (!prev) setFocusIndex(-1);
|
|
@@ -664,6 +695,7 @@ var LocaleDropdown = forwardRef(
|
|
|
664
695
|
const handleClose = useCallback(() => {
|
|
665
696
|
setIsOpen(false);
|
|
666
697
|
setFocusIndex(-1);
|
|
698
|
+
setQuery("");
|
|
667
699
|
triggerRef.current?.focus();
|
|
668
700
|
}, []);
|
|
669
701
|
const handleSelect = useCallback(
|
|
@@ -683,6 +715,14 @@ var LocaleDropdown = forwardRef(
|
|
|
683
715
|
document.addEventListener("mousedown", handleClickOutside);
|
|
684
716
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
685
717
|
}, [isOpen, handleClose]);
|
|
718
|
+
useEffect(() => {
|
|
719
|
+
if (!isOpen || !searchable) return;
|
|
720
|
+
const raf = requestAnimationFrame(() => searchInputRef.current?.focus());
|
|
721
|
+
return () => cancelAnimationFrame(raf);
|
|
722
|
+
}, [isOpen, searchable]);
|
|
723
|
+
useEffect(() => {
|
|
724
|
+
setFocusIndex(-1);
|
|
725
|
+
}, [query]);
|
|
686
726
|
const handleKeyDown = useCallback(
|
|
687
727
|
(e) => {
|
|
688
728
|
if (!isOpen) {
|
|
@@ -693,6 +733,7 @@ var LocaleDropdown = forwardRef(
|
|
|
693
733
|
}
|
|
694
734
|
return;
|
|
695
735
|
}
|
|
736
|
+
const count = filteredLocales.length;
|
|
696
737
|
switch (e.key) {
|
|
697
738
|
case "Escape":
|
|
698
739
|
e.preventDefault();
|
|
@@ -700,33 +741,44 @@ var LocaleDropdown = forwardRef(
|
|
|
700
741
|
break;
|
|
701
742
|
case "ArrowDown":
|
|
702
743
|
e.preventDefault();
|
|
703
|
-
setFocusIndex((prev) => (prev + 1) %
|
|
744
|
+
if (count > 0) setFocusIndex((prev) => (prev + 1) % count);
|
|
704
745
|
break;
|
|
705
746
|
case "ArrowUp":
|
|
706
747
|
e.preventDefault();
|
|
707
|
-
setFocusIndex((prev) => (prev - 1 +
|
|
748
|
+
if (count > 0) setFocusIndex((prev) => (prev - 1 + count) % count);
|
|
708
749
|
break;
|
|
709
750
|
case "Enter":
|
|
710
|
-
case " ":
|
|
711
751
|
e.preventDefault();
|
|
712
|
-
if (focusIndex >= 0 && focusIndex <
|
|
713
|
-
handleSelect(
|
|
752
|
+
if (focusIndex >= 0 && focusIndex < count) {
|
|
753
|
+
handleSelect(filteredLocales[focusIndex].code);
|
|
754
|
+
}
|
|
755
|
+
break;
|
|
756
|
+
case " ":
|
|
757
|
+
if (!searchable) {
|
|
758
|
+
e.preventDefault();
|
|
759
|
+
if (focusIndex >= 0 && focusIndex < count) {
|
|
760
|
+
handleSelect(filteredLocales[focusIndex].code);
|
|
761
|
+
}
|
|
714
762
|
}
|
|
715
763
|
break;
|
|
716
764
|
case "Home":
|
|
717
|
-
|
|
718
|
-
|
|
765
|
+
if (!searchable) {
|
|
766
|
+
e.preventDefault();
|
|
767
|
+
if (count > 0) setFocusIndex(0);
|
|
768
|
+
}
|
|
719
769
|
break;
|
|
720
770
|
case "End":
|
|
721
|
-
|
|
722
|
-
|
|
771
|
+
if (!searchable) {
|
|
772
|
+
e.preventDefault();
|
|
773
|
+
if (count > 0) setFocusIndex(count - 1);
|
|
774
|
+
}
|
|
723
775
|
break;
|
|
724
776
|
case "Tab":
|
|
725
777
|
handleClose();
|
|
726
778
|
break;
|
|
727
779
|
}
|
|
728
780
|
},
|
|
729
|
-
[isOpen, focusIndex,
|
|
781
|
+
[isOpen, focusIndex, filteredLocales, searchable, handleClose, handleSelect]
|
|
730
782
|
);
|
|
731
783
|
useEffect(() => {
|
|
732
784
|
if (!isOpen || focusIndex < 0 || !listRef.current) return;
|
|
@@ -734,6 +786,30 @@ var LocaleDropdown = forwardRef(
|
|
|
734
786
|
items[focusIndex]?.scrollIntoView({ block: "nearest" });
|
|
735
787
|
}, [isOpen, focusIndex]);
|
|
736
788
|
const activeDescendantId = isOpen && focusIndex >= 0 ? `${listboxId}-option-${focusIndex}` : void 0;
|
|
789
|
+
const renderOption = (locale, index) => {
|
|
790
|
+
const isActive = locale.code === activeLocale;
|
|
791
|
+
const isFocused = index === focusIndex;
|
|
792
|
+
const optionId = `${listboxId}-option-${index}`;
|
|
793
|
+
const optionProps = {
|
|
794
|
+
id: optionId,
|
|
795
|
+
role: "option",
|
|
796
|
+
"aria-selected": isActive,
|
|
797
|
+
className: clsx(
|
|
798
|
+
"ds-locale-dropdown__option",
|
|
799
|
+
isActive && "ds-locale-dropdown__option--active",
|
|
800
|
+
isFocused && "ds-locale-dropdown__option--focused"
|
|
801
|
+
),
|
|
802
|
+
onClick: () => handleSelect(locale.code),
|
|
803
|
+
...OptionComponent !== "button" && getHref ? { href: getHref(locale.code) } : { type: "button" }
|
|
804
|
+
};
|
|
805
|
+
return /* @__PURE__ */ jsxs(OptionComponent, { ...optionProps, children: [
|
|
806
|
+
/* @__PURE__ */ jsxs("span", { className: "ds-locale-dropdown__option-content", children: [
|
|
807
|
+
locale.flag && /* @__PURE__ */ jsx("span", { className: "ds-locale-dropdown__option-flag", "aria-hidden": "true", children: locale.flag }),
|
|
808
|
+
/* @__PURE__ */ jsx("span", { className: "ds-locale-dropdown__option-label", children: locale.label })
|
|
809
|
+
] }),
|
|
810
|
+
isActive && /* @__PURE__ */ jsx("span", { className: "ds-locale-dropdown__option-check", children: /* @__PURE__ */ jsx(CheckIcon, {}) })
|
|
811
|
+
] }, locale.code);
|
|
812
|
+
};
|
|
737
813
|
return /* @__PURE__ */ jsx(
|
|
738
814
|
"div",
|
|
739
815
|
{
|
|
@@ -757,7 +833,7 @@ var LocaleDropdown = forwardRef(
|
|
|
757
833
|
"aria-haspopup": "listbox",
|
|
758
834
|
"aria-expanded": isOpen,
|
|
759
835
|
"aria-controls": isOpen ? listboxId : void 0,
|
|
760
|
-
"aria-activedescendant": activeDescendantId,
|
|
836
|
+
"aria-activedescendant": searchable ? void 0 : activeDescendantId,
|
|
761
837
|
"aria-label": `Language: ${currentLocale.label}. Change language.`,
|
|
762
838
|
children: [
|
|
763
839
|
/* @__PURE__ */ jsx("span", { className: "ds-locale-dropdown__trigger-icon", children: /* @__PURE__ */ jsx(GlobeIcon, {}) }),
|
|
@@ -773,7 +849,49 @@ var LocaleDropdown = forwardRef(
|
|
|
773
849
|
]
|
|
774
850
|
}
|
|
775
851
|
),
|
|
776
|
-
/* @__PURE__ */
|
|
852
|
+
searchable ? /* @__PURE__ */ jsxs(
|
|
853
|
+
"div",
|
|
854
|
+
{
|
|
855
|
+
className: "ds-locale-dropdown__panel ds-locale-dropdown__panel--searchable",
|
|
856
|
+
"data-state": isOpen ? "open" : "closed",
|
|
857
|
+
children: [
|
|
858
|
+
/* @__PURE__ */ jsxs("div", { className: "ds-locale-dropdown__search", children: [
|
|
859
|
+
/* @__PURE__ */ jsx("span", { className: "ds-locale-dropdown__search-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(SearchIcon, {}) }),
|
|
860
|
+
/* @__PURE__ */ jsx(
|
|
861
|
+
"input",
|
|
862
|
+
{
|
|
863
|
+
ref: searchInputRef,
|
|
864
|
+
type: "text",
|
|
865
|
+
className: "ds-locale-dropdown__search-input",
|
|
866
|
+
placeholder: searchPlaceholder,
|
|
867
|
+
value: query,
|
|
868
|
+
onChange: (e) => setQuery(e.target.value),
|
|
869
|
+
onKeyDown: handleKeyDown,
|
|
870
|
+
role: "combobox",
|
|
871
|
+
"aria-expanded": isOpen,
|
|
872
|
+
"aria-controls": listboxId,
|
|
873
|
+
"aria-activedescendant": activeDescendantId,
|
|
874
|
+
"aria-autocomplete": "list",
|
|
875
|
+
"aria-label": searchPlaceholder,
|
|
876
|
+
autoComplete: "off",
|
|
877
|
+
spellCheck: false
|
|
878
|
+
}
|
|
879
|
+
)
|
|
880
|
+
] }),
|
|
881
|
+
/* @__PURE__ */ jsx(
|
|
882
|
+
"div",
|
|
883
|
+
{
|
|
884
|
+
ref: listRef,
|
|
885
|
+
id: listboxId,
|
|
886
|
+
className: "ds-locale-dropdown__list",
|
|
887
|
+
role: "listbox",
|
|
888
|
+
"aria-label": "Select language",
|
|
889
|
+
children: filteredLocales.length === 0 ? /* @__PURE__ */ jsx("div", { className: "ds-locale-dropdown__empty", role: "status", children: searchEmptyLabel }) : filteredLocales.map(renderOption)
|
|
890
|
+
}
|
|
891
|
+
)
|
|
892
|
+
]
|
|
893
|
+
}
|
|
894
|
+
) : /* @__PURE__ */ jsx(
|
|
777
895
|
"div",
|
|
778
896
|
{
|
|
779
897
|
ref: listRef,
|
|
@@ -783,30 +901,7 @@ var LocaleDropdown = forwardRef(
|
|
|
783
901
|
"aria-label": "Select language",
|
|
784
902
|
"data-state": isOpen ? "open" : "closed",
|
|
785
903
|
onKeyDown: handleKeyDown,
|
|
786
|
-
children:
|
|
787
|
-
const isActive = locale.code === activeLocale;
|
|
788
|
-
const isFocused = index === focusIndex;
|
|
789
|
-
const optionId = `${listboxId}-option-${index}`;
|
|
790
|
-
const optionProps = {
|
|
791
|
-
id: optionId,
|
|
792
|
-
role: "option",
|
|
793
|
-
"aria-selected": isActive,
|
|
794
|
-
className: clsx(
|
|
795
|
-
"ds-locale-dropdown__option",
|
|
796
|
-
isActive && "ds-locale-dropdown__option--active",
|
|
797
|
-
isFocused && "ds-locale-dropdown__option--focused"
|
|
798
|
-
),
|
|
799
|
-
onClick: () => handleSelect(locale.code),
|
|
800
|
-
...OptionComponent !== "button" && getHref ? { href: getHref(locale.code) } : { type: "button" }
|
|
801
|
-
};
|
|
802
|
-
return /* @__PURE__ */ jsxs(OptionComponent, { ...optionProps, children: [
|
|
803
|
-
/* @__PURE__ */ jsxs("span", { className: "ds-locale-dropdown__option-content", children: [
|
|
804
|
-
locale.flag && /* @__PURE__ */ jsx("span", { className: "ds-locale-dropdown__option-flag", "aria-hidden": "true", children: locale.flag }),
|
|
805
|
-
/* @__PURE__ */ jsx("span", { className: "ds-locale-dropdown__option-label", children: locale.label })
|
|
806
|
-
] }),
|
|
807
|
-
isActive && /* @__PURE__ */ jsx("span", { className: "ds-locale-dropdown__option-check", children: /* @__PURE__ */ jsx(CheckIcon, {}) })
|
|
808
|
-
] }, locale.code);
|
|
809
|
-
})
|
|
904
|
+
children: filteredLocales.map(renderOption)
|
|
810
905
|
}
|
|
811
906
|
)
|
|
812
907
|
] })
|
|
@@ -838,4 +933,4 @@ var MDXOutboundLink = ({
|
|
|
838
933
|
|
|
839
934
|
export { LocaleDropdown, MDXOutboundLink, NavbarV2, NavbarV2Actions, NavbarV2Brand, NavbarV2Tab, NavbarV2TabMenu, NavbarV2Tabs, SiteFooter };
|
|
840
935
|
//# sourceMappingURL=out.js.map
|
|
841
|
-
//# sourceMappingURL=chunk-
|
|
936
|
+
//# sourceMappingURL=chunk-Q3YVBUKQ.js.map
|