@deneb-ui/ui 2.0.23 → 2.0.24

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.
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ /**
3
+ * Base CSS variable mappings for real-time visual style editing.
4
+ * Components apply `--deneb-*` vars via useComponentStyle; this sheet defines fallbacks.
5
+ */
6
+ export declare function DenebComponentStyles(): React.JSX.Element;
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DenebComponentStyles = DenebComponentStyles;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ /**
6
+ * Base CSS variable mappings for real-time visual style editing.
7
+ * Components apply `--deneb-*` vars via useComponentStyle; this sheet defines fallbacks.
8
+ */
9
+ function DenebComponentStyles() {
10
+ const css = `
11
+ .deneb-card {
12
+ width: var(--deneb-card-width, auto);
13
+ min-width: var(--deneb-card-min-width, unset);
14
+ max-width: var(--deneb-card-max-width, 100%);
15
+ height: var(--deneb-card-height, auto);
16
+ aspect-ratio: var(--deneb-card-aspect-ratio, auto);
17
+ padding-top: var(--deneb-card-pt, 1.25rem);
18
+ padding-bottom: var(--deneb-card-pb, 1.25rem);
19
+ padding-left: var(--deneb-card-pl, 1.25rem);
20
+ padding-right: var(--deneb-card-pr, 1.25rem);
21
+ border-radius: var(--deneb-card-radius, 0.75rem);
22
+ border-width: var(--deneb-card-border-w, 0);
23
+ border-style: var(--deneb-card-border-s, solid);
24
+ border-color: var(--deneb-card-border-c, rgba(0, 0, 0, 0.08));
25
+ background-color: var(--deneb-card-bg, transparent);
26
+ background-image: var(--deneb-card-bg-gradient, none);
27
+ box-shadow: var(--deneb-card-shadow, none);
28
+ backdrop-filter: blur(var(--deneb-card-blur, 0px));
29
+ gap: var(--deneb-card-gap, unset);
30
+ transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
31
+ }
32
+ .deneb-card-balance {
33
+ display: flex;
34
+ flex-direction: column;
35
+ flex: 1 1 0%;
36
+ min-width: 0;
37
+ height: 100%;
38
+ }
39
+ .deneb-text {
40
+ font-family: var(--deneb-font-family, inherit);
41
+ font-size: var(--deneb-font-size, inherit);
42
+ font-weight: var(--deneb-font-weight, inherit);
43
+ line-height: var(--deneb-line-height, inherit);
44
+ letter-spacing: var(--deneb-letter-spacing, inherit);
45
+ color: var(--deneb-color, inherit);
46
+ text-align: var(--deneb-text-align, inherit);
47
+ text-transform: var(--deneb-text-transform, inherit);
48
+ margin-top: var(--deneb-margin-top, 0);
49
+ margin-bottom: var(--deneb-margin-bottom, 0);
50
+ margin-left: var(--deneb-margin-left, 0);
51
+ margin-right: var(--deneb-margin-right, 0);
52
+ }
53
+ .deneb-btn {
54
+ border-radius: var(--deneb-btn-radius, inherit);
55
+ padding-left: var(--deneb-btn-px, inherit);
56
+ padding-right: var(--deneb-btn-px, inherit);
57
+ padding-top: var(--deneb-btn-py, inherit);
58
+ padding-bottom: var(--deneb-btn-py, inherit);
59
+ background-color: var(--deneb-btn-bg, inherit);
60
+ color: var(--deneb-btn-color, inherit);
61
+ border-color: var(--deneb-btn-border-c, inherit);
62
+ }
63
+ .deneb-btn:hover {
64
+ background-color: var(--deneb-btn-hover-bg, inherit);
65
+ color: var(--deneb-btn-hover-color, inherit);
66
+ }
67
+ .deneb-grid {
68
+ grid-template-columns: var(--deneb-grid-cols, inherit);
69
+ column-gap: var(--deneb-grid-gap-x, inherit);
70
+ row-gap: var(--deneb-grid-gap-y, inherit);
71
+ align-items: var(--deneb-grid-equal-height, inherit);
72
+ }
73
+ .deneb-section {
74
+ padding-top: var(--deneb-section-pt, inherit);
75
+ padding-bottom: var(--deneb-section-pb, inherit);
76
+ padding-left: var(--deneb-section-px, inherit);
77
+ padding-right: var(--deneb-section-px, inherit);
78
+ max-width: var(--deneb-section-max-w, inherit);
79
+ background-color: var(--deneb-section-bg, inherit);
80
+ background-image: var(--deneb-section-bg-image, none);
81
+ }
82
+ `;
83
+ return (0, jsx_runtime_1.jsx)("style", { "data-deneb-component-styles": true, children: css });
84
+ }
@@ -4,6 +4,7 @@ exports.EditableCard = EditableCard;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const EditableText_1 = require("./EditableText");
6
6
  const EditableImage_1 = require("./EditableImage");
