@officexapp/catalogs-cli 0.4.0 → 0.4.1
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 +44 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1275,8 +1275,8 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
1275
1275
|
}
|
|
1276
1276
|
|
|
1277
1277
|
// --- Component Renderers ---
|
|
1278
|
-
function RenderComponent({ comp, isCover, formState, onFieldChange }) {
|
|
1279
|
-
const props = comp.props || {};
|
|
1278
|
+
function RenderComponent({ comp, isCover, formState, onFieldChange, onSubmit, propOverrides }) {
|
|
1279
|
+
const props = { ...(comp.props || {}), ...(propOverrides?.[comp.id] || {}) };
|
|
1280
1280
|
const type = comp.type;
|
|
1281
1281
|
const compClass = comp.className || '';
|
|
1282
1282
|
const compStyle = comp.style || {};
|
|
@@ -1452,7 +1452,7 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
1452
1452
|
case 'url':
|
|
1453
1453
|
case 'number':
|
|
1454
1454
|
case 'password':
|
|
1455
|
-
return h(TextInput, { comp, type, formState, onFieldChange, isCover, compClass, compStyle });
|
|
1455
|
+
return h(TextInput, { comp, type, formState, onFieldChange, isCover, compClass, compStyle, onSubmit });
|
|
1456
1456
|
|
|
1457
1457
|
case 'long_text':
|
|
1458
1458
|
return h('div', { className: 'space-y-1.5 ' + compClass, style: compStyle },
|
|
@@ -1723,7 +1723,7 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
1723
1723
|
);
|
|
1724
1724
|
}
|
|
1725
1725
|
|
|
1726
|
-
function TextInput({ comp, type, formState, onFieldChange, isCover, compClass, compStyle }) {
|
|
1726
|
+
function TextInput({ comp, type, formState, onFieldChange, isCover, compClass, compStyle, onSubmit }) {
|
|
1727
1727
|
const props = comp.props || {};
|
|
1728
1728
|
const inputType = type === 'email' ? 'email' : type === 'phone' ? 'tel' : type === 'url' ? 'url' : type === 'number' ? 'number' : type === 'password' ? 'password' : 'text';
|
|
1729
1729
|
return h('div', { className: 'space-y-1.5 ' + compClass, style: compStyle },
|
|
@@ -1739,6 +1739,7 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
1739
1739
|
placeholder: props.placeholder || '',
|
|
1740
1740
|
value: formState[comp.id] ?? '',
|
|
1741
1741
|
onChange: (e) => onFieldChange(comp.id, e.target.value),
|
|
1742
|
+
onKeyDown: (e) => { if (e.key === 'Enter' && onSubmit) { e.preventDefault(); onSubmit(); } },
|
|
1742
1743
|
})
|
|
1743
1744
|
);
|
|
1744
1745
|
}
|
|
@@ -2414,6 +2415,8 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
2414
2415
|
const historyRef = React.useRef(history);
|
|
2415
2416
|
historyRef.current = history;
|
|
2416
2417
|
const autoAdvanceTimer = React.useRef(null);
|
|
2418
|
+
const globalsRef = React.useRef({});
|
|
2419
|
+
const [compPropOverrides, setCompPropOverrides] = React.useState({});
|
|
2417
2420
|
|
|
2418
2421
|
// --- Cart logic ---
|
|
2419
2422
|
const addToCart = React.useCallback((pageId) => {
|
|
@@ -2557,7 +2560,7 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
2557
2560
|
getField: (id) => formStateRef.current[id],
|
|
2558
2561
|
getAllFields: () => ({ ...formStateRef.current }),
|
|
2559
2562
|
getPageId: () => currentPageId,
|
|
2560
|
-
setField: (id, value) =>
|
|
2563
|
+
setField: (id, value) => onFieldChangeRef.current?.(id, value),
|
|
2561
2564
|
goNext: () => handleNextRef.current?.(),
|
|
2562
2565
|
goBack: () => handleBackRef.current?.(),
|
|
2563
2566
|
on: (event, cb) => { if (!listeners[event]) listeners[event] = new Set(); listeners[event].add(cb); },
|
|
@@ -2565,6 +2568,11 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
2565
2568
|
openCart: () => setCartOpen(true),
|
|
2566
2569
|
closeCart: () => setCartOpen(false),
|
|
2567
2570
|
getCartItems: () => [...cartItems],
|
|
2571
|
+
getGlobal: (key) => globalsRef.current[key],
|
|
2572
|
+
setGlobal: (key, value) => { globalsRef.current[key] = value; },
|
|
2573
|
+
setComponentProp: (id, prop, value) => {
|
|
2574
|
+
setCompPropOverrides(prev => ({ ...prev, [id]: { ...(prev[id] || {}), [prop]: value } }));
|
|
2575
|
+
},
|
|
2568
2576
|
setValidationError: (id, msg) => {
|
|
2569
2577
|
setValidationErrors(prev => {
|
|
2570
2578
|
const next = prev.filter(e => e.componentId !== id);
|
|
@@ -2573,7 +2581,7 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
2573
2581
|
});
|
|
2574
2582
|
},
|
|
2575
2583
|
};
|
|
2576
|
-
window.CatalogKit = { get: () => instance, getField: instance.getField, setField: instance.setField, getPageId: instance.getPageId, goNext: instance.goNext, goBack: instance.goBack, on: instance.on, off: instance.off };
|
|
2584
|
+
window.CatalogKit = { get: () => instance, getField: instance.getField, setField: instance.setField, getPageId: instance.getPageId, goNext: instance.goNext, goBack: instance.goBack, on: instance.on, off: instance.off, setGlobal: instance.setGlobal, getGlobal: instance.getGlobal, setComponentProp: instance.setComponentProp };
|
|
2577
2585
|
window.__catalogKitListeners = listeners;
|
|
2578
2586
|
return () => { delete window.CatalogKit; delete window.__catalogKitListeners; };
|
|
2579
2587
|
}, []);
|
|
@@ -2615,9 +2623,11 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
2615
2623
|
const onFieldChange = React.useCallback((id, value) => {
|
|
2616
2624
|
setFormState(prev => ({ ...prev, [id]: value }));
|
|
2617
2625
|
devEvents.emit('field_change', { field_id: id, value, page_id: currentPageId });
|
|
2618
|
-
// Fire CatalogKit fieldchange
|
|
2626
|
+
// Fire CatalogKit fieldchange (unscoped + scoped)
|
|
2619
2627
|
const ckListeners = window.__catalogKitListeners || {};
|
|
2620
|
-
const
|
|
2628
|
+
const fcPayload = { fieldId: id, value, pageId: currentPageId };
|
|
2629
|
+
const fcSet = ckListeners['fieldchange']; if (fcSet?.size) for (const cb of fcSet) { try { cb(fcPayload); } catch {} }
|
|
2630
|
+
const scopedSet = ckListeners['fieldchange:' + id]; if (scopedSet?.size) for (const cb of scopedSet) { try { cb(fcPayload); } catch {} }
|
|
2621
2631
|
|
|
2622
2632
|
// Auto-advance: if page has auto_advance and this is a selection-type input
|
|
2623
2633
|
const pg = pages[currentPageId];
|
|
@@ -2647,6 +2657,8 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
2647
2657
|
}
|
|
2648
2658
|
}
|
|
2649
2659
|
}, [currentPageId, pages, formState, routing, navigateTo]);
|
|
2660
|
+
const onFieldChangeRef = React.useRef(onFieldChange);
|
|
2661
|
+
onFieldChangeRef.current = onFieldChange;
|
|
2650
2662
|
|
|
2651
2663
|
// --- Validation ---
|
|
2652
2664
|
const runValidation = React.useCallback(() => {
|
|
@@ -2684,6 +2696,21 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
2684
2696
|
if (currentPage?.offer) {
|
|
2685
2697
|
if (!currentPage.offer.accept_field) addToCart(currentPageId);
|
|
2686
2698
|
}
|
|
2699
|
+
// Fire CatalogKit beforenext event (scoped: "beforenext" + "beforenext:<pageId>")
|
|
2700
|
+
let prevented = false;
|
|
2701
|
+
let nextPageOverride;
|
|
2702
|
+
const beforeNextPayload = {
|
|
2703
|
+
pageId: currentPageId,
|
|
2704
|
+
preventDefault: () => { prevented = true; },
|
|
2705
|
+
setNextPage: (id) => { nextPageOverride = id; },
|
|
2706
|
+
};
|
|
2707
|
+
const ckListeners = window.__catalogKitListeners || {};
|
|
2708
|
+
for (const key of ['beforenext', 'beforenext:' + currentPageId]) {
|
|
2709
|
+
const set = ckListeners[key]; if (!set?.size) continue;
|
|
2710
|
+
for (const cb of set) { try { cb(beforeNextPayload); } catch (e) { console.error('[CatalogKit]', key, e); } }
|
|
2711
|
+
}
|
|
2712
|
+
if (prevented) return;
|
|
2713
|
+
if (nextPageOverride !== undefined) { navigateTo(nextPageOverride); return; }
|
|
2687
2714
|
const nextId = getNextPage(routing, currentPageId, formState, devContext);
|
|
2688
2715
|
navigateTo(nextId);
|
|
2689
2716
|
}, [currentPageId, routing, formState, pages, addToCart, navigateTo, runValidation]);
|
|
@@ -2879,6 +2906,11 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
2879
2906
|
if (c.prefill_mode === 'hidden' && formState[c.id] != null && formState[c.id] !== '') return false;
|
|
2880
2907
|
return true;
|
|
2881
2908
|
});
|
|
2909
|
+
// Find the last input component for Enter-to-submit
|
|
2910
|
+
const inputTypes = ['short_text', 'long_text', 'email', 'phone', 'url', 'number', 'password', 'currency', 'date', 'datetime', 'time', 'address'];
|
|
2911
|
+
const lastInputComp = [...components].reverse().find(c => inputTypes.includes(c.type));
|
|
2912
|
+
const lastInputId = lastInputComp?.id;
|
|
2913
|
+
|
|
2882
2914
|
const bgImage = page.background_image || catalog.settings?.theme?.background_image;
|
|
2883
2915
|
|
|
2884
2916
|
// Cart UI (shared between cover and standard)
|
|
@@ -2910,8 +2942,9 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
2910
2942
|
);
|
|
2911
2943
|
}
|
|
2912
2944
|
const fieldError = validationErrors.find(e => e.componentId === comp.id);
|
|
2945
|
+
const submitHandler = comp.id === lastInputId ? handleNext : undefined;
|
|
2913
2946
|
return h('div', { key: comp.id || i, 'data-component-id': comp.id, 'data-component-type': comp.type, className: fieldError ? 'cf-field-error' : '' },
|
|
2914
|
-
h(RenderComponent, { comp, isCover: true, formState, onFieldChange }),
|
|
2947
|
+
h(RenderComponent, { comp, isCover: true, formState, onFieldChange, onSubmit: submitHandler, propOverrides: compPropOverrides }),
|
|
2915
2948
|
fieldError ? h('p', { className: 'text-xs text-red-300 font-medium mt-1', role: 'alert' }, fieldError.message) : null
|
|
2916
2949
|
);
|
|
2917
2950
|
}),
|
|
@@ -2972,8 +3005,9 @@ function buildPreviewHtml(schema, port, validation, devConfig) {
|
|
|
2972
3005
|
);
|
|
2973
3006
|
}
|
|
2974
3007
|
const fieldError = validationErrors.find(e => e.componentId === comp.id);
|
|
3008
|
+
const submitHandler = comp.id === lastInputId ? handleNext : undefined;
|
|
2975
3009
|
return h('div', { key: comp.id || i, 'data-component-id': comp.id, 'data-component-type': comp.type, className: fieldError ? 'cf-field-error' : '' },
|
|
2976
|
-
h(RenderComponent, { comp, isCover: false, formState, onFieldChange }),
|
|
3010
|
+
h(RenderComponent, { comp, isCover: false, formState, onFieldChange, onSubmit: submitHandler, propOverrides: compPropOverrides }),
|
|
2977
3011
|
fieldError ? h('p', { className: 'text-xs text-red-500 font-medium mt-1', role: 'alert' }, fieldError.message) : null
|
|
2978
3012
|
);
|
|
2979
3013
|
}),
|