@deneb-ui/core 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.
- package/README.md +5 -0
- package/dist/engine/cssVariables.d.ts +8 -0
- package/dist/engine/cssVariables.js +186 -0
- package/dist/engine/deepMerge.d.ts +2 -0
- package/dist/engine/deepMerge.js +19 -0
- package/dist/engine/domPatcher.d.ts +6 -0
- package/dist/engine/domPatcher.js +54 -0
- package/dist/engine/tokenResolver.d.ts +3 -0
- package/dist/engine/tokenResolver.js +35 -0
- package/dist/fonts/clamp.d.ts +8 -0
- package/dist/fonts/clamp.js +47 -0
- package/dist/fonts/google-url.d.ts +1 -0
- package/dist/fonts/google-url.js +41 -0
- package/dist/fonts/index.d.ts +5 -0
- package/dist/fonts/index.js +21 -0
- package/dist/fonts/installProject.d.ts +25 -0
- package/dist/fonts/installProject.js +273 -0
- package/dist/fonts/registry.d.ts +7 -0
- package/dist/fonts/registry.js +138 -0
- package/dist/fonts/resolve.d.ts +7 -0
- package/dist/fonts/resolve.js +117 -0
- package/dist/fonts/types.d.ts +36 -0
- package/dist/fonts/types.js +2 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +25 -0
- package/dist/types/markers.d.ts +7 -0
- package/dist/types/markers.js +31 -0
- package/dist/types/protocol.d.ts +10 -0
- package/dist/types/protocol.js +19 -0
- package/dist/types/styles.d.ts +90 -0
- package/dist/types/styles.js +2 -0
- package/dist/validation/styleSchemaValidator.d.ts +8 -0
- package/dist/validation/styleSchemaValidator.js +44 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# @deneb-ui/core
|
|
2
|
+
|
|
3
|
+
Headless style engine for the Deneb / Fivora real-time visual editing ecosystem.
|
|
4
|
+
|
|
5
|
+
Provides style schemas, CSS variable generators, instant DOM patching (`FIVORA_PREVIEW_STYLE_PATCH`), and validation utilities. Framework-agnostic — consumed by `@deneb-ui/ui` and the template preview focus bridge.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ButtonStyleProperties, CardStyleProperties, GridStyleProperties, SectionStyleProperties, TextStyleProperties } from '../types/styles';
|
|
2
|
+
export declare function formatUnit(value: string | number | undefined): string | undefined;
|
|
3
|
+
export declare function textStyleToCssVariables(style: TextStyleProperties): Record<string, string>;
|
|
4
|
+
export declare function cardStyleToCssVariables(style: CardStyleProperties): Record<string, string>;
|
|
5
|
+
export declare function buttonStyleToCssVariables(style: ButtonStyleProperties): Record<string, string>;
|
|
6
|
+
export declare function gridStyleToCssVariables(style: GridStyleProperties): Record<string, string>;
|
|
7
|
+
export declare function sectionStyleToCssVariables(style: SectionStyleProperties): Record<string, string>;
|
|
8
|
+
export declare function styleToCssVariables(styleKind: 'text' | 'card' | 'button' | 'grid' | 'section', style: Record<string, unknown>): Record<string, string>;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatUnit = formatUnit;
|
|
4
|
+
exports.textStyleToCssVariables = textStyleToCssVariables;
|
|
5
|
+
exports.cardStyleToCssVariables = cardStyleToCssVariables;
|
|
6
|
+
exports.buttonStyleToCssVariables = buttonStyleToCssVariables;
|
|
7
|
+
exports.gridStyleToCssVariables = gridStyleToCssVariables;
|
|
8
|
+
exports.sectionStyleToCssVariables = sectionStyleToCssVariables;
|
|
9
|
+
exports.styleToCssVariables = styleToCssVariables;
|
|
10
|
+
const clamp_1 = require("../fonts/clamp");
|
|
11
|
+
const resolve_1 = require("../fonts/resolve");
|
|
12
|
+
const tokenResolver_1 = require("./tokenResolver");
|
|
13
|
+
function formatUnit(value) {
|
|
14
|
+
if (value === undefined || value === '' || value === null)
|
|
15
|
+
return undefined;
|
|
16
|
+
if (typeof value === 'number')
|
|
17
|
+
return `${value}px`;
|
|
18
|
+
return /^\d+$/.test(value) ? `${value}px` : value;
|
|
19
|
+
}
|
|
20
|
+
function marginVars(style, prefix) {
|
|
21
|
+
const vars = {};
|
|
22
|
+
const top = style.marginTop ?? style.spacingTop;
|
|
23
|
+
const bottom = style.marginBottom ?? style.spacingBottom;
|
|
24
|
+
const left = style.marginLeft ?? style.spacingLeft;
|
|
25
|
+
const right = style.marginRight ?? style.spacingRight;
|
|
26
|
+
if (top !== undefined)
|
|
27
|
+
vars[`${prefix}-margin-top`] = formatUnit(top);
|
|
28
|
+
if (bottom !== undefined)
|
|
29
|
+
vars[`${prefix}-margin-bottom`] = formatUnit(bottom);
|
|
30
|
+
if (left !== undefined)
|
|
31
|
+
vars[`${prefix}-margin-left`] = formatUnit(left);
|
|
32
|
+
if (right !== undefined)
|
|
33
|
+
vars[`${prefix}-margin-right`] = formatUnit(right);
|
|
34
|
+
return vars;
|
|
35
|
+
}
|
|
36
|
+
function textStyleToCssVariables(style) {
|
|
37
|
+
const vars = {
|
|
38
|
+
...marginVars(style, '--deneb'),
|
|
39
|
+
};
|
|
40
|
+
if (style.fontFamily) {
|
|
41
|
+
vars['--deneb-font-family'] = (0, resolve_1.resolveFontFamily)(style.fontFamily);
|
|
42
|
+
}
|
|
43
|
+
if (style.fontSize !== undefined) {
|
|
44
|
+
vars['--deneb-font-size'] = (0, clamp_1.formatFontSize)(style.fontSize, {
|
|
45
|
+
responsive: style.responsiveFontSize === true,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (style.fontWeight !== undefined) {
|
|
49
|
+
vars['--deneb-font-weight'] = String(style.fontWeight);
|
|
50
|
+
}
|
|
51
|
+
if (style.lineHeight !== undefined) {
|
|
52
|
+
vars['--deneb-line-height'] =
|
|
53
|
+
typeof style.lineHeight === 'number'
|
|
54
|
+
? String(style.lineHeight)
|
|
55
|
+
: String(style.lineHeight);
|
|
56
|
+
}
|
|
57
|
+
if (style.letterSpacing) {
|
|
58
|
+
vars['--deneb-letter-spacing'] = style.letterSpacing;
|
|
59
|
+
}
|
|
60
|
+
if (style.color) {
|
|
61
|
+
vars['--deneb-color'] = (0, tokenResolver_1.resolveThemeToken)(style.color);
|
|
62
|
+
}
|
|
63
|
+
if (style.textAlign) {
|
|
64
|
+
vars['--deneb-text-align'] = style.textAlign;
|
|
65
|
+
}
|
|
66
|
+
if (style.textTransform) {
|
|
67
|
+
vars['--deneb-text-transform'] = style.textTransform;
|
|
68
|
+
}
|
|
69
|
+
return vars;
|
|
70
|
+
}
|
|
71
|
+
function cardStyleToCssVariables(style) {
|
|
72
|
+
const vars = {
|
|
73
|
+
...marginVars(style, '--deneb-card'),
|
|
74
|
+
};
|
|
75
|
+
if (style.width !== undefined)
|
|
76
|
+
vars['--deneb-card-width'] = formatUnit(style.width);
|
|
77
|
+
if (style.minWidth !== undefined)
|
|
78
|
+
vars['--deneb-card-min-width'] = formatUnit(style.minWidth);
|
|
79
|
+
if (style.maxWidth !== undefined)
|
|
80
|
+
vars['--deneb-card-max-width'] = formatUnit(style.maxWidth);
|
|
81
|
+
if (style.height !== undefined)
|
|
82
|
+
vars['--deneb-card-height'] = formatUnit(style.height);
|
|
83
|
+
if (style.aspectRatio)
|
|
84
|
+
vars['--deneb-card-aspect-ratio'] = style.aspectRatio;
|
|
85
|
+
if (style.paddingTop !== undefined)
|
|
86
|
+
vars['--deneb-card-pt'] = formatUnit(style.paddingTop);
|
|
87
|
+
if (style.paddingBottom !== undefined)
|
|
88
|
+
vars['--deneb-card-pb'] = formatUnit(style.paddingBottom);
|
|
89
|
+
if (style.paddingLeft !== undefined)
|
|
90
|
+
vars['--deneb-card-pl'] = formatUnit(style.paddingLeft);
|
|
91
|
+
if (style.paddingRight !== undefined)
|
|
92
|
+
vars['--deneb-card-pr'] = formatUnit(style.paddingRight);
|
|
93
|
+
if (style.borderRadius !== undefined)
|
|
94
|
+
vars['--deneb-card-radius'] = formatUnit(style.borderRadius);
|
|
95
|
+
if (style.borderWidth !== undefined)
|
|
96
|
+
vars['--deneb-card-border-w'] = formatUnit(style.borderWidth);
|
|
97
|
+
if (style.borderStyle)
|
|
98
|
+
vars['--deneb-card-border-s'] = style.borderStyle;
|
|
99
|
+
if (style.borderColor)
|
|
100
|
+
vars['--deneb-card-border-c'] = style.borderColor;
|
|
101
|
+
if (style.backgroundColor)
|
|
102
|
+
vars['--deneb-card-bg'] = (0, tokenResolver_1.resolveThemeToken)(style.backgroundColor);
|
|
103
|
+
if (style.backgroundGradient)
|
|
104
|
+
vars['--deneb-card-bg-gradient'] = style.backgroundGradient;
|
|
105
|
+
if (style.boxShadow)
|
|
106
|
+
vars['--deneb-card-shadow'] = (0, tokenResolver_1.resolveShadowPreset)(style.boxShadow);
|
|
107
|
+
if (style.backdropBlur !== undefined)
|
|
108
|
+
vars['--deneb-card-blur'] = formatUnit(style.backdropBlur);
|
|
109
|
+
if (style.gap !== undefined)
|
|
110
|
+
vars['--deneb-card-gap'] = formatUnit(style.gap);
|
|
111
|
+
return vars;
|
|
112
|
+
}
|
|
113
|
+
function buttonStyleToCssVariables(style) {
|
|
114
|
+
const vars = {
|
|
115
|
+
...marginVars(style, '--deneb-btn'),
|
|
116
|
+
};
|
|
117
|
+
if (style.borderRadius !== undefined)
|
|
118
|
+
vars['--deneb-btn-radius'] = formatUnit(style.borderRadius);
|
|
119
|
+
if (style.paddingX !== undefined)
|
|
120
|
+
vars['--deneb-btn-px'] = formatUnit(style.paddingX);
|
|
121
|
+
if (style.paddingY !== undefined)
|
|
122
|
+
vars['--deneb-btn-py'] = formatUnit(style.paddingY);
|
|
123
|
+
if (style.backgroundColor)
|
|
124
|
+
vars['--deneb-btn-bg'] = (0, tokenResolver_1.resolveThemeToken)(style.backgroundColor);
|
|
125
|
+
if (style.textColor)
|
|
126
|
+
vars['--deneb-btn-color'] = (0, tokenResolver_1.resolveThemeToken)(style.textColor);
|
|
127
|
+
if (style.borderColor)
|
|
128
|
+
vars['--deneb-btn-border-c'] = style.borderColor;
|
|
129
|
+
if (style.hoverBackgroundColor)
|
|
130
|
+
vars['--deneb-btn-hover-bg'] = style.hoverBackgroundColor;
|
|
131
|
+
if (style.hoverTextColor)
|
|
132
|
+
vars['--deneb-btn-hover-color'] = style.hoverTextColor;
|
|
133
|
+
return vars;
|
|
134
|
+
}
|
|
135
|
+
function gridStyleToCssVariables(style) {
|
|
136
|
+
const vars = {};
|
|
137
|
+
if (style.columns !== undefined)
|
|
138
|
+
vars['--deneb-grid-cols'] = String(style.columns);
|
|
139
|
+
if (style.minCardWidth)
|
|
140
|
+
vars['--deneb-grid-min-card'] = style.minCardWidth;
|
|
141
|
+
if (style.gapX !== undefined)
|
|
142
|
+
vars['--deneb-grid-gap-x'] = formatUnit(style.gapX);
|
|
143
|
+
if (style.gapY !== undefined)
|
|
144
|
+
vars['--deneb-grid-gap-y'] = formatUnit(style.gapY);
|
|
145
|
+
if (style.equalHeight !== undefined) {
|
|
146
|
+
vars['--deneb-grid-equal-height'] = style.equalHeight ? 'stretch' : 'start';
|
|
147
|
+
}
|
|
148
|
+
return vars;
|
|
149
|
+
}
|
|
150
|
+
function sectionStyleToCssVariables(style) {
|
|
151
|
+
const vars = {};
|
|
152
|
+
if (style.paddingTop !== undefined)
|
|
153
|
+
vars['--deneb-section-pt'] = formatUnit(style.paddingTop);
|
|
154
|
+
if (style.paddingBottom !== undefined)
|
|
155
|
+
vars['--deneb-section-pb'] = formatUnit(style.paddingBottom);
|
|
156
|
+
if (style.paddingX !== undefined)
|
|
157
|
+
vars['--deneb-section-px'] = formatUnit(style.paddingX);
|
|
158
|
+
if (style.maxWidth)
|
|
159
|
+
vars['--deneb-section-max-w'] = style.maxWidth;
|
|
160
|
+
if (style.backgroundColor)
|
|
161
|
+
vars['--deneb-section-bg'] = (0, tokenResolver_1.resolveThemeToken)(style.backgroundColor);
|
|
162
|
+
if (style.backgroundImage)
|
|
163
|
+
vars['--deneb-section-bg-image'] = style.backgroundImage;
|
|
164
|
+
if (style.backgroundOverlayColor)
|
|
165
|
+
vars['--deneb-section-overlay'] = style.backgroundOverlayColor;
|
|
166
|
+
if (style.backgroundOverlayOpacity !== undefined) {
|
|
167
|
+
vars['--deneb-section-overlay-opacity'] = String(style.backgroundOverlayOpacity);
|
|
168
|
+
}
|
|
169
|
+
return vars;
|
|
170
|
+
}
|
|
171
|
+
function styleToCssVariables(styleKind, style) {
|
|
172
|
+
switch (styleKind) {
|
|
173
|
+
case 'text':
|
|
174
|
+
return textStyleToCssVariables(style);
|
|
175
|
+
case 'card':
|
|
176
|
+
return cardStyleToCssVariables(style);
|
|
177
|
+
case 'button':
|
|
178
|
+
return buttonStyleToCssVariables(style);
|
|
179
|
+
case 'grid':
|
|
180
|
+
return gridStyleToCssVariables(style);
|
|
181
|
+
case 'section':
|
|
182
|
+
return sectionStyleToCssVariables(style);
|
|
183
|
+
default:
|
|
184
|
+
return {};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isPlainObject = isPlainObject;
|
|
4
|
+
exports.deepMerge = deepMerge;
|
|
5
|
+
function isPlainObject(value) {
|
|
6
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function deepMerge(base, patch) {
|
|
9
|
+
const next = { ...base };
|
|
10
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
11
|
+
if (isPlainObject(value) && isPlainObject(next[key])) {
|
|
12
|
+
next[key] = deepMerge(next[key], value);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
next[key] = value;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return next;
|
|
19
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { StyleKind } from '../types/styles';
|
|
2
|
+
export declare function getLiveStyleCache(): Map<string, Record<string, unknown>>;
|
|
3
|
+
export declare function applyCssVariablesToElement(element: HTMLElement, cssVars: Record<string, string>): void;
|
|
4
|
+
export declare function findStyleTargetElement(targetPath: string, styleType?: StyleKind): HTMLElement | null;
|
|
5
|
+
export declare function patchElementStyle(element: HTMLElement, styleKind: StyleKind, updates: Record<string, unknown>): void;
|
|
6
|
+
export declare function patchStyleByPath(targetPath: string, styleKind: StyleKind, updates: Record<string, unknown>): boolean;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getLiveStyleCache = getLiveStyleCache;
|
|
4
|
+
exports.applyCssVariablesToElement = applyCssVariablesToElement;
|
|
5
|
+
exports.findStyleTargetElement = findStyleTargetElement;
|
|
6
|
+
exports.patchElementStyle = patchElementStyle;
|
|
7
|
+
exports.patchStyleByPath = patchStyleByPath;
|
|
8
|
+
const markers_1 = require("../types/markers");
|
|
9
|
+
const deepMerge_1 = require("./deepMerge");
|
|
10
|
+
const cssVariables_1 = require("./cssVariables");
|
|
11
|
+
const liveStyleCache = new Map();
|
|
12
|
+
function getLiveStyleCache() {
|
|
13
|
+
return liveStyleCache;
|
|
14
|
+
}
|
|
15
|
+
function applyCssVariablesToElement(element, cssVars) {
|
|
16
|
+
for (const [varName, varVal] of Object.entries(cssVars)) {
|
|
17
|
+
if (varVal) {
|
|
18
|
+
element.style.setProperty(varName, varVal);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
element.style.removeProperty(varName);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function findStyleTargetElement(targetPath, styleType) {
|
|
26
|
+
if (typeof document === 'undefined' || !targetPath)
|
|
27
|
+
return null;
|
|
28
|
+
for (const selector of (0, markers_1.buildStyleFallbackSelectors)(targetPath, styleType)) {
|
|
29
|
+
const match = document.querySelector(selector);
|
|
30
|
+
if (match)
|
|
31
|
+
return match;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function patchElementStyle(element, styleKind, updates) {
|
|
36
|
+
const targetPath = element.getAttribute(markers_1.STYLE_TARGET_ATTRIBUTE) ?? '';
|
|
37
|
+
const cacheKey = targetPath || element.getAttribute('data-preview-field-path') || '';
|
|
38
|
+
const previous = cacheKey ? liveStyleCache.get(cacheKey) ?? {} : {};
|
|
39
|
+
const merged = (0, deepMerge_1.deepMerge)(previous, updates);
|
|
40
|
+
if (cacheKey)
|
|
41
|
+
liveStyleCache.set(cacheKey, merged);
|
|
42
|
+
const cssVars = (0, cssVariables_1.styleToCssVariables)(styleKind, merged);
|
|
43
|
+
applyCssVariablesToElement(element, cssVars);
|
|
44
|
+
if (!element.getAttribute(markers_1.STYLE_TYPE_ATTRIBUTE)) {
|
|
45
|
+
element.setAttribute(markers_1.STYLE_TYPE_ATTRIBUTE, styleKind);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function patchStyleByPath(targetPath, styleKind, updates) {
|
|
49
|
+
const element = findStyleTargetElement(targetPath, styleKind);
|
|
50
|
+
if (!element)
|
|
51
|
+
return false;
|
|
52
|
+
patchElementStyle(element, styleKind, updates);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveFontFamily = void 0;
|
|
4
|
+
exports.resolveShadowPreset = resolveShadowPreset;
|
|
5
|
+
exports.resolveThemeToken = resolveThemeToken;
|
|
6
|
+
var resolve_1 = require("../fonts/resolve");
|
|
7
|
+
Object.defineProperty(exports, "resolveFontFamily", { enumerable: true, get: function () { return resolve_1.resolveFontFamily; } });
|
|
8
|
+
const SHADOW_PRESETS = {
|
|
9
|
+
none: 'none',
|
|
10
|
+
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
|
|
11
|
+
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)',
|
|
12
|
+
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)',
|
|
13
|
+
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)',
|
|
14
|
+
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
|
|
15
|
+
};
|
|
16
|
+
function resolveShadowPreset(value) {
|
|
17
|
+
if (!value)
|
|
18
|
+
return undefined;
|
|
19
|
+
return SHADOW_PRESETS[value] ?? value;
|
|
20
|
+
}
|
|
21
|
+
function resolveThemeToken(value) {
|
|
22
|
+
if (!value)
|
|
23
|
+
return undefined;
|
|
24
|
+
if (value.startsWith('var('))
|
|
25
|
+
return value;
|
|
26
|
+
const themeMap = {
|
|
27
|
+
primary: 'var(--brand-color, #2563eb)',
|
|
28
|
+
secondary: 'var(--brand-secondary, #0f172a)',
|
|
29
|
+
surface: 'var(--surface-color, #ffffff)',
|
|
30
|
+
background: 'var(--page-bg, #f8fafc)',
|
|
31
|
+
heading: 'var(--heading-color, #0f172a)',
|
|
32
|
+
muted: 'var(--muted-color, #64748b)',
|
|
33
|
+
};
|
|
34
|
+
return themeMap[value] ?? value;
|
|
35
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a px/rem font size into a responsive clamp() for storefront viewports.
|
|
3
|
+
* Example: 48px → clamp(2.25rem, 1.5rem + 2.5vw, 3rem)
|
|
4
|
+
*/
|
|
5
|
+
export declare function formatResponsiveFontSize(value: string | number): string | undefined;
|
|
6
|
+
export declare function formatFontSize(value: string | number | undefined, options?: {
|
|
7
|
+
responsive?: boolean;
|
|
8
|
+
}): string | undefined;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatResponsiveFontSize = formatResponsiveFontSize;
|
|
4
|
+
exports.formatFontSize = formatFontSize;
|
|
5
|
+
/**
|
|
6
|
+
* Converts a px/rem font size into a responsive clamp() for storefront viewports.
|
|
7
|
+
* Example: 48px → clamp(2.25rem, 1.5rem + 2.5vw, 3rem)
|
|
8
|
+
*/
|
|
9
|
+
function formatResponsiveFontSize(value) {
|
|
10
|
+
if (value === undefined || value === null || value === '')
|
|
11
|
+
return undefined;
|
|
12
|
+
let px;
|
|
13
|
+
if (typeof value === 'number') {
|
|
14
|
+
px = value;
|
|
15
|
+
}
|
|
16
|
+
else if (/^\d+(\.\d+)?px$/i.test(value.trim())) {
|
|
17
|
+
px = parseFloat(value);
|
|
18
|
+
}
|
|
19
|
+
else if (/^\d+(\.\d+)?rem$/i.test(value.trim())) {
|
|
20
|
+
px = parseFloat(value) * 16;
|
|
21
|
+
}
|
|
22
|
+
else if (/^\d+$/.test(value.trim())) {
|
|
23
|
+
px = parseFloat(value);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
if (!Number.isFinite(px) || px <= 0)
|
|
29
|
+
return undefined;
|
|
30
|
+
const preferredRem = px / 16;
|
|
31
|
+
const minRem = Math.max(preferredRem * 0.72, 0.75);
|
|
32
|
+
const maxRem = preferredRem * 1.15;
|
|
33
|
+
const vwFactor = Math.min(Math.max(preferredRem * 0.08, 0.5), 3.5);
|
|
34
|
+
return `clamp(${minRem.toFixed(3)}rem, ${(preferredRem * 0.55).toFixed(3)}rem + ${vwFactor.toFixed(2)}vw, ${maxRem.toFixed(3)}rem)`;
|
|
35
|
+
}
|
|
36
|
+
function formatFontSize(value, options) {
|
|
37
|
+
if (value === undefined || value === null || value === '')
|
|
38
|
+
return undefined;
|
|
39
|
+
if (options?.responsive) {
|
|
40
|
+
const clamped = formatResponsiveFontSize(value);
|
|
41
|
+
if (clamped)
|
|
42
|
+
return clamped;
|
|
43
|
+
}
|
|
44
|
+
if (typeof value === 'number')
|
|
45
|
+
return `${value}px`;
|
|
46
|
+
return /^\d+$/.test(value) ? `${value}px` : value;
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function buildGoogleFontsStylesheetUrl(fontIds: string[]): string | null;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildGoogleFontsStylesheetUrl = buildGoogleFontsStylesheetUrl;
|
|
4
|
+
const registry_1 = require("./registry");
|
|
5
|
+
const resolve_1 = require("./resolve");
|
|
6
|
+
function buildFamilyParam(font) {
|
|
7
|
+
if (!font.googleQuery)
|
|
8
|
+
return null;
|
|
9
|
+
const weights = font.weights.length > 0 ? font.weights : [400];
|
|
10
|
+
const unique = Array.from(new Set(weights)).sort((a, b) => a - b);
|
|
11
|
+
if (font.italic) {
|
|
12
|
+
const pairs = unique.flatMap((w) => [`0,${w}`, `1,${w}`]);
|
|
13
|
+
return `family=${font.googleQuery}:ital,wght@${pairs.join(';')}`;
|
|
14
|
+
}
|
|
15
|
+
if (font.variable || unique.length > 4) {
|
|
16
|
+
const min = unique[0];
|
|
17
|
+
const max = unique[unique.length - 1];
|
|
18
|
+
return `family=${font.googleQuery}:wght@${min}..${max}`;
|
|
19
|
+
}
|
|
20
|
+
return `family=${font.googleQuery}:wght@${unique.join(';')}`;
|
|
21
|
+
}
|
|
22
|
+
function buildGoogleFontsStylesheetUrl(fontIds) {
|
|
23
|
+
const params = [];
|
|
24
|
+
const seen = new Set();
|
|
25
|
+
for (const rawId of fontIds) {
|
|
26
|
+
const font = registry_1.DENEB_FONT_BY_ID.get(rawId) ?? (0, resolve_1.lookupFontDefinition)(rawId);
|
|
27
|
+
if (!font || !font.googleFonts || !font.googleQuery)
|
|
28
|
+
continue;
|
|
29
|
+
const installId = font.substituteId && !font.fontsourcePackage ? font.substituteId : font.id;
|
|
30
|
+
const installFont = registry_1.DENEB_FONT_BY_ID.get(installId) ?? font;
|
|
31
|
+
if (seen.has(installFont.id))
|
|
32
|
+
continue;
|
|
33
|
+
seen.add(installFont.id);
|
|
34
|
+
const param = buildFamilyParam(installFont);
|
|
35
|
+
if (param)
|
|
36
|
+
params.push(param);
|
|
37
|
+
}
|
|
38
|
+
if (params.length === 0)
|
|
39
|
+
return null;
|
|
40
|
+
return `https://fonts.googleapis.com/css2?${params.join('&')}&display=swap`;
|
|
41
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./types"), exports);
|
|
18
|
+
__exportStar(require("./registry"), exports);
|
|
19
|
+
__exportStar(require("./resolve"), exports);
|
|
20
|
+
__exportStar(require("./clamp"), exports);
|
|
21
|
+
__exportStar(require("./google-url"), exports);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DenebFontDefinition } from './types';
|
|
2
|
+
export declare const FONTS_MANIFEST_REL = ".deneb/fonts.json";
|
|
3
|
+
export declare const FONTS_CSS_REL = "src/fonts/deneb-fonts.css";
|
|
4
|
+
export declare const FONTS_CSS_IMPORT = "./fonts/deneb-fonts.css";
|
|
5
|
+
export interface InstallProjectFontsOptions {
|
|
6
|
+
projectDir: string;
|
|
7
|
+
fontIds?: string[];
|
|
8
|
+
all?: boolean;
|
|
9
|
+
quiet?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface InstallProjectFontsResult {
|
|
12
|
+
ok: boolean;
|
|
13
|
+
skipped?: string;
|
|
14
|
+
installed: string[];
|
|
15
|
+
packages: string[];
|
|
16
|
+
cssPath?: string;
|
|
17
|
+
manifestPath?: string;
|
|
18
|
+
layoutPatched?: boolean;
|
|
19
|
+
warnings: string[];
|
|
20
|
+
}
|
|
21
|
+
export declare function findSiteDataPath(projectDir: string): string | null;
|
|
22
|
+
export declare function findHostProject(startDir: string): string | null;
|
|
23
|
+
export declare function generateFontsCss(fonts: DenebFontDefinition[]): string;
|
|
24
|
+
export declare function installProjectFonts(options: InstallProjectFontsOptions): InstallProjectFontsResult;
|
|
25
|
+
export declare function installFontsForHostOf(packageDir: string): InstallProjectFontsResult;
|