UNPKG

lightview

Version:

A reactive UI library with features of Bau, Juris, and HTMX plus safe LLM UI generation

144 lines (118 loc) 4.25 kB
/** * Lightview Diff Component (DaisyUI) * @see https://daisyui.com/components/diff/ */ import '../daisyui.js'; /** * Diff Component - side-by-side comparison * @param {Object} props * @param {string} props.aspectRatio - Aspect ratio class (e.g., 'aspect-16/9') * @param {boolean} props.useShadow - Render in Shadow DOM with isolated DaisyUI styles */ const Diff = (props = {}, ...children) => { const { tags } = globalThis.Lightview || {}; const LVX = globalThis.LightviewX || {}; if (!tags) return null; const { div, shadowDOM } = tags; const { aspectRatio = 'aspect-video', useShadow, class: className = '', ...rest } = props; const diffEl = div({ class: `diff ${aspectRatio} ${className}`.trim(), ...rest }, ...children); // Check if we should use shadow DOM let usesShadow = false; if (LVX.shouldUseShadow) { usesShadow = LVX.shouldUseShadow(useShadow); } else { usesShadow = useShadow === true; } if (usesShadow) { const adoptedStyleSheets = LVX.getAdoptedStyleSheets ? LVX.getAdoptedStyleSheets() : []; const themeValue = LVX.themeSignal ? () => LVX.themeSignal.value : 'light'; return div({ class: 'contents' }, shadowDOM({ mode: 'open', adoptedStyleSheets }, div({ 'data-theme': themeValue }, diffEl ) ) ); } return diffEl; }; /** * Diff Item 1 */ Diff.Item1 = (props = {}, ...children) => { const { tags } = globalThis.Lightview || {}; if (!tags) return null; const { src, alt = '', class: className = '', ...rest } = props; if (src) { return tags.div({ class: `diff-item-1 ${className}`.trim(), role: 'img', ...rest }, tags.img({ src, alt, style: 'width: 100%; height: 100%; object-fit: cover; display: block;' }) ); } return tags.div({ class: `diff-item-1 ${className}`.trim(), ...rest }, ...children); }; /** * Diff Item 2 */ Diff.Item2 = (props = {}, ...children) => { const { tags } = globalThis.Lightview || {}; if (!tags) return null; const { src, alt = '', class: className = '', ...rest } = props; if (src) { return tags.div({ class: `diff-item-2 ${className}`.trim(), role: 'img', tabindex: '0', ...rest }, tags.img({ src, alt, style: 'width: 100%; height: 100%; object-fit: cover; display: block;' }) ); } return tags.div({ class: `diff-item-2 ${className}`.trim(), tabindex: '0', ...rest }, ...children); }; /** * Diff Resizer */ Diff.Resizer = (props = {}) => { const { tags } = globalThis.Lightview || {}; if (!tags) return null; return tags.input({ type: 'range', min: '0', max: '100', value: '50', class: 'diff-resizer', oninput: "this.parentElement.style.setProperty('--diff-offset', this.value + '%')", ...props }); }; const tags = globalThis.Lightview.tags; tags.Diff = Diff; tags['Diff.Item1'] = Diff.Item1; tags['Diff.Item2'] = Diff.Item2; tags['Diff.Resizer'] = Diff.Resizer; // Register as Custom Elements using customElementWrapper if (globalThis.LightviewX && typeof customElements !== 'undefined') { const { customElementWrapper } = globalThis.LightviewX; if (!customElements.get('lv-diff')) { customElements.define('lv-diff', customElementWrapper(Diff, { attributeMap: { aspectRatio: String } })); } if (!customElements.get('lv-diff-item1')) { customElements.define('lv-diff-item1', customElementWrapper(Diff.Item1, { attributeMap: { src: String, alt: String } })); } if (!customElements.get('lv-diff-item2')) { customElements.define('lv-diff-item2', customElementWrapper(Diff.Item2, { attributeMap: { src: String, alt: String } })); } if (!customElements.get('lv-diff-resizer')) { customElements.define('lv-diff-resizer', customElementWrapper(Diff.Resizer, {})); } } export default Diff;