@officexapp/catalogs-cli 0.4.1 → 0.4.2
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.js +80 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1340,7 +1340,7 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
1340
1340
|
}
|
|
1341
1341
|
|
|
1342
1342
|
case 'html':
|
|
1343
|
-
return h('
|
|
1343
|
+
return h(HtmlBlock, { content: props.content || '', className: compClass, style: compStyle, formState });
|
|
1344
1344
|
|
|
1345
1345
|
case 'banner': {
|
|
1346
1346
|
const variants = {
|
|
@@ -1976,6 +1976,38 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
1976
1976
|
);
|
|
1977
1977
|
}
|
|
1978
1978
|
|
|
1979
|
+
// --- HtmlBlock: renders HTML content and executes inline <script> tags ---
|
|
1980
|
+
function HtmlBlock({ content, className, style, formState }) {
|
|
1981
|
+
const ref = React.useRef(null);
|
|
1982
|
+
const executedRef = React.useRef(new Set());
|
|
1983
|
+
// Template interpolation: replace {{field_id}} with form state values
|
|
1984
|
+
const interpolated = React.useMemo(() =>
|
|
1985
|
+
(content || '').replace(/{{(w+)}}/g, (_, id) => formState?.[id] ?? ''),
|
|
1986
|
+
[content, formState]
|
|
1987
|
+
);
|
|
1988
|
+
React.useEffect(() => {
|
|
1989
|
+
const container = ref.current;
|
|
1990
|
+
if (!container) return;
|
|
1991
|
+
const scripts = container.querySelectorAll('script');
|
|
1992
|
+
scripts.forEach((orig) => {
|
|
1993
|
+
const key = orig.src || orig.textContent || '';
|
|
1994
|
+
if (executedRef.current.has(key)) return;
|
|
1995
|
+
executedRef.current.add(key);
|
|
1996
|
+
if (orig.src) {
|
|
1997
|
+
const s = document.createElement('script');
|
|
1998
|
+
s.src = orig.src;
|
|
1999
|
+
if (orig.type) s.type = orig.type;
|
|
2000
|
+
s.async = true;
|
|
2001
|
+
container.appendChild(s);
|
|
2002
|
+
} else if (orig.textContent) {
|
|
2003
|
+
try { new Function(orig.textContent)(); }
|
|
2004
|
+
catch (e) { console.error('[CatalogKit:dev] Inline script error:', e); }
|
|
2005
|
+
}
|
|
2006
|
+
});
|
|
2007
|
+
}, [interpolated]);
|
|
2008
|
+
return h('div', { ref, className: 'prose prose-sm max-w-none ' + (className || ''), style, dangerouslySetInnerHTML: { __html: interpolated } });
|
|
2009
|
+
}
|
|
2010
|
+
|
|
1979
2011
|
function ActionButton({ action, themeColor, onAction }) {
|
|
1980
2012
|
const st = action.style || 'primary';
|
|
1981
2013
|
const hasSide = !!action.side_statement;
|
|
@@ -2021,7 +2053,7 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
2021
2053
|
);
|
|
2022
2054
|
}
|
|
2023
2055
|
|
|
2024
|
-
function StickyBottomBar({ config, page, formState, cartItems, themeColor, onNext, onAction, onBack, historyLen }) {
|
|
2056
|
+
function StickyBottomBar({ config, page, formState, cartItems, themeColor, onNext, onAction, onFieldAndNavigate, onBack, historyLen }) {
|
|
2025
2057
|
const [visible, setVisible] = React.useState(!config.delay_ms);
|
|
2026
2058
|
const [scrollDir, setScrollDir] = React.useState('down');
|
|
2027
2059
|
React.useEffect(() => {
|
|
@@ -2044,15 +2076,27 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
2044
2076
|
glass_dark: { backgroundColor: 'rgba(0,0,0,0.85)', backdropFilter: 'blur(16px)', color: 'white' },
|
|
2045
2077
|
gradient: { background: 'linear-gradient(135deg, ' + themeColor + ' 0%, ' + themeColor + 'dd 100%)', color: 'white' },
|
|
2046
2078
|
};
|
|
2047
|
-
const
|
|
2048
|
-
const
|
|
2049
|
-
if (
|
|
2050
|
-
if (
|
|
2051
|
-
const actionId =
|
|
2079
|
+
const dispatchAction = (act) => {
|
|
2080
|
+
const cmd = act?.action || 'next';
|
|
2081
|
+
if (cmd === 'next') { onNext(); return; }
|
|
2082
|
+
if (cmd.startsWith('action:')) {
|
|
2083
|
+
const actionId = cmd.slice(7);
|
|
2052
2084
|
const action = page.actions?.find(a => a.id === actionId);
|
|
2053
2085
|
if (action) onAction(action); else onNext();
|
|
2054
|
-
|
|
2086
|
+
return;
|
|
2087
|
+
}
|
|
2088
|
+
if (cmd.startsWith('field:')) {
|
|
2089
|
+
const parts = cmd.slice(6).split(':');
|
|
2090
|
+
if (parts.length >= 2) { onFieldAndNavigate(parts[0], parts.slice(1).join(':')); }
|
|
2091
|
+
return;
|
|
2092
|
+
}
|
|
2093
|
+
onNext();
|
|
2055
2094
|
};
|
|
2095
|
+
const primaryLabel = config.primary?.label
|
|
2096
|
+
? interpolate(config.primary.label)
|
|
2097
|
+
: config.button_text || page.submit_label || 'Continue';
|
|
2098
|
+
const secondaryAction = config.secondary;
|
|
2099
|
+
const secondaryLabel = secondaryAction?.label ? interpolate(secondaryAction.label) : null;
|
|
2056
2100
|
return h('div', {
|
|
2057
2101
|
className: 'cf-sticky-bar' + (show ? '' : ' hidden'),
|
|
2058
2102
|
style: bgStyles[config.style || 'solid'] || bgStyles.solid,
|
|
@@ -2066,12 +2110,19 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
2066
2110
|
h('div', { className: 'flex items-center gap-3' },
|
|
2067
2111
|
config.cart_badge && cartItems.length > 0
|
|
2068
2112
|
? h('span', { className: 'bg-red-500 text-white text-xs font-bold rounded-full w-5 h-5 flex items-center justify-center' }, cartItems.length) : null,
|
|
2113
|
+
secondaryLabel
|
|
2114
|
+
? h('button', {
|
|
2115
|
+
className: 'text-sm font-medium hover:opacity-80 transition-opacity',
|
|
2116
|
+
style: { color: config.style === 'glass_dark' ? 'rgba(255,255,255,0.6)' : '#6b7280' },
|
|
2117
|
+
onClick: () => dispatchAction(secondaryAction),
|
|
2118
|
+
}, secondaryLabel)
|
|
2119
|
+
: null,
|
|
2069
2120
|
h('button', {
|
|
2070
2121
|
className: 'cf-btn-primary text-white text-sm',
|
|
2071
2122
|
style: { backgroundColor: config.style === 'gradient' ? 'rgba(255,255,255,0.9)' : themeColor, color: config.style === 'gradient' ? themeColor : 'white' },
|
|
2072
2123
|
disabled: config.disabled,
|
|
2073
|
-
onClick:
|
|
2074
|
-
},
|
|
2124
|
+
onClick: () => dispatchAction(config.primary),
|
|
2125
|
+
}, primaryLabel)
|
|
2075
2126
|
)
|
|
2076
2127
|
)
|
|
2077
2128
|
);
|
|
@@ -2746,6 +2797,24 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
2746
2797
|
navigateTo(nextPageId);
|
|
2747
2798
|
}, [currentPageId, routing, formState, pages, addToCart, navigateTo, runValidation]);
|
|
2748
2799
|
|
|
2800
|
+
// --- Field + Navigate (for sticky bar field: dispatch) ---
|
|
2801
|
+
const handleFieldAndNavigate = React.useCallback((fieldId, value) => {
|
|
2802
|
+
const newFormState = { ...formState, [fieldId]: value };
|
|
2803
|
+
setFormState(newFormState);
|
|
2804
|
+
const page = pages[currentPageId];
|
|
2805
|
+
if (page) {
|
|
2806
|
+
const errors = validatePage(page, newFormState, devContext);
|
|
2807
|
+
setValidationErrors(errors);
|
|
2808
|
+
if (errors.length > 0) {
|
|
2809
|
+
const el = document.querySelector('[data-component-id="' + errors[0].componentId + '"]');
|
|
2810
|
+
if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
2811
|
+
return;
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
const nextPageId = getNextPage(routing, currentPageId, newFormState, devContext);
|
|
2815
|
+
navigateTo(nextPageId);
|
|
2816
|
+
}, [currentPageId, routing, formState, pages, navigateTo]);
|
|
2817
|
+
|
|
2749
2818
|
// --- Resume prompt ---
|
|
2750
2819
|
if (showResumeModal) {
|
|
2751
2820
|
return h('div', { className: 'cf-resume-backdrop' },
|
|
@@ -3037,7 +3106,7 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
3037
3106
|
? h(StickyBottomBar, {
|
|
3038
3107
|
config: { ...(catalog.settings?.sticky_bar || {}), ...(page.sticky_bar || {}) },
|
|
3039
3108
|
page, formState, cartItems, themeColor,
|
|
3040
|
-
onNext: handleNext, onAction: handleAction, onBack: handleBack,
|
|
3109
|
+
onNext: handleNext, onAction: handleAction, onFieldAndNavigate: handleFieldAndNavigate, onBack: handleBack,
|
|
3041
3110
|
historyLen: history.length,
|
|
3042
3111
|
})
|
|
3043
3112
|
: null
|