@otl-core/cms-utils 1.1.0 → 1.1.3

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/index.d.cts CHANGED
@@ -1,5 +1,4 @@
1
- import { Category, ResponsiveValue, BorderConfig, ShadowConfig, ColorReference, LocalizedString, BreakpointWithBase, ResponsiveConfig, OrganizationInfo, VocabularyTerm } from '@otl-core/cms-types';
2
- import { ClassValue } from 'clsx';
1
+ import { LocalizedString, ResponsiveValue, BreakpointWithBase, ResponsiveConfig, OrganizationInfo } from '@otl-core/cms-types';
3
2
 
4
3
  /**
5
4
  * A/B/n Variant Resolver
@@ -34,15 +33,6 @@ interface MultivariateFormBlockData {
34
33
  document: unknown;
35
34
  }>;
36
35
  }
37
- /**
38
- * Given a bucket value [0, 1) and variant weights,
39
- * deterministically select a variant.
40
- *
41
- * The weights don't need to sum to 100 -- they are normalized.
42
- * A user with a given bucket will always get the same variant
43
- * for a given weight configuration.
44
- */
45
- declare function selectVariant(bucket: number, variants: VariantConfig[]): string;
46
36
  /**
47
37
  * Check if page content is multivariate.
48
38
  */
@@ -70,134 +60,6 @@ declare function resolveEntryVariant(content: Record<string, unknown>, bucket: n
70
60
  */
71
61
  declare function resolveFormVariantsInSections(sections: unknown[], bucket: number): unknown[];
72
62
 
73
- /**
74
- * Category utility functions
75
- */
76
-
77
- /**
78
- * Tree node with children
79
- */
80
- interface CategoryTreeNode extends Category {
81
- children: CategoryTreeNode[];
82
- }
83
- /**
84
- * Builds a hierarchical tree from flat category array
85
- * @param categories Flat array of categories
86
- * @returns Array of root-level categories with nested children
87
- */
88
- declare function buildCategoryTree(categories: Category[]): CategoryTreeNode[];
89
- /**
90
- * Flattens a category tree back to a flat array
91
- * @param tree Hierarchical category tree
92
- * @returns Flat array of categories
93
- */
94
- declare function flattenCategoryTree(tree: CategoryTreeNode[]): Category[];
95
- /**
96
- * Gets the full path of a category (all ancestors)
97
- * @param categoryId Category ID to get path for
98
- * @param categories Flat array of all categories
99
- * @param locale Locale to use for names (optional)
100
- * @returns Array of categories from root to target
101
- */
102
- declare function getCategoryPath(categoryId: string, categories: Category[], locale?: string): Category[];
103
- /**
104
- * Gets the display name for a category in a specific locale
105
- * @param category Category object
106
- * @param locale Locale code (e.g., 'en', 'de-DE')
107
- * @param fallbackLocale Fallback locale if primary not found
108
- * @returns Display name string
109
- */
110
- declare function getCategoryName(category: Category, locale: string, fallbackLocale?: string): string;
111
- /**
112
- * Gets the slug for a category in a specific locale
113
- * @param category Category object
114
- * @param locale Locale code
115
- * @param fallbackLocale Fallback locale if primary not found
116
- * @returns Slug string
117
- */
118
- declare function getCategorySlug(category: Category, locale: string, fallbackLocale?: string): string;
119
- /**
120
- * Checks if a category is an ancestor of another category
121
- * @param ancestorId Potential ancestor category ID
122
- * @param descendantId Descendant category ID
123
- * @param categories Flat array of all categories
124
- * @returns True if ancestorId is an ancestor of descendantId
125
- */
126
- declare function isAncestor(ancestorId: string, descendantId: string, categories: Category[]): boolean;
127
- /**
128
- * Gets all descendants of a category (recursive)
129
- * @param categoryId Parent category ID
130
- * @param categories Flat array of all categories
131
- * @returns Array of all descendant categories
132
- */
133
- declare function getDescendants(categoryId: string, categories: Category[]): Category[];
134
- /**
135
- * Finds a category by slug in a specific locale
136
- * @param slug Slug to search for
137
- * @param locale Locale code
138
- * @param categories Flat array of all categories
139
- * @returns Category if found, undefined otherwise
140
- */
141
- declare function findCategoryBySlug(slug: string, locale: string, categories: Category[]): Category | undefined;
142
-
143
- /**
144
- * Utility for merging Tailwind CSS class names
145
- * Combines clsx for conditional classes with tailwind-merge to handle conflicts
146
- */
147
-
148
- /**
149
- * Merge class names intelligently
150
- * - Uses clsx for conditional classes
151
- * - Uses tailwind-merge to deduplicate and resolve conflicts
152
- *
153
- * @example
154
- * cn("px-2 py-1", condition && "bg-blue-500")
155
- * cn({ "font-bold": isActive }, "text-lg")
156
- */
157
- declare function cn(...inputs: ClassValue[]): string;
158
-
159
- /**
160
- * CSS Resolution Utilities
161
- * Converts CMS type system values (ColorReference, BorderConfig, ResponsiveValue)
162
- * into CSS strings for rendering.
163
- */
164
-
165
- /**
166
- * Minify CSS by removing comments, extra whitespace, and unnecessary characters
167
- */
168
- declare function minifyCSS(css: string): string;
169
- /**
170
- * Resolve a ColorReference to a CSS color string
171
- */
172
- declare function resolveColorToCSS(colorRef: ColorReference | undefined, target?: "background" | "foreground"): string | undefined;
173
- /**
174
- * Resolve multiple ColorReferences to CSS color strings
175
- */
176
- declare function resolveColorsToCSS<T extends Record<string, ColorReference | undefined>>(colorRefs: T): Partial<Record<keyof T, string>>;
177
- /**
178
- * Resolve a BorderConfig to CSS border properties
179
- */
180
- declare function resolveBorderToCSS(borderConfig: BorderConfig | undefined): Record<string, string> | undefined;
181
- interface ResponsiveSpacingConfig {
182
- border?: ResponsiveValue<BorderConfig>;
183
- margin?: ResponsiveValue<string>;
184
- padding?: ResponsiveValue<string>;
185
- gap?: ResponsiveValue<string>;
186
- shadow?: ResponsiveValue<ShadowConfig>;
187
- }
188
- /**
189
- * Generate responsive CSS for spacing (margin, padding, gap, border) with media queries
190
- */
191
- declare function generateResponsiveSpacingCSS(className: string, config: ResponsiveSpacingConfig): string | null;
192
- /**
193
- * Check if a ResponsiveSpacingConfig has any margin values set
194
- */
195
- declare function hasAnyMargin(config: ResponsiveSpacingConfig): boolean;
196
- /**
197
- * Map animation timing name to CSS timing function
198
- */
199
- declare function getAnimationTimingFunction(timing?: string): string;
200
-
201
63
  /**
202
64
  * Get localized string with proper fallback logic
203
65
  * 1. Try user's preferred locale (from cookie or browser)
@@ -210,47 +72,11 @@ declare function getLocalizedString(value: string | LocalizedString | null | und
210
72
  defaultLocale?: string;
211
73
  supportedLocales?: string[];
212
74
  }): string;
213
- /**
214
- * Get all available locales from a localized string
215
- */
216
- declare function getAvailableLocales(value: string | LocalizedString): string[];
217
- /**
218
- * Check if a value is a localized string object
219
- */
220
- declare function isLocalizedString(value: unknown): value is LocalizedString;
221
- /**
222
- * Detect locale from various sources (URL, browser, config)
223
- * Priority: URL param > path segment > browser language > default
224
- * Note: This function requires browser environment
225
- */
226
- declare function detectLocale(defaultLocale?: string, supportedLocales?: string[]): string;
227
- /**
228
- * Format locale for HTML lang attribute (e.g., 'en-US')
229
- */
230
- declare function formatLocaleForHtml(locale: string): string;
231
75
 
232
76
  /**
233
77
  * Utility functions for working with responsive values
234
78
  */
235
79
 
236
- /** A responsive value where every breakpoint -- including base -- is optional. */
237
- type NormalizedResponsiveValue<T> = {
238
- base?: T;
239
- sm?: T;
240
- md?: T;
241
- lg?: T;
242
- xl?: T;
243
- "2xl"?: T;
244
- };
245
- /**
246
- * Normalize an optional `ResponsiveValue<T>` into a flat object where every
247
- * breakpoint key is optional. Useful for CSS generation loops.
248
- *
249
- * - `undefined` -> `{}`
250
- * - `"8px"` -> `{ base: "8px" }`
251
- * - `{ base: "8px", md: "16px" }` -> same
252
- */
253
- declare function normalizeResponsiveValue<T>(value: ResponsiveValue<T> | undefined): NormalizedResponsiveValue<T>;
254
80
  /**
255
81
  * Type guard to check if a value is a ResponsiveConfig
256
82
  * Requires the object to have a "base" property
@@ -260,32 +86,6 @@ declare function isResponsiveConfig<T>(value: ResponsiveValue<T>): value is Resp
260
86
  * Get value for a specific breakpoint with fallback to base
261
87
  */
262
88
  declare function getBreakpointValue<T>(value: ResponsiveValue<T>, breakpoint: BreakpointWithBase): T;
263
- /**
264
- * Get all defined breakpoints in a responsive value
265
- */
266
- declare function getDefinedBreakpoints<T>(value: ResponsiveValue<T>): BreakpointWithBase[];
267
- /**
268
- * Convert a single value or responsive value to a ResponsiveConfig
269
- */
270
- declare function toResponsiveConfig<T>(fields: {
271
- base: T;
272
- sm?: T;
273
- md?: T;
274
- lg?: T;
275
- xl?: T;
276
- "2xl"?: T;
277
- }): ResponsiveConfig<T>;
278
- /**
279
- * Convert a ResponsiveConfig to flat breakpoint fields
280
- */
281
- declare function fromResponsiveConfig<T>(value: ResponsiveValue<T>): {
282
- base: T;
283
- sm?: T;
284
- md?: T;
285
- lg?: T;
286
- xl?: T;
287
- "2xl"?: T;
288
- };
289
89
 
290
90
  /**
291
91
  * Schedule Resolver
@@ -301,64 +101,6 @@ declare function fromResponsiveConfig<T>(value: ResponsiveValue<T>): {
301
101
  * @returns true if content is visible, false otherwise
302
102
  */
303
103
  declare function isContentVisible(publishAt: string | null | undefined, expiresAt: string | null | undefined, now?: Date): boolean;
304
- /**
305
- * Filter a list of items based on schedule metadata.
306
- * Each item must have optional publish_at and expires_at fields.
307
- *
308
- * @param items - Array of items with schedule metadata
309
- * @param now - Optional current time (defaults to new Date())
310
- * @returns Filtered array containing only currently visible items
311
- */
312
- declare function filterScheduledContent<T extends {
313
- publish_at?: string;
314
- expires_at?: string;
315
- }>(items: T[], now?: Date): T[];
316
-
317
- /**
318
- * Style Utilities
319
- * Helpers to convert CMS config values to CSS strings and Tailwind classes.
320
- * For CSS resolution utilities (resolveColorToCSS, resolveBorderToCSS, etc.)
321
- * see css.utils.ts.
322
- */
323
-
324
- /**
325
- * Convert border config to CSS string
326
- */
327
- declare function borderToStyle(border: ResponsiveValue<BorderConfig> | undefined): string;
328
- /**
329
- * Format shadow config to CSS box-shadow value
330
- */
331
- declare function formatShadow(shadow: ShadowConfig | undefined): string;
332
- /**
333
- * Convert padding config to Tailwind class
334
- */
335
- declare function paddingToClass(padding?: string): string;
336
- /**
337
- * Convert padding top config to Tailwind class
338
- */
339
- declare function paddingTopToClass(paddingTop?: string): string;
340
- /**
341
- * Convert padding bottom config to Tailwind class
342
- */
343
- declare function paddingBottomToClass(paddingBottom?: string): string;
344
- /**
345
- * Convert spacing config to Tailwind class
346
- */
347
- declare function spacingToClass(spacing?: string): string;
348
- /**
349
- * Convert max-width config to Tailwind class
350
- */
351
- declare function widthToClass(width?: string): string;
352
- /**
353
- * Convert color config to inline style object
354
- */
355
- declare function colorToStyle(color?: string): {
356
- backgroundColor?: string;
357
- };
358
- /**
359
- * Convert gap config to Tailwind class
360
- */
361
- declare function gapToClass(gap?: number): string;
362
104
 
363
105
  /**
364
106
  * Password Protection Resolution Utilities
@@ -378,15 +120,6 @@ declare function gapToClass(gap?: number): string;
378
120
  * @returns True if content is password-protected, false otherwise
379
121
  */
380
122
  declare function isPasswordProtected(password_protected?: boolean): boolean;
381
- /**
382
- * Filter password-protected content from a list
383
- * Useful for listings like blog posts where we don't want to show protected items
384
- * @param items - Array of items with password_protected metadata
385
- * @returns Filtered array with only non-protected items
386
- */
387
- declare function filterPasswordProtectedContent<T extends {
388
- password_protected?: boolean;
389
- }>(items: T[]): T[];
390
123
 
391
124
  /**
392
125
  * JSON-LD structured data generation utilities.
@@ -458,35 +191,7 @@ declare function generateJsonLd(input: JsonLdInput): Record<string, unknown>;
458
191
 
459
192
  /**
460
193
  * SEO utility functions for OTL CMS.
461
- *
462
- * These helpers extract common metadata from site configs and are used
463
- * by both the engine's `generateMetadata` and component-level code.
464
- *
465
- * They are environment-agnostic: callers pass an explicit `siteUrlOverride`
466
- * (e.g. from `process.env.NEXT_PUBLIC_SITE_URL`) instead of reading env vars
467
- * directly, keeping the package framework-independent.
468
- */
469
- /**
470
- * Derive the public site origin (no trailing slash).
471
- *
472
- * Priority:
473
- * 1. `siteUrlOverride` (e.g. env var)
474
- * 2. First custom domain from site config
475
- * 3. Subdomain-based OTL Studio URL
476
- */
477
- declare function deriveSiteUrl(configs: Record<string, unknown>, siteUrlOverride?: string): string;
478
- /** Extract the localized site name from configs. */
479
- declare function deriveSiteName(configs: Record<string, unknown>, locale: string): string;
480
- /** Extract the localized site description from configs. */
481
- declare function deriveSiteDescription(configs: Record<string, unknown>, locale: string): string | undefined;
482
- /**
483
- * Detect a locale prefix from the first URL segment.
484
- *
485
- * Returns `[locale, pathWithoutPrefix]`. If the first segment is not a
486
- * recognised locale, the site's default locale and the original path
487
- * are returned unchanged.
488
194
  */
489
- declare function detectLocaleFromSegments(segments: string[], fullPath: string, supportedLocales: string[], defaultLocale: string): [string, string];
490
195
  /**
491
196
  * Convert a short locale code to the `og:locale` format.
492
197
  *
@@ -518,19 +223,4 @@ interface PaginationInfo {
518
223
  */
519
224
  declare function extractPaginationFromLayout(layout: unknown[] | undefined): PaginationInfo | null;
520
225
 
521
- /**
522
- * Resolve a vocabulary term to a plain string.
523
- * Fallback chain: exact locale -> defaultLocale -> first available key -> "".
524
- */
525
- declare function resolveVocabularyTerm(term: VocabularyTerm, locale: string, defaultLocale?: string): string;
526
- /**
527
- * Return a URL-safe slug of the resolved vocabulary term.
528
- */
529
- declare function vocabularySlug(term: VocabularyTerm, locale: string, defaultLocale?: string): string;
530
- /**
531
- * Return the set of locales that are missing a translation for this term.
532
- * Only relevant for localized (object) terms; returns empty array for plain strings.
533
- */
534
- declare function missingVocabularyLocales(term: VocabularyTerm, requiredLocales: string[]): string[];
535
-
536
- export { type CategoryTreeNode, type JsonLdInput, type MultivariateFormBlockData, type MultivariatePageContent, type NormalizedResponsiveValue, type PaginationInfo, type ResponsiveSpacingConfig, type VariantConfig, borderToStyle, buildBreadcrumbs, buildCategoryTree, buildHreflangAlternates, cn, colorToStyle, deriveSiteDescription, deriveSiteName, deriveSiteUrl, detectLocale, detectLocaleFromSegments, extractPaginationFromLayout, filterPasswordProtectedContent, filterScheduledContent, findCategoryBySlug, flattenCategoryTree, formatLocaleForHtml, formatShadow, fromResponsiveConfig, gapToClass, generateJsonLd, generateResponsiveSpacingCSS, getAnimationTimingFunction, getAvailableLocales, getBreakpointValue, getCategoryName, getCategoryPath, getCategorySlug, getDefinedBreakpoints, getDescendants, getLocalizedString, hasAnyMargin, isAncestor, isContentVisible, isLocalizedString, isMultivariateContent, isPasswordProtected, isResponsiveConfig, localeToOgFormat, minifyCSS, missingVocabularyLocales, normalizeResponsiveValue, paddingBottomToClass, paddingToClass, paddingTopToClass, resolveBorderToCSS, resolveColorToCSS, resolveColorsToCSS, resolveEntryVariant, resolveFormVariantsInSections, resolvePageVariant, resolveVocabularyTerm, selectVariant, spacingToClass, toResponsiveConfig, vocabularySlug, widthToClass };
226
+ export { type JsonLdInput, type MultivariateFormBlockData, type MultivariatePageContent, type PaginationInfo, type VariantConfig, buildBreadcrumbs, buildHreflangAlternates, extractPaginationFromLayout, generateJsonLd, getBreakpointValue, getLocalizedString, isContentVisible, isMultivariateContent, isPasswordProtected, isResponsiveConfig, localeToOgFormat, resolveEntryVariant, resolveFormVariantsInSections, resolvePageVariant };