Enhance platform row block with new animation options and gallery support
- Added new attributes for dashboard, device, TV stick, camera, never goes dark, and branded animations in the platform row block. - Implemented HTML structures for various animations including dashboard, device, TV stick, and branded displays. - Integrated a media uploader for selecting images for a TV slideshow. - Updated the editor controls to manage new animation settings and gallery images. Update enqueue scripts for new animation functionalities - Enqueued scripts for gallery TV slideshow and video editor timeline animator. Revise theme color palette for improved aesthetics - Changed primary color scheme to a new vibrant palette for light and dark modes. Adjust button styles to reflect new primary color - Updated button background color to match the new primary color in theme settings. Modify theme JSON to align with new color definitions - Updated color definitions in theme.json to reflect the new primary color scheme for both light and dark modes.
This commit is contained in:
@@ -1170,28 +1170,105 @@ reg('oribi/platform-row', {
|
||||
parent: ['oribi/platform-section'],
|
||||
supports: { html: false, reusable: false },
|
||||
attributes: {
|
||||
heading: { type: 'string', default: '' },
|
||||
description: { type: 'string', default: '' },
|
||||
btnText: { type: 'string', default: 'Learn More' },
|
||||
btnUrl: { type: 'string', default: '' },
|
||||
visual: { type: 'string', default: '' },
|
||||
reversed: { type: 'boolean', default: false },
|
||||
imgId: { type: 'number', default: 0 },
|
||||
imgUrl: { type: 'string', default: '' },
|
||||
imgAlt: { type: 'string', default: '' },
|
||||
imgWidth: { type: 'number', default: 300 },
|
||||
cameraAnim: { type: 'boolean', default: false },
|
||||
heading: { type: 'string', default: '' },
|
||||
description: { type: 'string', default: '' },
|
||||
btnText: { type: 'string', default: 'Learn More' },
|
||||
btnUrl: { type: 'string', default: '' },
|
||||
visual: { type: 'string', default: '' },
|
||||
reversed: { type: 'boolean', default: false },
|
||||
imgId: { type: 'number', default: 0 },
|
||||
imgUrl: { type: 'string', default: '' },
|
||||
imgAlt: { type: 'string', default: '' },
|
||||
imgWidth: { type: 'number', default: 300 },
|
||||
isDashboard: { type: 'boolean', default: false },
|
||||
deviceAnim: { type: 'boolean', default: false },
|
||||
tvStick: { type: 'boolean', default: false },
|
||||
cameraAnim: { type: 'boolean', default: false },
|
||||
neverGoesDark: { type: 'boolean', default: false },
|
||||
brandedAnim: { type: 'boolean', default: false },
|
||||
galleryIds: { type: 'array', default: [] },
|
||||
},
|
||||
edit: function (props) {
|
||||
var a = props.attributes, s = props.setAttributes;
|
||||
var imgW = a.imgWidth || 300;
|
||||
|
||||
/* ── Animation HTML strings (mirror PHP render, used via dangerouslySetInnerHTML) ── */
|
||||
var DA_SCREEN = '<div class="da-screen"><div class="da-promo"><div class="da-promo__top"><span class="da-promo__dot"></span><span class="da-promo__brand"></span></div><div class="da-promo__hero"></div><div class="da-promo__row"><span class="da-promo__line da-promo__line--lg"></span><span class="da-promo__line da-promo__line--sm"></span></div><div class="da-promo__row"><span class="da-promo__line da-promo__line--md"></span><span class="da-promo__line da-promo__line--xs"></span></div><div class="da-promo__ticker"><span class="da-promo__chip"></span><span class="da-promo__chip"></span><span class="da-promo__chip"></span></div></div></div>';
|
||||
var DA_HTML = '<div class="da-stage" aria-hidden="true">' +
|
||||
'<div class="da-device da-tablet"><div class="da-body">' + DA_SCREEN + '</div><span class="da-label">Tablet</span></div>' +
|
||||
'<div class="da-device da-monitor-sm"><div class="da-body">' + DA_SCREEN + '</div><div class="da-stand"><div class="da-stem"></div><div class="da-base"></div></div><span class="da-label">Small Monitor</span></div>' +
|
||||
'<div class="da-device da-monitor-lg"><div class="da-body">' + DA_SCREEN + '</div><div class="da-stand"><div class="da-stem"></div><div class="da-base"></div></div><span class="da-label">Large Monitor</span></div>' +
|
||||
'<div class="da-device da-tv"><div class="da-body">' + DA_SCREEN + '</div><div class="da-feet"><div class="da-foot"></div><div class="da-foot"></div></div><span class="da-label">TV</span></div>' +
|
||||
'<div class="da-device da-projector"><div class="da-proj-layout"><div class="da-proj-body"><div class="da-lens"></div></div><div class="da-beam"></div><div class="da-proj-screen">' + DA_SCREEN + '</div></div><span class="da-label">Projector</span></div>' +
|
||||
'<div class="da-device da-vwall"><div class="da-vwall-grid"><div class="da-panel">' + DA_SCREEN + '</div><div class="da-panel">' + DA_SCREEN + '</div><div class="da-panel">' + DA_SCREEN + '</div><div class="da-panel">' + DA_SCREEN + '</div></div><span class="da-label">Video Wall</span></div>' +
|
||||
'</div>';
|
||||
|
||||
var TS_MI = '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
|
||||
var TS_COL = '<div class="ts-menu__col"><div class="ts-menu__cat"></div>' + TS_MI + TS_MI + TS_MI + '</div>';
|
||||
var TS_HTML = '<div class="ts-stage" data-tv-stick-anim aria-hidden="true">' +
|
||||
'<div class="ts-tv"><div class="ts-tv__body"><div class="ts-tv__screen"><div class="ts-slides">' +
|
||||
'<div class="ts-slide ts-slide--menu"><div class="ts-menu"><div class="ts-menu__header"><div class="ts-menu__logo"></div><div class="ts-menu__title"></div></div><div class="ts-menu__cols">' + TS_COL + TS_COL + '</div></div></div>' +
|
||||
'<div class="ts-slide ts-slide--wayfind"><div class="ts-wf"><div class="ts-wf__header"><div class="ts-wf__building"></div></div><div class="ts-wf__rows"><div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--left"></span><span class="ts-wf__label ts-wf__label--w1"></span><span class="ts-wf__floor"></span></div><div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--right"></span><span class="ts-wf__label ts-wf__label--w2"></span><span class="ts-wf__floor"></span></div><div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--up"></span><span class="ts-wf__label ts-wf__label--w3"></span><span class="ts-wf__floor"></span></div><div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--left"></span><span class="ts-wf__label ts-wf__label--w4"></span><span class="ts-wf__floor"></span></div></div></div></div>' +
|
||||
'<div class="ts-slide ts-slide--sched"><div class="ts-sched"><div class="ts-sched__header"><div class="ts-sched__title"></div><div class="ts-sched__date"></div></div><div class="ts-sched__table"><div class="ts-sched__hrow"><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span></div><div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__event ts-sched__event--a"></span><span class="ts-sched__cell"></span><span class="ts-sched__cell"></span></div><div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__cell"></span><span class="ts-sched__event ts-sched__event--b"></span><span class="ts-sched__cell"></span></div><div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__cell"></span><span class="ts-sched__cell"></span><span class="ts-sched__event ts-sched__event--c"></span></div><div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__event ts-sched__event--a"></span><span class="ts-sched__event ts-sched__event--b"></span><span class="ts-sched__cell"></span></div></div></div></div>' +
|
||||
'</div></div><div class="ts-tv__port"></div></div><div class="ts-tv__feet"><div class="ts-tv__foot"></div><div class="ts-tv__foot"></div></div></div>' +
|
||||
'<div class="ts-stick"><div class="ts-stick__body"><div class="ts-stick__led"></div></div><div class="ts-stick__connector"></div></div>' +
|
||||
'</div>';
|
||||
|
||||
var NGD_ROW = '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
||||
var NGD_ROWH = '<div class="ngd-menu__row ngd-menu__row--hl"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
|
||||
var NGD_HTML = '<div class="ngd-stage" aria-hidden="true">' +
|
||||
'<div class="ngd-tv"><div class="ngd-tv__body"><div class="ngd-tv__screen"><div class="ngd-menu"><div class="ngd-menu__hd"><div class="ngd-menu__logo"></div><div class="ngd-menu__ttl"></div></div><div class="ngd-menu__cols"><div class="ngd-menu__col"><div class="ngd-menu__cat"></div>' + NGD_ROW + NGD_ROWH + NGD_ROW + '</div><div class="ngd-menu__col"><div class="ngd-menu__cat"></div>' + NGD_ROW + NGD_ROW + NGD_ROWH + '</div></div><div class="ngd-menu__ticker"><div class="ngd-menu__ticker-inner"></div></div></div></div><div class="ngd-tv__port"></div></div><div class="ngd-tv__feet"><div class="ngd-tv__foot"></div><div class="ngd-tv__foot"></div></div></div>' +
|
||||
'<div class="ngd-player"><div class="ngd-player__connector"></div><div class="ngd-player__body"><div class="ngd-player__led"></div></div><div class="ngd-player__check"><svg viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="11" cy="11" r="10" stroke="#4CAF50" stroke-width="1.5"/><polyline points="6,11 9.5,14.5 16,7.5" stroke="#4CAF50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></div></div>' +
|
||||
'<div class="ngd-signal-wrap"><div class="ngd-cloud"><svg class="ngd-cloud__svg" viewBox="0 0 64 46" fill="none" xmlns="http://www.w3.org/2000/svg"><circle class="ngd-cloud__path" cx="32" cy="23" r="14" stroke-width="2.2" fill="none"/><path class="ngd-cloud__path" d="M18.5 23C23 20 41 20 45.5 23" stroke-width="1.9" stroke-linecap="round" fill="none"/><path class="ngd-cloud__path" d="M20.5 29C25.5 31 38.5 31 43.5 29" stroke-width="1.9" stroke-linecap="round" fill="none"/><path class="ngd-cloud__path" d="M24.5 12C21.5 16.5 21.5 29.5 24.5 34" stroke-width="1.9" stroke-linecap="round" fill="none"/><path class="ngd-cloud__path" d="M39.5 12C42.5 16.5 42.5 29.5 39.5 34" stroke-width="1.9" stroke-linecap="round" fill="none"/></svg></div><div class="ngd-signal-line"><div class="ngd-signal__dots"><div class="ngd-signal__dot ngd-signal__dot--1"></div><div class="ngd-signal__dot ngd-signal__dot--2"></div><div class="ngd-signal__dot ngd-signal__dot--3"></div></div><div class="ngd-signal__break"><svg viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="9" cy="9" r="8" fill="rgba(239,68,68,0.12)" stroke="#ef4444" stroke-width="1.2"/><line x1="5.5" y1="5.5" x2="12.5" y2="12.5" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/><line x1="12.5" y1="5.5" x2="5.5" y2="12.5" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/></svg></div></div></div>' +
|
||||
'</div>';
|
||||
|
||||
var BD_SPLASH = '<div class="bd-splash"><div class="bd-splash__logo"></div></div>';
|
||||
var BD_HDR = '<div class="bd-ui__header"><div class="bd-ui__logo"></div><div class="bd-ui__brand-bar"></div></div>';
|
||||
var BD_HTML = '<div class="bd-stage" aria-hidden="true">' +
|
||||
'<div class="bd-device bd-device--tablet"><span class="bd-device__label">Kiosk</span><div class="bd-device__body"><div class="bd-device__screen">' + BD_SPLASH + '<div class="bd-ui">' + BD_HDR + '<div class="bd-ui__content"><div class="bd-promo bd-promo--welcome"><div class="bd-promo__hero"></div><div class="bd-promo__heading"></div><div class="bd-promo__text"></div><div class="bd-promo__btn"></div></div></div></div></div></div></div>' +
|
||||
'<div class="bd-device bd-device--wall"><span class="bd-device__label">Wall Display</span><div class="bd-device__body"><div class="bd-device__screen">' + BD_SPLASH + '<div class="bd-ui">' + BD_HDR + '<div class="bd-ui__content"><div class="bd-promo bd-promo--sale"><div class="bd-promo__cols"><div class="bd-promo__visual"></div><div class="bd-promo__info"><div class="bd-promo__badge"></div><div class="bd-promo__heading"></div><div class="bd-promo__text"></div><div class="bd-promo__text bd-promo__text--short"></div><div class="bd-promo__price"></div></div></div></div></div></div></div></div><div class="bd-mount"></div></div>' +
|
||||
'<div class="bd-device bd-device--interactive"><span class="bd-device__label">Interactive</span><div class="bd-device__body"><div class="bd-device__screen">' + BD_SPLASH + '<div class="bd-ui">' + BD_HDR + '<div class="bd-ui__content"><div class="bd-promo bd-promo--menu"><div class="bd-promo__heading"></div><div class="bd-promo__grid"><div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div><div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div><div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div><div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div></div></div></div></div></div></div><div class="bd-table"></div></div>' +
|
||||
'</div>';
|
||||
|
||||
var DB_HTML = '<div class="dashboard-tv" data-dashboard-container="true"><div class="dashboard-tv__body"><div class="dashboard-tv__screen"><svg viewBox="0 0 800 450" xmlns="http://www.w3.org/2000/svg" class="dashboard-chart" role="img" aria-label="Animated dashboard charts"><defs><linearGradient id="dbe-barGrad" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#D83302" stop-opacity="1"/><stop offset="100%" stop-color="#4CAF50" stop-opacity=".8"/></linearGradient><linearGradient id="dbe-lineGrad" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#4CAF50" stop-opacity=".3"/><stop offset="100%" stop-color="#4CAF50" stop-opacity="0"/></linearGradient></defs><g transform="translate(35,20)"><text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#888">Performance</text><g id="dbe-bars1" transform="translate(0,25)"><rect x="0" y="60" width="28" height="60" fill="url(#dbe-barGrad)"/><rect x="40" y="80" width="28" height="40" fill="url(#dbe-barGrad)"/><rect x="80" y="40" width="28" height="80" fill="url(#dbe-barGrad)"/><rect x="120" y="70" width="28" height="50" fill="url(#dbe-barGrad)"/><rect x="160" y="50" width="28" height="70" fill="url(#dbe-barGrad)"/></g><g transform="translate(0,152)"><text class="cl" x="14" y="0" font-size="10" text-anchor="middle" fill="#aaa">API</text><text class="cl" x="54" y="0" font-size="10" text-anchor="middle" fill="#aaa">Cache</text><text class="cl" x="94" y="0" font-size="10" text-anchor="middle" fill="#aaa">DB</text><text class="cl" x="134" y="0" font-size="10" text-anchor="middle" fill="#aaa">Queue</text><text class="cl" x="174" y="0" font-size="10" text-anchor="middle" fill="#aaa">Worker</text></g></g><g transform="translate(430,20)"><text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#888">Requests/sec</text><g transform="translate(0,25)"><rect x="0" y="50" width="28" height="70" fill="url(#dbe-barGrad)"/><rect x="40" y="30" width="28" height="90" fill="url(#dbe-barGrad)"/><rect x="80" y="65" width="28" height="55" fill="url(#dbe-barGrad)"/><rect x="120" y="45" width="28" height="75" fill="url(#dbe-barGrad)"/></g><g transform="translate(0,152)"><text class="cl" x="14" y="0" font-size="10" text-anchor="middle" fill="#aaa">Read</text><text class="cl" x="54" y="0" font-size="10" text-anchor="middle" fill="#aaa">Write</text><text class="cl" x="94" y="0" font-size="10" text-anchor="middle" fill="#aaa">Update</text><text class="cl" x="134" y="0" font-size="10" text-anchor="middle" fill="#aaa">Delete</text></g></g><g transform="translate(35,245)"><text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#888">Traffic Trend</text><g transform="translate(0,25)"><line class="grid-line" x1="0" y1="0" x2="340" y2="0" stroke="#ddd" stroke-width=".5"/><line class="grid-line" x1="0" y1="40" x2="340" y2="40" stroke="#ddd" stroke-width=".5"/><line class="grid-line" x1="0" y1="80" x2="340" y2="80" stroke="#ddd" stroke-width=".5"/><line class="grid-line" x1="0" y1="120" x2="340" y2="120" stroke="#ddd" stroke-width=".5"/><path d="M0,90 L42,70 L85,50 L127,80 L170,45 L212,65 L255,55 L297,75 L340,60 L340,145 L0,145 Z" fill="url(#dbe-lineGrad)"/><path d="M0,90 L42,70 L85,50 L127,80 L170,45 L212,65 L255,55 L297,75 L340,60" stroke="#4CAF50" stroke-width="2.5" fill="none" stroke-linecap="round"/></g></g><g transform="translate(490,245)"><text class="ct" x="100" y="0" font-size="14" font-weight="600" text-anchor="middle" fill="#888">Distribution</text><g transform="translate(100,90)"><path d="M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z" fill="#D83302" opacity=".9"/><path d="M0,0 L38.89,-38.89 A55,55 0 0,1 55,0 Z" fill="#4CAF50" opacity=".8"/><path d="M0,0 L55,0 A55,55 0 0,1 0,55 Z" fill="#f59e0b" opacity=".7"/><path d="M0,0 L0,55 A55,55 0 1,1 0,-55 Z" fill="#ef4444" opacity=".7"/><circle cx="0" cy="0" r="22" fill="#f5f5f5" stroke="#ddd" stroke-width="1"/></g></g></svg></div></div><div class="dashboard-tv__feet"><div class="dashboard-tv__foot"></div><div class="dashboard-tv__foot"></div></div></div>';
|
||||
|
||||
return el(Frag, null,
|
||||
el(IC, null,
|
||||
el(PB, { title: 'Row Settings' },
|
||||
el(TC, { label: 'Visual (emoji)', value: a.visual, onChange: function(v){s({visual:v});} }),
|
||||
el(TC, { label: 'Button URL', value: a.btnUrl, onChange: function(v){s({btnUrl:v});} }),
|
||||
el(TG, { label: 'Reversed', checked: !!a.reversed, onChange: function(v){s({reversed:v});} }),
|
||||
el(TG, { label: 'Camera Animation', checked: !!a.cameraAnim, onChange: function(v){s({cameraAnim:v});} })
|
||||
el(TG, { label: 'Dashboard Animation', checked: !!a.isDashboard, onChange: function(v){s({isDashboard:v});} }),
|
||||
el(TG, { label: 'Device Animation', checked: !!a.deviceAnim, onChange: function(v){s({deviceAnim:v});} }),
|
||||
el(TG, { label: 'TV Stick Animation', checked: !!a.tvStick, onChange: function(v){s({tvStick:v});} }),
|
||||
el(TG, { label: 'Camera Animation', checked: !!a.cameraAnim, onChange: function(v){s({cameraAnim:v});} }),
|
||||
el(TG, { label: 'Never Goes Dark', checked: !!a.neverGoesDark, onChange: function(v){s({neverGoesDark:v});} }),
|
||||
el(TG, { label: 'Branded Display', checked: !!a.brandedAnim, onChange: function(v){s({brandedAnim:v});} })
|
||||
),
|
||||
el(PB, { title: 'Gallery TV Slideshow', initialOpen: false },
|
||||
el(MUC, null,
|
||||
el(MU, {
|
||||
onSelect: function(media) {
|
||||
s({ galleryIds: media.map(function(m){ return m.id; }) });
|
||||
},
|
||||
allowedTypes: ['image'],
|
||||
gallery: true,
|
||||
multiple: true,
|
||||
value: a.galleryIds || [],
|
||||
render: function(ref) {
|
||||
return el(Frag, null,
|
||||
a.galleryIds && a.galleryIds.length
|
||||
? el('div', { style: { marginBottom: '8px' } },
|
||||
el('p', { style: { margin: '0 0 4px' } }, a.galleryIds.length + ' image(s) selected'),
|
||||
el(Btn, { variant: 'link', isDestructive: true, onClick: function(){ s({ galleryIds: [] }); } }, 'Clear gallery')
|
||||
)
|
||||
: null,
|
||||
el(Btn, { onClick: ref.open, variant: 'secondary', __next40pxDefaultSize: true },
|
||||
a.galleryIds && a.galleryIds.length ? 'Edit gallery' : 'Select images for TV slideshow')
|
||||
);
|
||||
}
|
||||
})
|
||||
)
|
||||
),
|
||||
el(PB, { title: 'Visual Image', initialOpen: false },
|
||||
el(MUC, null,
|
||||
@@ -1222,7 +1299,9 @@ reg('oribi/platform-row', {
|
||||
a.btnUrl ? el(RT, { tagName: 'span', className: 'btn btn-outline mt-3',
|
||||
value: a.btnText, onChange: function(v){s({btnText:v});}, placeholder: 'Button...' }) : null
|
||||
),
|
||||
a.cameraAnim
|
||||
a.isDashboard
|
||||
? el('div', { className: 'platform-visual has-dashboard', dangerouslySetInnerHTML: { __html: DB_HTML } })
|
||||
: a.cameraAnim
|
||||
? el('div', { className: 'platform-visual has-camera' },
|
||||
el('div', { className: 'cam-stage', 'aria-hidden': 'true' },
|
||||
// Photo camera (left)
|
||||
@@ -1282,6 +1361,14 @@ reg('oribi/platform-row', {
|
||||
)
|
||||
)
|
||||
)
|
||||
: a.deviceAnim
|
||||
? el('div', { className: 'platform-visual has-anim', dangerouslySetInnerHTML: { __html: DA_HTML } })
|
||||
: a.tvStick
|
||||
? el('div', { className: 'platform-visual has-tv-stick', dangerouslySetInnerHTML: { __html: TS_HTML } })
|
||||
: a.neverGoesDark
|
||||
? el('div', { className: 'platform-visual has-ngd', dangerouslySetInnerHTML: { __html: NGD_HTML } })
|
||||
: a.brandedAnim
|
||||
? el('div', { className: 'platform-visual has-branded', dangerouslySetInnerHTML: { __html: BD_HTML } })
|
||||
: a.imgUrl
|
||||
? el('div', { className: 'platform-visual has-img' },
|
||||
el('img', { src: a.imgUrl, style: { width: imgW + 'px', maxWidth: '100%', height: 'auto', borderRadius: '4px', objectFit: 'contain', display: 'block', marginInline: 'auto' } })
|
||||
@@ -1618,6 +1705,74 @@ reg('oribi/comparison-table', {
|
||||
var a = props.attributes, s = props.setAttributes;
|
||||
var cols = a.columns || [];
|
||||
var rows = a.rows || [];
|
||||
|
||||
/* ── Column helpers ─────────────────────────────────────── */
|
||||
function updateCol(idx, val) {
|
||||
var c = cols.slice(); c[idx] = val; s({ columns: c });
|
||||
}
|
||||
function addCol() {
|
||||
var newRows = rows.map(function(r) {
|
||||
if (r.group) return r;
|
||||
return Object.assign({}, r, { values: (r.values || []).concat([false]) });
|
||||
});
|
||||
s({ columns: cols.concat(['Plan']), rows: newRows });
|
||||
}
|
||||
function removeCol(idx) {
|
||||
var c = cols.slice(); c.splice(idx, 1);
|
||||
var newRows = rows.map(function(r) {
|
||||
if (r.group) return r;
|
||||
var v = (r.values || []).slice(); v.splice(idx, 1);
|
||||
return Object.assign({}, r, { values: v });
|
||||
});
|
||||
s({ columns: c, rows: newRows });
|
||||
}
|
||||
|
||||
/* ── Row helpers ────────────────────────────────────────── */
|
||||
function updateRow(idx, key, val) {
|
||||
var r = rows.slice();
|
||||
r[idx] = Object.assign({}, r[idx]);
|
||||
r[idx][key] = val;
|
||||
s({ rows: r });
|
||||
}
|
||||
function updateCell(ri, ci, val) {
|
||||
var r = rows.slice();
|
||||
r[ri] = Object.assign({}, r[ri]);
|
||||
var v = (r[ri].values || []).slice();
|
||||
v[ci] = val;
|
||||
r[ri].values = v;
|
||||
s({ rows: r });
|
||||
}
|
||||
function toggleCell(ri, ci) {
|
||||
var val = (rows[ri].values || [])[ci];
|
||||
updateCell(ri, ci, val === true ? false : val === false ? true : true);
|
||||
}
|
||||
function switchCellToText(ri, ci) { updateCell(ri, ci, ''); }
|
||||
function addFeatureRow() {
|
||||
var vals = cols.map(function() { return false; });
|
||||
s({ rows: rows.concat([{ feature: 'New feature', values: vals }]) });
|
||||
}
|
||||
function addGroupRow() {
|
||||
s({ rows: rows.concat([{ group: 'New Group' }]) });
|
||||
}
|
||||
function removeRow(idx) {
|
||||
var r = rows.slice(); r.splice(idx, 1); s({ rows: r });
|
||||
}
|
||||
function moveRow(idx, dir) {
|
||||
var t = idx + dir;
|
||||
if (t < 0 || t >= rows.length) return;
|
||||
var r = rows.slice();
|
||||
var tmp = r[idx]; r[idx] = r[t]; r[t] = tmp;
|
||||
s({ rows: r });
|
||||
}
|
||||
|
||||
/* ── Inline styles for editor controls ──────────────────── */
|
||||
var inputStyle = { width: '100%', padding: '4px 6px', border: '1px solid #ddd', borderRadius: '3px', fontSize: '13px', background: 'transparent', boxSizing: 'border-box' };
|
||||
var thInputStyle = Object.assign({}, inputStyle, { fontWeight: 600, textAlign: 'center' });
|
||||
var smallBtnStyle = { background: 'none', border: 'none', cursor: 'pointer', padding: '2px 4px', fontSize: '11px', lineHeight: 1, opacity: 0.6, verticalAlign: 'middle' };
|
||||
var rowCtrlStyle = { whiteSpace: 'nowrap', width: '1%', padding: '4px', verticalAlign: 'middle', border: 'none', background: 'transparent' };
|
||||
var cellBtnStyle = { background: 'none', border: '1px solid #ddd', borderRadius: '3px', cursor: 'pointer', padding: '2px 6px', fontSize: '13px', lineHeight: '1.4', margin: '0 1px' };
|
||||
|
||||
/* ── Render ─────────────────────────────────────────────── */
|
||||
return el(Frag, null,
|
||||
el(IC, null,
|
||||
el(PB, { title: 'Table Settings' },
|
||||
@@ -1625,6 +1780,21 @@ reg('oribi/comparison-table', {
|
||||
{ label: 'Normal', value: 'normal' }, { label: 'Alternate', value: 'alt' }
|
||||
], onChange: function(v){s({variant:v});} }),
|
||||
el(TC, { label: 'Label', value: a.label, onChange: function(v){s({label:v});} })
|
||||
),
|
||||
el(PB, { title: 'Columns', initialOpen: false },
|
||||
cols.map(function(col, i) {
|
||||
return el('div', { key: i, style: { display: 'flex', gap: '4px', marginBottom: '8px', alignItems: 'center' } },
|
||||
el(TC, { label: '', value: col, onChange: function(v){ updateCol(i, v); }, style: { flex: 1 } }),
|
||||
el(Btn, { isDestructive: true, isSmall: true, onClick: function(){ removeCol(i); } }, '\u2715')
|
||||
);
|
||||
}),
|
||||
el(Btn, { isSecondary: true, isSmall: true, onClick: addCol }, '+ Add Column')
|
||||
),
|
||||
el(PB, { title: 'Add Rows', initialOpen: false },
|
||||
el('div', { style: { display: 'flex', gap: '8px' } },
|
||||
el(Btn, { isSecondary: true, isSmall: true, onClick: addFeatureRow }, '+ Feature Row'),
|
||||
el(Btn, { isSecondary: true, isSmall: true, onClick: addGroupRow }, '+ Group Row')
|
||||
)
|
||||
)
|
||||
),
|
||||
el('section', { className: a.variant === 'alt' ? 'section section-alt' : 'section' },
|
||||
@@ -1639,26 +1809,62 @@ reg('oribi/comparison-table', {
|
||||
el('thead', null,
|
||||
el('tr', null,
|
||||
el('th', { className: 'comparison-feature-col' }, 'Feature'),
|
||||
cols.map(function(col, i) { return el('th', { key: i }, col); })
|
||||
cols.map(function(col, i) {
|
||||
return el('th', { key: i },
|
||||
el('input', { type: 'text', value: col, style: thInputStyle, onChange: function(e){ updateCol(i, e.target.value); } })
|
||||
);
|
||||
}),
|
||||
el('th', { style: rowCtrlStyle })
|
||||
)
|
||||
),
|
||||
el('tbody', null,
|
||||
rows.map(function(row, i) {
|
||||
rows.map(function(row, ri) {
|
||||
if (row.group) {
|
||||
return el('tr', { key: i, className: 'comparison-group-row' },
|
||||
el('td', { colSpan: cols.length + 1 }, row.group)
|
||||
return el('tr', { key: ri, className: 'comparison-group-row' },
|
||||
el('td', { colSpan: cols.length + 1 },
|
||||
el('input', { type: 'text', value: row.group, style: Object.assign({}, inputStyle, { fontWeight: 700 }), onChange: function(e){ updateRow(ri, 'group', e.target.value); } })
|
||||
),
|
||||
el('td', { style: rowCtrlStyle },
|
||||
el('button', { style: smallBtnStyle, onClick: function(){ moveRow(ri, -1); }, title: 'Move up' }, '\u25B2'),
|
||||
el('button', { style: smallBtnStyle, onClick: function(){ moveRow(ri, 1); }, title: 'Move down' }, '\u25BC'),
|
||||
el('button', { style: Object.assign({}, smallBtnStyle, { color: '#b00' }), onClick: function(){ removeRow(ri); }, title: 'Remove row' }, '\u2715')
|
||||
)
|
||||
);
|
||||
}
|
||||
return el('tr', { key: i },
|
||||
el('td', { className: 'comparison-feature-name' }, row.feature || ''),
|
||||
(row.values || []).map(function(val, j) {
|
||||
return el('td', { key: j, className: 'comparison-cell' },
|
||||
val === true ? '\u2713' : val === false ? '\u2014' : String(val)
|
||||
return el('tr', { key: ri },
|
||||
el('td', { className: 'comparison-feature-name' },
|
||||
el('input', { type: 'text', value: row.feature || '', style: inputStyle, placeholder: 'Feature name\u2026', onChange: function(e){ updateRow(ri, 'feature', e.target.value); } })
|
||||
),
|
||||
(row.values || []).map(function(val, ci) {
|
||||
if (typeof val === 'boolean') {
|
||||
return el('td', { key: ci, className: 'comparison-cell', style: { textAlign: 'center' } },
|
||||
el('button', { style: Object.assign({}, cellBtnStyle, { color: val ? '#2e7d32' : '#c62828' }), onClick: function(){ toggleCell(ri, ci); }, title: 'Toggle \u2713/\u2717' },
|
||||
val ? '\u2713' : '\u2717'
|
||||
),
|
||||
el('button', { style: Object.assign({}, smallBtnStyle, { fontSize: '10px' }), onClick: function(){ switchCellToText(ri, ci); }, title: 'Switch to text' }, 'Aa')
|
||||
);
|
||||
}
|
||||
return el('td', { key: ci, className: 'comparison-cell' },
|
||||
el('div', { style: { display: 'flex', alignItems: 'center', gap: '2px' } },
|
||||
el('input', { type: 'text', value: String(val), style: Object.assign({}, inputStyle, { flex: 1, minWidth: '60px' }), placeholder: 'Value\u2026', onChange: function(e){ updateCell(ri, ci, e.target.value); } }),
|
||||
el('button', { style: Object.assign({}, smallBtnStyle, { color: '#2e7d32' }), onClick: function(){ updateCell(ri, ci, true); }, title: 'Set as \u2713' }, '\u2713'),
|
||||
el('button', { style: Object.assign({}, smallBtnStyle, { color: '#c62828' }), onClick: function(){ updateCell(ri, ci, false); }, title: 'Set as \u2717' }, '\u2717')
|
||||
)
|
||||
);
|
||||
})
|
||||
}),
|
||||
el('td', { style: rowCtrlStyle },
|
||||
el('button', { style: smallBtnStyle, onClick: function(){ moveRow(ri, -1); }, title: 'Move up' }, '\u25B2'),
|
||||
el('button', { style: smallBtnStyle, onClick: function(){ moveRow(ri, 1); }, title: 'Move down' }, '\u25BC'),
|
||||
el('button', { style: Object.assign({}, smallBtnStyle, { color: '#b00' }), onClick: function(){ removeRow(ri); }, title: 'Remove row' }, '\u2715')
|
||||
)
|
||||
);
|
||||
})
|
||||
)
|
||||
),
|
||||
el('div', { style: { display: 'flex', gap: '8px', marginTop: '12px', justifyContent: 'center' } },
|
||||
el(Btn, { isSecondary: true, isSmall: true, onClick: addFeatureRow }, '+ Feature Row'),
|
||||
el(Btn, { isSecondary: true, isSmall: true, onClick: addGroupRow }, '+ Group Row'),
|
||||
el(Btn, { isSecondary: true, isSmall: true, onClick: addCol }, '+ Column')
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user