7
+ const useComponentStyle_1 = require("./hooks/useComponentStyle");
7
8
  const RADIUS_MAP = {
8
9
  none: '0px',
9
10
  sm: '4px',
@@ -57,6 +58,8 @@ function EditableCard({ itemPath, item, titleKey = 'title', bodyKey = 'body', im
57
58
  : typeof border === 'string'
58
59
  ? border
59
60
  : undefined;
61
+ const stylePath = `${itemPath}.card`;
62
+ const { cssVars: styleVars } = (0, useComponentStyle_1.useComponentStyle)(stylePath, 'card');
60
63
  const cardStyle = {
61
64
  ...(width !== undefined ? { width } : {}),
62
65
  ...(minWidth !== undefined ? { minWidth } : {}),
@@ -79,7 +82,8 @@ function EditableCard({ itemPath, item, titleKey = 'title', bodyKey = 'body', im
79
82
  ...(resolvedBorder ? { border: resolvedBorder } : {}),
80
83
  ...(resolvedPadding ? { padding: resolvedPadding } : {}),
81
84
  ...(align ? { textAlign: align } : {}),
85
+ ...styleVars,
82
86
  ...style,
83
87
  };
84
- return ((0, jsx_runtime_1.jsxs)(Component, { "data-preview-item-path": itemPath, className: `editable-card ${className}`.trim(), style: cardStyle, ...props, children: [imageUrl !== undefined && ((0, jsx_runtime_1.jsx)("div", { className: "editable-card-image-wrap", children: (0, jsx_runtime_1.jsx)(EditableImage_1.EditableImage, { id: `${itemPath}.${imageKey}`, src: imageUrl, fallbackSrc: imageFallback, alt: title, className: "editable-card-image" }) })), (0, jsx_runtime_1.jsx)("div", { className: "editable-card-body", style: balance ? { display: 'flex', flexDirection: 'column', flex: '1 1 auto' } : undefined, children: children ? (children) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { variant: "h3", color: "heading", id: `${itemPath}.${titleKey}`, "data-preview-field-path": `${itemPath}.${titleKey}`, defaultValue: title, className: "editable-card-title" }), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { variant: "p", color: "muted", id: `${itemPath}.${bodyKey}`, "data-preview-field-path": `${itemPath}.${bodyKey}`, defaultValue: body, className: "editable-card-body-text" })] })) })] }));
88
+ return ((0, jsx_runtime_1.jsxs)(Component, { "data-preview-item-path": itemPath, "data-preview-style-target": stylePath, "data-preview-style-type": "card", className: `deneb-card editable-card ${balance ? 'deneb-card-balance' : ''} ${className}`.trim(), style: cardStyle, ...props, children: [imageUrl !== undefined && ((0, jsx_runtime_1.jsx)("div", { className: "editable-card-image-wrap", children: (0, jsx_runtime_1.jsx)(EditableImage_1.EditableImage, { id: `${itemPath}.${imageKey}`, src: imageUrl, fallbackSrc: imageFallback, alt: title, className: "editable-card-image" }) })), (0, jsx_runtime_1.jsx)("div", { className: "editable-card-body", style: balance ? { display: 'flex', flexDirection: 'column', flex: '1 1 auto' } : undefined, children: children ? (children) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { variant: "h3", color: "heading", id: `${itemPath}.${titleKey}`, "data-preview-field-path": `${itemPath}.${titleKey}`, defaultValue: title, className: "editable-card-title" }), (0, jsx_runtime_1.jsx)(EditableText_1.EditableText, { variant: "p", color: "muted", id: `${itemPath}.${bodyKey}`, "data-preview-field-path": `${itemPath}.${bodyKey}`, defaultValue: body, className: "editable-card-body-text" })] })) })] }));
85
89
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EditableGrid = EditableGrid;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const useComponentStyle_1 = require("./hooks/useComponentStyle");
5
6
  const responsive_1 = require("./utils/responsive");
6
7
  const SPACING_MAP = {
7
8
  none: '0',
@@ -19,6 +20,9 @@ const SPACING_MAP = {
19
20
  function EditableGrid({ as: Component = 'div', id, 'data-preview-list-path': previewListPath, 'data-preview-static': previewStatic, minCardWidth = '280px', columns, gap = 'md', equalHeight = true, align = 'stretch', style, className = '', children, ...props }) {
20
21
  const resolvedGap = gap !== undefined ? (SPACING_MAP[String(gap)] || String(gap)) : '1.25rem';
21
22
  const { template: templateCols, dataAttrs } = (0, responsive_1.resolveResponsiveColumns)(columns, minCardWidth);
23
+ const listPath = previewListPath || id;
24
+ const stylePath = listPath ? `${listPath}.grid` : undefined;
25
+ const { cssVars: styleVars } = (0, useComponentStyle_1.useComponentStyle)(stylePath, 'grid');
22
26
  const gridStyle = {
23
27
  display: 'grid',
24
28
  gridTemplateColumns: templateCols,
@@ -31,7 +35,8 @@ function EditableGrid({ as: Component = 'div', id, 'data-preview-list-path': pre
31
35
  '--deneb-cols-desktop': dataAttrs['data-cols-desktop'],
32
36
  }
33
37
  : {}),
38
+ ...styleVars,
34
39
  ...style,
35
40
  };
36
- return ((0, jsx_runtime_1.jsx)(Component, { "data-preview-list-path": previewListPath || id, className: `editable-grid ${className}`.trim(), style: gridStyle, ...(dataAttrs || {}), ...props, children: children }));
41
+ return ((0, jsx_runtime_1.jsx)(Component, { "data-preview-list-path": listPath, "data-preview-style-target": stylePath, "data-preview-style-type": "grid", className: `deneb-grid editable-grid ${className}`.trim(), style: gridStyle, ...(dataAttrs || {}), ...props, children: children }));
37
42
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EditableSection = EditableSection;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const useComponentStyle_1 = require("./hooks/useComponentStyle");
5
6
  const responsive_1 = require("./utils/responsive");
6
7
  const SECTION_PADDING_MAP = responsive_1.RESPONSIVE_SECTION_PADDING;
7
8
  /**
@@ -15,13 +16,16 @@ function EditableSection({ as: Component = 'section', name, padding = 'lg', bg,
15
16
  : typeof border === 'string'
16
17
  ? border
17
18
  : undefined;
19
+ const stylePath = `${name}.section`;
20
+ const { cssVars: styleVars } = (0, useComponentStyle_1.useComponentStyle)(stylePath, 'section');
18
21
  const sectionStyle = {
19
22
  ...(resolvedPadding ? { padding: resolvedPadding } : {}),
20
23
  ...(bg ? { background: bg } : {}),
21
24
  ...(color ? { color } : {}),
22
25
  ...(maxWidth !== undefined ? { maxWidth, marginLeft: 'auto', marginRight: 'auto' } : {}),
23
26
  ...(resolvedBorder ? { borderBottom: resolvedBorder } : {}),
27
+ ...styleVars,
24
28
  ...style,
25
29
  };
26
- return ((0, jsx_runtime_1.jsx)(Component, { "data-design-section": name, className: `editable-section ${className}`.trim(), style: sectionStyle, ...props, children: children }));
30
+ return ((0, jsx_runtime_1.jsx)(Component, { "data-design-section": name, "data-preview-style-target": stylePath, "data-preview-style-type": "section", className: `deneb-section editable-section ${className}`.trim(), style: sectionStyle, ...props, children: children }));
27
31
  }
@@ -81,7 +81,7 @@ export interface EditableTextProps extends React.HTMLAttributes<HTMLElement> {
81
81
  * EditableText provides full typography controls (color, size, weight, line-height, alignment, transform, variants)
82
82
  * alongside strict Fivora visual editing bindings.
83
83
  */
84
- export declare function EditableText({ id, 'data-preview-field-path': previewFieldPath, defaultValue, placeholder, children, as: ComponentOverride, variant, color, size, weight, lineHeight, align, transform, letterSpacing, fontFamily, style, ...props }: EditableTextProps): React.JSX.Element;
84
+ export declare function EditableText({ id, 'data-preview-field-path': previewFieldPath, defaultValue, placeholder, children, as: ComponentOverride, variant, color, size, weight, lineHeight, align, transform, letterSpacing, fontFamily, style, className, ...props }: EditableTextProps): React.JSX.Element;
85
85
  export interface EditableHeadingProps extends Omit<EditableTextProps, 'variant'> {
86
86
  level?: 1 | 2 | 3 | 4 | 5 | 6;
87
87
  }
@@ -10,7 +10,7 @@ exports.EditableQuote = EditableQuote;
10
10
  exports.EditableLink = EditableLink;
11
11
  exports.EditableButton = EditableButton;
12
12
  const jsx_runtime_1 = require("react/jsx-runtime");
13
- const SiteDataProvider_1 = require("./SiteDataProvider");
13
+ const useComponentStyle_1 = require("./hooks/useComponentStyle");
14
14
  exports.SIZE_MAP = {
15
15
  xs: '0.75rem',
16
16
  sm: '0.875rem',
@@ -106,7 +106,7 @@ function toCssUnit(value) {
106
106
  * EditableText provides full typography controls (color, size, weight, line-height, alignment, transform, variants)
107
107
  * alongside strict Fivora visual editing bindings.
108
108
  */
109
- function EditableText({ id, 'data-preview-field-path': previewFieldPath, defaultValue, placeholder, children, as: ComponentOverride, variant, color, size, weight, lineHeight, align, transform, letterSpacing, fontFamily, style, ...props }) {
109
+ function EditableText({ id, 'data-preview-field-path': previewFieldPath, defaultValue, placeholder, children, as: ComponentOverride, variant, color, size, weight, lineHeight, align, transform, letterSpacing, fontFamily, style, className = '', ...props }) {
110
110
  const path = previewFieldPath || id;
111
111
  const rawContent = children !== undefined ? children : defaultValue;
112
112
  const isContentEmpty = rawContent === undefined ||
@@ -114,7 +114,7 @@ function EditableText({ id, 'data-preview-field-path': previewFieldPath, default
114
114
  (typeof rawContent === 'string' && rawContent.trim() === '');
115
115
  const isPlaceholderActive = isContentEmpty && Boolean(placeholder);
116
116
  const displayContent = isPlaceholderActive ? placeholder : rawContent;
117
- const dynamicStyle = (0, SiteDataProvider_1.useFieldStyle)(path);
117
+ const { cssVars: styleVars } = (0, useComponentStyle_1.useComponentStyle)(path, 'text');
118
118
  const variantDefaults = variant ? exports.VARIANT_DEFAULTS[variant] : undefined;
119
119
  const Component = ComponentOverride || variantDefaults?.as || 'span';
120
120
  const effectiveColor = color || variantDefaults?.color;
@@ -134,24 +134,6 @@ function EditableText({ id, 'data-preview-field-path': previewFieldPath, default
134
134
  const resolvedFontFamily = effectiveFontFamily
135
135
  ? (exports.FONT_FAMILY_MAP[effectiveFontFamily] || effectiveFontFamily)
136
136
  : undefined;
137
- // Dynamic visual editor overrides
138
- const dynamicColor = dynamicStyle?.color
139
- ? (exports.COLOR_MAP[String(dynamicStyle.color)] || String(dynamicStyle.color))
140
- : undefined;
141
- const dynamicSize = dynamicStyle?.fontSize !== undefined && dynamicStyle?.fontSize !== ''
142
- ? (exports.SIZE_MAP[String(dynamicStyle.fontSize)] || toCssUnit(dynamicStyle.fontSize))
143
- : undefined;
144
- const dynamicLineHeight = dynamicStyle?.lineHeight !== undefined && dynamicStyle?.lineHeight !== ''
145
- ? (exports.LINE_HEIGHT_MAP[String(dynamicStyle.lineHeight)] || dynamicStyle.lineHeight)
146
- : undefined;
147
- const dynamicFontFamily = dynamicStyle?.fontFamily
148
- ? (exports.FONT_FAMILY_MAP[String(dynamicStyle.fontFamily)] || String(dynamicStyle.fontFamily))
149
- : undefined;
150
- const dynamicAlign = dynamicStyle?.textAlign;
151
- const dynamicMarginTop = toCssUnit(dynamicStyle?.spacingTop);
152
- const dynamicMarginBottom = toCssUnit(dynamicStyle?.spacingBottom);
153
- const dynamicMarginLeft = toCssUnit(dynamicStyle?.spacingLeft);
154
- const dynamicMarginRight = toCssUnit(dynamicStyle?.spacingRight);
155
137
  const typographyStyle = {
156
138
  // Minimum dimensions ensure empty/placeholder elements never collapse to 0x0 and remain 100% clickable in Fivora
157
139
  minHeight: '1.2em',
@@ -166,19 +148,10 @@ function EditableText({ id, 'data-preview-field-path': previewFieldPath, default
166
148
  ...(effectiveTransform ? { textTransform: effectiveTransform } : {}),
167
149
  ...(resolvedLetterSpacing ? { letterSpacing: resolvedLetterSpacing } : {}),
168
150
  ...(resolvedFontFamily ? { fontFamily: resolvedFontFamily } : {}),
151
+ ...styleVars,
169
152
  ...style,
170
- // Visual editor overrides take highest precedence:
171
- ...(dynamicColor ? { color: dynamicColor } : {}),
172
- ...(dynamicSize ? { fontSize: dynamicSize } : {}),
173
- ...(dynamicLineHeight ? { lineHeight: dynamicLineHeight } : {}),
174
- ...(dynamicAlign ? { textAlign: dynamicAlign } : {}),
175
- ...(dynamicFontFamily ? { fontFamily: dynamicFontFamily } : {}),
176
- ...(dynamicMarginTop !== undefined ? { marginTop: dynamicMarginTop } : {}),
177
- ...(dynamicMarginBottom !== undefined ? { marginBottom: dynamicMarginBottom } : {}),
178
- ...(dynamicMarginLeft !== undefined ? { marginLeft: dynamicMarginLeft } : {}),
179
- ...(dynamicMarginRight !== undefined ? { marginRight: dynamicMarginRight } : {}),
180
153
  };
181
- return ((0, jsx_runtime_1.jsx)(Component, { "data-preview-field-path": path, "data-preview-placeholder": isPlaceholderActive ? 'true' : undefined, style: typographyStyle, ...props, children: displayContent }));
154
+ return ((0, jsx_runtime_1.jsx)(Component, { "data-preview-field-path": path, "data-preview-style-target": path, "data-preview-style-type": "text", "data-preview-placeholder": isPlaceholderActive ? 'true' : undefined, className: `deneb-text ${className}`.trim(), style: typographyStyle, ...props, children: displayContent }));
182
155
  }
183
156
  function EditableHeading({ level = 2, as, ...props }) {
184
157
  const variant = `h${level}`;
@@ -270,6 +243,7 @@ function EditableLink({ id, 'data-preview-field-path': previewFieldPath, targetP
270
243
  function EditableButton({ id, 'data-preview-field-path': previewFieldPath, defaultValue, targetPage, btnVariant = 'primary', size = 'md', children, className = '', style, ...props }) {
271
244
  const path = previewFieldPath || id;
272
245
  const content = children !== undefined ? children : defaultValue;
246
+ const { cssVars: styleVars } = (0, useComponentStyle_1.useComponentStyle)(path, 'button');
273
247
  const sizeStyles = {
274
248
  sm: { padding: '0.375rem 0.875rem', fontSize: '0.875rem', borderRadius: '6px' },
275
249
  md: { padding: '0.625rem 1.25rem', fontSize: '1rem', borderRadius: '8px' },
@@ -319,9 +293,10 @@ function EditableButton({ id, 'data-preview-field-path': previewFieldPath, defau
319
293
  transition: 'all 0.2s cubic-bezier(0.4, 0, 0.2, 1)',
320
294
  ...sizeStyles[size],
321
295
  ...variantStyles[btnVariant],
296
+ ...styleVars,
322
297
  ...style,
323
298
  };
324
- const buttonEl = ((0, jsx_runtime_1.jsx)("button", { style: baseStyle, className: `editable-btn ${className}`.trim(), ...props, children: path ? ((0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": path, children: content })) : (content) }));
299
+ const buttonEl = ((0, jsx_runtime_1.jsx)("button", { "data-preview-style-target": path, "data-preview-style-type": "button", style: baseStyle, className: `deneb-btn editable-btn ${className}`.trim(), ...props, children: path ? ((0, jsx_runtime_1.jsx)("span", { "data-preview-field-path": path, children: content })) : (content) }));
325
300
  if (targetPage) {
326
301
  return (0, jsx_runtime_1.jsx)("span", { "data-target-page": targetPage, children: buttonEl });
327
302
  }
@@ -9,6 +9,7 @@ export declare const DENEB_PREVIEW_FOCUS_MESSAGE = "DENEB_PREVIEW_FOCUS_PAGE";
9
9
  export declare const PREVIEW_FOCUS_MESSAGE = "FIVORA_PREVIEW_FOCUS_PAGE";
10
10
  export declare const LEGACY_PREVIEW_FOCUS_MESSAGE: string;
11
11
  export declare const PREVIEW_FIELD_ATTRIBUTE = "data-preview-field-path";
12
+ export { STYLE_PATCH_MESSAGE, DENEB_STYLE_PATCH_MESSAGE } from '@deneb-ui/core';
12
13
  export type GenericRecord = Record<string, unknown>;
13
14
  export type SiteData = {
14
15
  project?: {
@@ -25,6 +26,7 @@ export type SiteData = {
25
26
  requiredPages?: string[] | null;
26
27
  } | null;
27
28
  content?: GenericRecord | null;
29
+ styles?: GenericRecord | null;
28
30
  [key: string]: unknown;
29
31
  };
30
32
  export declare const SiteDataContext: React.Context<SiteData>;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  'use client';
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.DenebDataContext = exports.useDenebData = exports.DenebDataProvider = exports.SiteDataContext = exports.PREVIEW_FIELD_ATTRIBUTE = exports.LEGACY_PREVIEW_FOCUS_MESSAGE = exports.PREVIEW_FOCUS_MESSAGE = exports.DENEB_PREVIEW_FOCUS_MESSAGE = exports.LEGACY_PREVIEW_READY_MESSAGE = exports.PREVIEW_READY_MESSAGE = exports.DENEB_PREVIEW_READY_MESSAGE = exports.LEGACY_PREVIEW_DATA_MESSAGE = exports.PREVIEW_DATA_MESSAGE = exports.DENEB_PREVIEW_DATA_MESSAGE = void 0;
4
+ exports.DenebDataContext = exports.useDenebData = exports.DenebDataProvider = exports.SiteDataContext = exports.DENEB_STYLE_PATCH_MESSAGE = exports.STYLE_PATCH_MESSAGE = exports.PREVIEW_FIELD_ATTRIBUTE = exports.LEGACY_PREVIEW_FOCUS_MESSAGE = exports.PREVIEW_FOCUS_MESSAGE = exports.DENEB_PREVIEW_FOCUS_MESSAGE = exports.LEGACY_PREVIEW_READY_MESSAGE = exports.PREVIEW_READY_MESSAGE = exports.DENEB_PREVIEW_READY_MESSAGE = exports.LEGACY_PREVIEW_DATA_MESSAGE = exports.PREVIEW_DATA_MESSAGE = exports.DENEB_PREVIEW_DATA_MESSAGE = void 0;
5
5
  exports.isRecord = isRecord;
6
6
  exports.mergeSiteData = mergeSiteData;
7
7
  exports.normalizeOrigin = normalizeOrigin;
@@ -17,6 +17,9 @@ exports.getFieldStyle = getFieldStyle;
17
17
  exports.useFieldStyle = useFieldStyle;
18
18
  const jsx_runtime_1 = require("react/jsx-runtime");
19
19
  const react_1 = require("react");
20
+ const core_1 = require("@deneb-ui/core");
21
+ const DenebComponentStyles_1 = require("./DenebComponentStyles");
22
+ const FontLoader_1 = require("./fonts/FontLoader");
20
23
  const ResponsiveBaseStyles_1 = require("./ResponsiveBaseStyles");
21
24
  exports.DENEB_PREVIEW_DATA_MESSAGE = 'DENEB_PREVIEW_SITE_DATA';
22
25
  exports.PREVIEW_DATA_MESSAGE = 'FIVORA_PREVIEW_SITE_DATA';
@@ -31,6 +34,9 @@ exports.DENEB_PREVIEW_FOCUS_MESSAGE = 'DENEB_PREVIEW_FOCUS_PAGE';
31
34
  exports.PREVIEW_FOCUS_MESSAGE = 'FIVORA_PREVIEW_FOCUS_PAGE';
32
35
  exports.LEGACY_PREVIEW_FOCUS_MESSAGE = previousPreviewMessage('FOCUS_PAGE');
33
36
  exports.PREVIEW_FIELD_ATTRIBUTE = 'data-preview-field-path';
37
+ var core_2 = require("@deneb-ui/core");
38
+ Object.defineProperty(exports, "STYLE_PATCH_MESSAGE", { enumerable: true, get: function () { return core_2.STYLE_PATCH_MESSAGE; } });
39
+ Object.defineProperty(exports, "DENEB_STYLE_PATCH_MESSAGE", { enumerable: true, get: function () { return core_2.DENEB_STYLE_PATCH_MESSAGE; } });
34
40
  const PARENT_ORIGIN_KEY = '__FIVORA_PREVIEW_PARENT_ORIGIN__';
35
41
  const LEGACY_PARENT_ORIGIN_KEY = previousPreviewStorageKey('PARENT_ORIGIN');
36
42
  const SITE_DATA_CACHE_KEY = '__FIVORA_PREVIEW_SITE_DATA_CACHE__';
@@ -51,7 +57,7 @@ function mergeSiteData(current, incoming) {
51
57
  for (const key of Object.keys(incoming)) {
52
58
  // Parent preview always sends complete content/media snapshots. Replacing
53
59
  // them wholesale avoids deep-cloning large collections on every keystroke.
54
- if (key === 'content' || key === 'media') {
60
+ if (key === 'content' || key === 'media' || key === 'styles') {
55
61
  next[key] = incoming[key];
56
62
  continue;
57
63
  }
@@ -201,7 +207,9 @@ function SiteDataProvider({ children, initialSiteData, fallbackSiteData, }) {
201
207
  const isFocus = event.data.type === exports.DENEB_PREVIEW_FOCUS_MESSAGE ||
202
208
  event.data.type === exports.PREVIEW_FOCUS_MESSAGE ||
203
209
  event.data.type === exports.LEGACY_PREVIEW_FOCUS_MESSAGE;
204
- if (!isData && !isFocus) {
210
+ const isStylePatch = event.data.type === core_1.STYLE_PATCH_MESSAGE ||
211
+ event.data.type === core_1.DENEB_STYLE_PATCH_MESSAGE;
212
+ if (!isData && !isFocus && !isStylePatch) {
205
213
  return;
206
214
  }
207
215
  // Pin the first concrete parent origin when referrer was suppressed.
@@ -226,6 +234,15 @@ function SiteDataProvider({ children, initialSiteData, fallbackSiteData, }) {
226
234
  applyIncomingSiteData(event.data.siteData);
227
235
  return;
228
236
  }
237
+ if (isStylePatch) {
238
+ const targetPath = typeof event.data.targetPath === 'string' ? event.data.targetPath : '';
239
+ const styleType = typeof event.data.styleType === 'string' ? event.data.styleType : 'text';
240
+ const properties = isRecord(event.data.properties) ? event.data.properties : {};
241
+ if (targetPath) {
242
+ (0, core_1.patchStyleByPath)(targetPath, styleType, properties);
243
+ }
244
+ return;
245
+ }
229
246
  if (isFocus) {
230
247
  const fieldPath = typeof event.data.fieldPath === 'string' ? event.data.fieldPath : '';
231
248
  if (!fieldPath)
@@ -249,7 +266,7 @@ function SiteDataProvider({ children, initialSiteData, fallbackSiteData, }) {
249
266
  return () => window.removeEventListener('message', onMessage);
250
267
  }, []);
251
268
  const value = (0, react_1.useMemo)(() => siteData, [siteData]);
252
- return ((0, jsx_runtime_1.jsxs)(exports.SiteDataContext.Provider, { value: value, children: [(0, jsx_runtime_1.jsx)(ResponsiveBaseStyles_1.ResponsiveBaseStyles, {}), children] }));
269
+ return ((0, jsx_runtime_1.jsxs)(exports.SiteDataContext.Provider, { value: value, children: [(0, jsx_runtime_1.jsx)(FontLoader_1.FontLoader, {}), (0, jsx_runtime_1.jsx)(ResponsiveBaseStyles_1.ResponsiveBaseStyles, {}), (0, jsx_runtime_1.jsx)(DenebComponentStyles_1.DenebComponentStyles, {}), children] }));
253
270
  }
254
271
  function useSiteData() {
255
272
  return (0, react_1.useContext)(exports.SiteDataContext);
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ export declare const DENEB_FONTS_LINK_ID = "deneb-google-fonts";
3
+ export interface FontLoaderProps {
4
+ /** Additional font ids to preload beyond site-data discovery */
5
+ fontIds?: string[];
6
+ /** Use Google Fonts CDN (default in preview). Set false when `deneb fonts install` CSS is present */
7
+ useGoogleCdn?: boolean;
8
+ }
9
+ /**
10
+ * Dynamically loads Google Fonts used by the active site-data theme + style tree.
11
+ * In production, pair with `deneb fonts install` which writes self-hosted @fontsource CSS.
12
+ */
13
+ export declare function FontLoader({ fontIds, useGoogleCdn }: FontLoaderProps): React.JSX.Element | null;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.DENEB_FONTS_LINK_ID = void 0;
5
+ exports.FontLoader = FontLoader;
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ const react_1 = require("react");
8
+ const useDenebFonts_1 = require("./useDenebFonts");
9
+ exports.DENEB_FONTS_LINK_ID = 'deneb-google-fonts';
10
+ /**
11
+ * Dynamically loads Google Fonts used by the active site-data theme + style tree.
12
+ * In production, pair with `deneb fonts install` which writes self-hosted @fontsource CSS.
13
+ */
14
+ function FontLoader({ fontIds = [], useGoogleCdn = true }) {
15
+ const { googleStylesheetUrl, cssVariables, fontIds: activeFontIds } = (0, useDenebFonts_1.useDenebFonts)(fontIds);
16
+ const loadedUrl = (0, react_1.useRef)(null);
17
+ const enableCdn = useGoogleCdn;
18
+ (0, react_1.useEffect)(() => {
19
+ if (!enableCdn || !googleStylesheetUrl || typeof document === 'undefined')
20
+ return;
21
+ const selfHosted = getComputedStyle(document.documentElement)
22
+ .getPropertyValue('--deneb-fonts-selfhosted')
23
+ .trim();
24
+ if (selfHosted === '1')
25
+ return;
26
+ if (loadedUrl.current === googleStylesheetUrl)
27
+ return;
28
+ let link = document.getElementById(exports.DENEB_FONTS_LINK_ID);
29
+ if (!link) {
30
+ link = document.createElement('link');
31
+ link.id = exports.DENEB_FONTS_LINK_ID;
32
+ link.rel = 'stylesheet';
33
+ document.head.appendChild(link);
34
+ }
35
+ link.href = googleStylesheetUrl;
36
+ loadedUrl.current = googleStylesheetUrl;
37
+ }, [enableCdn, googleStylesheetUrl]);
38
+ if (Object.keys(cssVariables).length === 0)
39
+ return null;
40
+ return ((0, jsx_runtime_1.jsx)("style", { "data-deneb-font-vars": true, "data-deneb-font-count": activeFontIds.length, children: `:root { ${Object.entries(cssVariables)
41
+ .map(([key, value]) => `${key}: ${value};`)
42
+ .join(' ')} }` }));
43
+ }
@@ -0,0 +1,6 @@
1
+ export declare function useDenebFonts(extraFontIds?: string[]): {
2
+ fontIds: string[];
3
+ googleStylesheetUrl: string | null;
4
+ cssVariables: Record<string, string>;
5
+ catalog: (import("@deneb-ui/core").DenebFontDefinition | null)[];
6
+ };
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.useDenebFonts = useDenebFonts;
5
+ const react_1 = require("react");
6
+ const core_1 = require("@deneb-ui/core");
7
+ const SiteDataProvider_1 = require("../SiteDataProvider");
8
+ function useDenebFonts(extraFontIds = []) {
9
+ const siteData = (0, SiteDataProvider_1.useSiteData)();
10
+ const fontIds = (0, react_1.useMemo)(() => {
11
+ const fromSite = (0, core_1.collectFontIdsFromSiteData)(siteData);
12
+ const merged = new Set([...fromSite, ...extraFontIds.filter(Boolean)]);
13
+ return Array.from(merged);
14
+ }, [siteData, extraFontIds]);
15
+ const googleStylesheetUrl = (0, react_1.useMemo)(() => (0, core_1.buildGoogleFontsStylesheetUrl)(fontIds), [fontIds]);
16
+ const cssVariables = (0, react_1.useMemo)(() => {
17
+ const theme = siteData?.theme ??
18
+ siteData
19
+ ?.template?.structure?.theme;
20
+ const heading = (0, core_1.resolveFontFamily)(typeof theme?.headingFont === 'string' ? theme.headingFont : undefined);
21
+ const body = (0, core_1.resolveFontFamily)(typeof theme?.bodyFont === 'string' ? theme.bodyFont : undefined);
22
+ return {
23
+ ...(heading ? { '--heading-font': heading } : {}),
24
+ ...(body ? { '--body-font': body } : {}),
25
+ };
26
+ }, [siteData]);
27
+ const catalog = (0, react_1.useMemo)(() => fontIds.map((id) => (0, core_1.lookupFontDefinition)(id)).filter(Boolean), [fontIds]);
28
+ return { fontIds, googleStylesheetUrl, cssVariables, catalog };
29
+ }
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { type StyleKind } from '@deneb-ui/core';
3
+ import { type GenericRecord } from '../SiteDataProvider';
4
+ export declare function resolveComponentStyle(siteData: GenericRecord, stylePath: string, defaults?: GenericRecord): GenericRecord;
5
+ export declare function useComponentStyle<T extends GenericRecord = GenericRecord>(stylePath: string | undefined, styleKind: StyleKind, defaults?: Partial<T>): {
6
+ style: T;
7
+ cssVars: React.CSSProperties;
8
+ };
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.resolveComponentStyle = resolveComponentStyle;
5
+ exports.useComponentStyle = useComponentStyle;
6
+ const react_1 = require("react");
7
+ const core_1 = require("@deneb-ui/core");
8
+ const SiteDataProvider_1 = require("../SiteDataProvider");
9
+ function getNestedValue(root, dottedPath) {
10
+ if (!root || !dottedPath)
11
+ return undefined;
12
+ const parts = (0, SiteDataProvider_1.parseFieldPath)(dottedPath);
13
+ let current = root;
14
+ for (const part of parts) {
15
+ if (typeof part === 'number') {
16
+ if (!Array.isArray(current))
17
+ return undefined;
18
+ current = current[part];
19
+ }
20
+ else {
21
+ if (!(0, SiteDataProvider_1.isRecord)(current))
22
+ return undefined;
23
+ current = current[part];
24
+ }
25
+ }
26
+ return current;
27
+ }
28
+ function resolveComponentStyle(siteData, stylePath, defaults) {
29
+ const stylesTree = (0, SiteDataProvider_1.isRecord)(siteData.styles) ? siteData.styles : {};
30
+ const fromStylesTree = stylesTree[stylePath];
31
+ const fromContentSuffix = (0, SiteDataProvider_1.getFieldStyle)(siteData.content, stylePath);
32
+ const raw = (0, SiteDataProvider_1.isRecord)(fromStylesTree)
33
+ ? fromStylesTree
34
+ : fromContentSuffix ?? {};
35
+ return { ...(defaults ?? {}), ...raw };
36
+ }
37
+ function useComponentStyle(stylePath, styleKind, defaults) {
38
+ const siteData = (0, SiteDataProvider_1.useSiteData)();
39
+ const merged = (0, react_1.useMemo)(() => {
40
+ if (!stylePath)
41
+ return (defaults ?? {});
42
+ return resolveComponentStyle(siteData, stylePath, defaults);
43
+ }, [siteData, stylePath, defaults]);
44
+ const cssVars = (0, react_1.useMemo)(() => (0, core_1.styleToCssVariables)(styleKind, merged), [styleKind, merged]);
45
+ return { style: merged, cssVars };
46
+ }
package/dist/index.d.ts CHANGED
@@ -34,6 +34,12 @@ export * from './EditableFilterSidebar';
34
34
  export * from './SiteDataProvider';
35
35
  export * from './ThemeStyles';
36
36
  export { ResponsiveBaseStyles } from './ResponsiveBaseStyles';
37
+ export { DenebComponentStyles } from './DenebComponentStyles';
38
+ export { FontLoader, DENEB_FONTS_LINK_ID } from './fonts/FontLoader';
39
+ export { useDenebFonts } from './fonts/useDenebFonts';
40
+ export * from './hooks/useComponentStyle';
41
+ export { DENEB_FONT_REGISTRY, DENEB_GOOGLE_FONT_COUNT, buildGoogleFontsStylesheetUrl, collectFontIdsFromSiteData, listFontsByCategory, lookupFontDefinition, normalizeFontId, resolveInstallableFont, formatResponsiveFontSize, } from '@deneb-ui/core';
42
+ export { STYLE_PATCH_MESSAGE, DENEB_STYLE_PATCH_MESSAGE, STYLE_TARGET_ATTRIBUTE, STYLE_TYPE_ATTRIBUTE, patchElementStyle, patchStyleByPath, styleToCssVariables, validateStyleTree, collectStyleTargetsFromHtml, } from '@deneb-ui/core';
37
43
  export * from './utils';
38
44
  export * from './core';
39
45
  export * from './contact';
package/dist/index.js CHANGED
@@ -18,7 +18,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
18
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.DENEB_AUTHOR = exports.DENEB_FRAMEWORK_VERSION = exports.DENEB_FRAMEWORK_NAME = exports.FilterSidebar = exports.CartDrawer = exports.FloatingContactWidget = exports.CookieConsentBanner = exports.ProductQuickView = exports.TrustBadges = exports.StickyMobileBar = exports.CategoryPills = exports.AnnouncementBar = exports.HeroSplit = exports.Hero = exports.Footer = exports.Header = exports.Navbar = exports.ContactForm = exports.FAQ = exports.Accordion = exports.TestimonialCard = exports.PricingCard = exports.ServiceCard = exports.CustomerReviews = exports.ProductDetail = exports.ProductGrid = exports.ProductCard = exports.List = exports.Box = exports.Section = exports.Grid = exports.Image = exports.Quote = exports.Badge = exports.Paragraph = exports.Heading = exports.Text = exports.Dialog = exports.Card = exports.Button = exports.ResponsiveBaseStyles = void 0;
21
+ exports.Hero = exports.Footer = exports.Header = exports.Navbar = exports.ContactForm = exports.FAQ = exports.Accordion = exports.TestimonialCard = exports.PricingCard = exports.ServiceCard = exports.CustomerReviews = exports.ProductDetail = exports.ProductGrid = exports.ProductCard = exports.List = exports.Box = exports.Section = exports.Grid = exports.Image = exports.Quote = exports.Badge = exports.Paragraph = exports.Heading = exports.Text = exports.Dialog = exports.Card = exports.Button = exports.collectStyleTargetsFromHtml = exports.validateStyleTree = exports.styleToCssVariables = exports.patchStyleByPath = exports.patchElementStyle = exports.STYLE_TYPE_ATTRIBUTE = exports.STYLE_TARGET_ATTRIBUTE = exports.DENEB_STYLE_PATCH_MESSAGE = exports.STYLE_PATCH_MESSAGE = exports.formatResponsiveFontSize = exports.resolveInstallableFont = exports.normalizeFontId = exports.lookupFontDefinition = exports.listFontsByCategory = exports.collectFontIdsFromSiteData = exports.buildGoogleFontsStylesheetUrl = exports.DENEB_GOOGLE_FONT_COUNT = exports.DENEB_FONT_REGISTRY = exports.useDenebFonts = exports.DENEB_FONTS_LINK_ID = exports.FontLoader = exports.DenebComponentStyles = exports.ResponsiveBaseStyles = void 0;
22
+ exports.DENEB_AUTHOR = exports.DENEB_FRAMEWORK_VERSION = exports.DENEB_FRAMEWORK_NAME = exports.FilterSidebar = exports.CartDrawer = exports.FloatingContactWidget = exports.CookieConsentBanner = exports.ProductQuickView = exports.TrustBadges = exports.StickyMobileBar = exports.CategoryPills = exports.AnnouncementBar = exports.HeroSplit = void 0;
22
23
  __exportStar(require("./EditableText"), exports);
23
24
  __exportStar(require("./EditableImage"), exports);
24
25
  __exportStar(require("./EditableList"), exports);
@@ -52,6 +53,34 @@ __exportStar(require("./SiteDataProvider"), exports);
52
53
  __exportStar(require("./ThemeStyles"), exports);
53
54
  var ResponsiveBaseStyles_1 = require("./ResponsiveBaseStyles");
54
55
  Object.defineProperty(exports, "ResponsiveBaseStyles", { enumerable: true, get: function () { return ResponsiveBaseStyles_1.ResponsiveBaseStyles; } });
56
+ var DenebComponentStyles_1 = require("./DenebComponentStyles");
57
+ Object.defineProperty(exports, "DenebComponentStyles", { enumerable: true, get: function () { return DenebComponentStyles_1.DenebComponentStyles; } });
58
+ var FontLoader_1 = require("./fonts/FontLoader");
59
+ Object.defineProperty(exports, "FontLoader", { enumerable: true, get: function () { return FontLoader_1.FontLoader; } });
60
+ Object.defineProperty(exports, "DENEB_FONTS_LINK_ID", { enumerable: true, get: function () { return FontLoader_1.DENEB_FONTS_LINK_ID; } });
61
+ var useDenebFonts_1 = require("./fonts/useDenebFonts");
62
+ Object.defineProperty(exports, "useDenebFonts", { enumerable: true, get: function () { return useDenebFonts_1.useDenebFonts; } });
63
+ __exportStar(require("./hooks/useComponentStyle"), exports);
64
+ var core_1 = require("@deneb-ui/core");
65
+ Object.defineProperty(exports, "DENEB_FONT_REGISTRY", { enumerable: true, get: function () { return core_1.DENEB_FONT_REGISTRY; } });
66
+ Object.defineProperty(exports, "DENEB_GOOGLE_FONT_COUNT", { enumerable: true, get: function () { return core_1.DENEB_GOOGLE_FONT_COUNT; } });
67
+ Object.defineProperty(exports, "buildGoogleFontsStylesheetUrl", { enumerable: true, get: function () { return core_1.buildGoogleFontsStylesheetUrl; } });
68
+ Object.defineProperty(exports, "collectFontIdsFromSiteData", { enumerable: true, get: function () { return core_1.collectFontIdsFromSiteData; } });
69
+ Object.defineProperty(exports, "listFontsByCategory", { enumerable: true, get: function () { return core_1.listFontsByCategory; } });
70
+ Object.defineProperty(exports, "lookupFontDefinition", { enumerable: true, get: function () { return core_1.lookupFontDefinition; } });
71
+ Object.defineProperty(exports, "normalizeFontId", { enumerable: true, get: function () { return core_1.normalizeFontId; } });
72
+ Object.defineProperty(exports, "resolveInstallableFont", { enumerable: true, get: function () { return core_1.resolveInstallableFont; } });
73
+ Object.defineProperty(exports, "formatResponsiveFontSize", { enumerable: true, get: function () { return core_1.formatResponsiveFontSize; } });
74
+ var core_2 = require("@deneb-ui/core");
75
+ Object.defineProperty(exports, "STYLE_PATCH_MESSAGE", { enumerable: true, get: function () { return core_2.STYLE_PATCH_MESSAGE; } });
76
+ Object.defineProperty(exports, "DENEB_STYLE_PATCH_MESSAGE", { enumerable: true, get: function () { return core_2.DENEB_STYLE_PATCH_MESSAGE; } });
77
+ Object.defineProperty(exports, "STYLE_TARGET_ATTRIBUTE", { enumerable: true, get: function () { return core_2.STYLE_TARGET_ATTRIBUTE; } });
78
+ Object.defineProperty(exports, "STYLE_TYPE_ATTRIBUTE", { enumerable: true, get: function () { return core_2.STYLE_TYPE_ATTRIBUTE; } });
79
+ Object.defineProperty(exports, "patchElementStyle", { enumerable: true, get: function () { return core_2.patchElementStyle; } });
80
+ Object.defineProperty(exports, "patchStyleByPath", { enumerable: true, get: function () { return core_2.patchStyleByPath; } });
81
+ Object.defineProperty(exports, "styleToCssVariables", { enumerable: true, get: function () { return core_2.styleToCssVariables; } });
82
+ Object.defineProperty(exports, "validateStyleTree", { enumerable: true, get: function () { return core_2.validateStyleTree; } });
83
+ Object.defineProperty(exports, "collectStyleTargetsFromHtml", { enumerable: true, get: function () { return core_2.collectStyleTargetsFromHtml; } });
55
84
  // Smart template components & actions
56
85
  __exportStar(require("./utils"), exports);
57
86
  __exportStar(require("./core"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deneb-ui/ui",
3
- "version": "2.0.23",
3
+ "version": "2.0.24",
4
4
  "description": "Visual-first React component library for editable commerce storefronts. Built for Next.js and Fivora.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -18,10 +18,12 @@
18
18
  },
19
19
  "files": [
20
20
  "dist",
21
+ "scripts",
21
22
  "README.md"
22
23
  ],
23
24
  "scripts": {
24
25
  "build": "tsc",
26
+ "postinstall": "node ./scripts/setup-fonts.cjs",
25
27
  "prepublishOnly": "npm run build"
26
28
  },
27
29
  "keywords": [
@@ -46,7 +48,9 @@
46
48
  "Induranga Kawishwara <https://github.com/Induranga-kawishwara>"
47
49
  ],
48
50
  "license": "MIT",
49
- "dependencies": {},
51
+ "dependencies": {
52
+ "@deneb-ui/core": "^2.0.24"
53
+ },
50
54
  "peerDependencies": {
51
55
  "react": "^18.0.0 || ^19.0.0",
52
56
  "react-dom": "^18.0.0 || ^19.0.0"
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Runs after `npm install @deneb-ui/ui`.
5
+ * Walks up to the host Next/React app and self-hosts project fonts.
6
+ * Skip with DENEB_SKIP_FONTS=1.
7
+ */
8
+ if (process.env.DENEB_SKIP_FONTS === '1') {
9
+ process.exit(0);
10
+ }
11
+
12
+ try {
13
+ const { installFontsForHostOf } = require('@deneb-ui/core/install-fonts');
14
+ const result = installFontsForHostOf(__dirname);
15
+ if (result.skipped) {
16
+ process.exit(0);
17
+ }
18
+ if (result.ok && result.installed.length > 0) {
19
+ console.log(
20
+ `[@deneb-ui/ui] Configured ${result.installed.length} font(s): ${result.installed.join(', ')}`,
21
+ );
22
+ }
23
+ } catch {
24
+ // Never fail the host npm install because fonts could not be configured.
25
+ process.exit(0);
26
+ }