### Install Solari Split-Flap Source: https://github.com/hardikpandya/solari-split-flap/blob/main/README.md Install the library using npm. This is the first step before using the display in your project. ```bash npm install solari-split-flap ``` -------------------------------- ### Cycle Through Quotes Source: https://github.com/hardikpandya/solari-split-flap/blob/main/index.html Shuffles an array of quotes and then repeatedly cycles through them, laying out and displaying each quote. Includes an initial delay before starting the cycle. ```javascript var shuffled = quotes.slice(); for (var si = shuffled.length - 1; si > 0; si--) { var sj = Math.floor(Math.random() * (si + 1)); var tmp = shuffled[si]; shuffled[si] = shuffled[sj]; shuffled[sj] = tmp; } var qIndex = 0; function cycle() { var quote = shuffled[qIndex % shuffled.length]; var result = layoutQuote(quote); displayQuote(result, function() { qIndex++; cycle(); }); } setTimeout(cycle, 800); ``` -------------------------------- ### Initialize SolariBoard with Vanilla JS Source: https://github.com/hardikpandya/solari-split-flap/blob/main/README.md Instantiate the SolariBoard in vanilla JavaScript. This requires an HTML element with the ID 'board' and specifies display dimensions and quotes. ```javascript import { SolariBoard } from 'solari-split-flap'; const board = new SolariBoard(document.getElementById('board'), { cols: 20, rows: 8, theme: 'ocean', quotes: [ ['HELLO WORLD', '', '@SOLARI'], ['STAY HUNGRY.', 'STAY FOOLISH.', '', '@STEWART BRAND'], ], }); board.start(); ``` -------------------------------- ### Sample Text Lines for Display (JavaScript) Source: https://github.com/hardikpandya/solari-split-flap/blob/main/themes.html An array containing sample text and author information to be displayed on the Solari split-flap boards. This data is used to populate the display rows. ```javascript var sampleLines = [ { text: 'SIMPLICITY IS', author: false }, { text: 'THE ULTIMATE', author: false }, { text: 'SOPHISTICATION.', author: false }, { text: '', author: false }, { text: 'LEONARDO DA VINCI', author: true } ]; ``` -------------------------------- ### Create Solari Theme Cards (JavaScript) Source: https://github.com/hardikpandya/solari-split-flap/blob/main/themes.html Dynamically creates and appends theme cards to the gallery based on the defined themes and sample lines. This script iterates through each theme, generates its corresponding colors, and constructs the HTML elements for the display. ```javascript var COLS = 18; var ROWS = 5; var gallery = document.getElementById('gallery'); themes.forEach(function(t) { var theme = generateTheme(t.hue, t.sat, t.mode); var card = document.createElement('div'); card.className = 'theme-card'; card.style.background = theme.bodyBg; var label = document.createElement('div'); label.className = 'theme-label'; label.textContent = t.name + ' (' + t.mode + ')'; label.style.background = theme.labelBg; label.style.color = theme.labelText; card.appendChild(label); var board = document.createElement('div'); board.className = 'theme-board'; board.style.background = theme.boardBg; var startRow = 0; for (var r = 0; r < ROWS; r++) { var row = document.createElement('div'); row.className = 'theme-row'; var lineData = sampleLines[r] || { text: '', author: false }; var text = lineData.text; var isAuthor = lineData.author; var color = isAuthor ? theme.author : theme.text; var pad = isAuthor ? Math.max(0, COLS - text.length) : 0; for (var c = 0; c < COLS; c++) { var ch = (c >= pad && c < pad + text.length) ? text[c - pad] : '\u00A0'; var cell = document.createElement('div'); ``` -------------------------------- ### Trigger Audio Initialization Source: https://github.com/hardikpandya/solari-split-flap/blob/main/index.html Ensures audio initialization is called upon the first user interaction (click or keydown). ```javascript document.addEventListener('click', function() { initAudio(); }, { once: true }); document.addEventListener('keydown', function() { initAudio(); }, { once: true }); ``` -------------------------------- ### Generate and Apply Custom Theme Source: https://github.com/hardikpandya/solari-split-flap/blob/main/README.md Create custom color themes using the `generateTheme` function and apply them with `applyTheme`. The function takes hue, saturation, and mode ('dark' or 'light') as arguments. ```javascript // generateTheme(hue, saturation, mode) // hue: 0-360, sat: 0-100, mode: 'dark' or 'light' var theme = generateTheme(155, 30, 'dark'); // mint dark applyTheme(theme); ``` -------------------------------- ### Initialize Audio Context Source: https://github.com/hardikpandya/solari-split-flap/blob/main/index.html Initializes the Web Audio API context for sound effects. This should be called once, ideally triggered by user interaction. ```javascript var audioCtx = null; var soundEnabled = false; function initAudio() { if (audioCtx) return; try { audioCtx = new (window.AudioContext || window.webkitAudioContext)(); soundEnabled = true; } catch(e) { soundEnabled = false; } } ``` -------------------------------- ### Theme Switching Event Listener Source: https://github.com/hardikpandya/solari-split-flap/blob/main/index.html Listens for the 't' key press to cycle through predefined themes and apply them to the display. This allows for dynamic theme changes. ```javascript var themeIndex = 0; document.addEventListener('keydown', function(e) { if (e.key === 't' || e.key === 'T') { themeIndex = (themeIndex + 1) % themes.length; var t = themes[themeIndex]; applyTheme(generateTheme(t.hue, t.sat, t.mode)); } }); ``` -------------------------------- ### Load Solari Split-Flap via CDN Source: https://github.com/hardikpandya/solari-split-flap/blob/main/README.md Include the Solari Split-Flap display in an HTML page using a CDN link. This method is suitable for quick integration without a build process. ```html
``` -------------------------------- ### Preset Themes Array Source: https://github.com/hardikpandya/solari-split-flap/blob/main/index.html An array of predefined theme objects, each specifying hue, saturation, and mode. These themes can be cycled through using keyboard input. ```javascript var themes = [ { name: 'classic', hue: 0, sat: 0, mode: 'dark' }, { name: 'mint', hue: 155, sat: 30, mode: 'dark' }, { name: 'ocean', hue: 210, sat: 35, mode: 'dark' }, { name: 'purple', hue: 270, sat: 30, mode: 'dark' }, { name: 'amber', hue: 35, sat: 40, mode: 'dark' }, { name: 'rose', hue: 345, sat: 25, mode: 'dark' }, { name: 'fog', hue: 0, sat: 0, mode: 'light' }, { name: 'sage', hue: 140, sat: 15, mode: 'light' }, { name: 'lavender', hue: 260, sat: 20, mode: 'light' }, ]; ``` -------------------------------- ### Generate Theme Colors (JavaScript) Source: https://github.com/hardikpandya/solari-split-flap/blob/main/themes.html Generates color palettes for different themes based on hue, saturation, and mode (dark/light). This function is used to define the visual appearance of the Solari display elements. ```javascript function hsl(h, s, l) { return 'hsl(' + h + ', ' + s + '%, ' + l + '%)'; } function generateTheme(hue, sat, mode) { if (mode === 'dark') { return { bodyBg: hsl(hue, sat, 6), boardBg: hsl(hue, sat, 10), flapTop: hsl(hue, sat, 18), flapBottom: hsl(hue, sat, 14), gapLine: hsl(hue, sat, 6), text: hsl(hue, Math.min(sat, 10), 94), author: sat === 0 ? hsl(45, 85, 60) : hsl(hue, Math.max(sat, 50), 65), labelBg: 'rgba(255,255,255,0.1)', labelText: hsl(hue, Math.min(sat, 10), 80) }; } else { return { bodyBg: hsl(hue, sat, 95), boardBg: hsl(hue, sat, 88), flapTop: hsl(hue, sat, 82), flapBottom: hsl(hue, sat, 76), gapLine: hsl(hue, sat, 70), text: hsl(hue, sat, 10), author: sat === 0 ? hsl(45, 85, 42) : hsl(hue, Math.max(sat, 40), 35), labelBg: 'rgba(0,0,0,0.08)', labelText: hsl(hue, sat, 30) }; } } ``` -------------------------------- ### Display Quote Animation and Styling Source: https://github.com/hardikpandya/solari-split-flap/blob/main/index.html Applies character changes to the display grid, schedules drum animations, and applies 'author-cell' classes based on the layout result. It calculates the maximum animation time to schedule the callback. ```javascript function displayQuote(result, callback) { var grid = result.grid; var authorRows = result.authorRows; var maxDrumTime = 0; for (var r = 0; r < ROWS; r++) { for (var c = 0; c < COLS; c++) { var idx = r * COLS + c; var target = grid[r][c]; var delay = (r * COLS + c) * CHAR_DELAY; if (currentChars[idx] !== target) { var drumTime = drumToChar(idx, target, delay); if (delay + drumTime > maxDrumTime) maxDrumTime = delay + drumTime; } (function(cellIdx, row, cellDelay) { var tid = setTimeout(function() { if (authorRows[row]) { cells[cellIdx].classList.add('author-cell'); } else { cells[cellIdx].classList.remove('author-cell'); } }, cellDelay + FLIP_MS + 50); cellTimers[cellIdx].push(tid); })(idx, r, delay); } } setTimeout(callback, maxDrumTime + HOLD_MS); } ``` -------------------------------- ### Base and Theme Styles for Split-Flap Display Source: https://github.com/hardikpandya/solari-split-flap/blob/main/index.html Defines the reset, theme variables, and base styles for the split-flap board and its elements. Includes dark theme defaults and transitions for theme changes. ```css *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; } :root { /* Theme: dark (default) — hue 0, sat 0%, dark mode */ --sf-body-bg: #111; --sf-board-bg: #1a1a1a; --sf-flap-top: #2a2a2a; --sf-flap-bottom: #222; --sf-gap-line: #111; --sf-text: #f0f0f0; --sf-author: #f5c542; } body { min-height: 100vh; display: flex; align-items: center; justify-content: center; flex-direction: column; background: var(--sf-body-bg); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; transition: background 0.4s ease; } .split-flap-board { display: flex; flex-direction: column; gap: 3px; padding: 2rem; background: var(--sf-board-bg); border-radius: 12px; width: fit-content; margin: 2rem auto; overflow: hidden; transition: background 0.4s ease; } .split-flap-row { display: flex; gap: 3px; } .split-flap-cell { width: 28px; height: 40px; perspective: 200px; } .flap-display { position: relative; width: 100%; height: 100%; font-family: "SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", "Courier New", monospace; font-size: 1.1rem; font-weight: bold; color: var(--sf-text); text-align: center; transition: color 0.4s ease; } .flap-top { position: absolute; top: 0; left: 0; width: 100%; height: calc(50% - 0.25px); background: var(--sf-flap-top); border-radius: 4px 4px 0 0; clip-path: polygon(0 0, 100% 0, 100% calc(100% - 3px), calc(100% - 3px) 100%, 3px 100%, 0 calc(100% - 3px)); overflow: hidden; z-index: 1; transition: background 0.4s ease; } .flap-top .flap-char { position: absolute; top: 0; left: 0; width: 100%; height: 200%; display: flex; align-items: center; justify-content: center; line-height: 1; } .flap-bottom { position: absolute; bottom: 0; left: 0; width: 100%; height: calc(50% - 0.25px); background: var(--sf-flap-bottom); border-radius: 0 0 4px 4px; clip-path: polygon(3px 0, calc(100% - 3px) 0, 100% 3px, 100% 100%, 0 100%, 0 3px); overflow: hidden; z-index: 1; transition: background 0.4s ease; } .flap-bottom .flap-char { position: absolute; bottom: 0; left: 0; width: 100%; height: 200%; display: flex; align-items: center; justify-content: center; line-height: 1; } /* Gap line removed — board bg gap between top/bottom halves provides the split */ .split-flap-cell.author-cell .flap-top .flap-char, .split-flap-cell.author-cell .flap-bottom .flap-char, .split-flap-cell.author-cell .flap-flip-front .flap-char, .split-flap-cell.author-cell .flap-flip-back .flap-char { color: var(--sf-author); } /* Theme switcher hint */ .theme-hint { position: fixed; bottom: 1.5rem; right: 1.5rem; font-size: 0.7rem; color: var(--sf-text); opacity: 0.3; font-family: "SF Mono", "Fira Code", monospace; text-transform: uppercase; letter-spacing: 0.08em; pointer-events: none; transition: color 0.4s ease, opacity 0.4s ease; } .theme-hint .key { display: inline-block; border: 1px solid; border-radius: 3px; padding: 0.1em 0.35em; margin: 0 0.15em; opacity: 0.6; } ``` -------------------------------- ### Solari Theme Definitions (JavaScript) Source: https://github.com/hardikpandya/solari-split-flap/blob/main/themes.html An array defining the properties for various Solari themes, including name, hue, saturation, and color mode. These themes are used to generate the color palettes. ```javascript var themes = [ { name: 'classic', hue: 0, sat: 0, mode: 'dark' }, { name: 'mint', hue: 155, sat: 30, mode: 'dark' }, { name: 'ocean', hue: 210, sat: 35, mode: 'dark' }, { name: 'purple', hue: 270, sat: 30, mode: 'dark' }, { name: 'amber', hue: 35, sat: 40, mode: 'dark' }, { name: 'rose', hue: 345, sat: 25, mode: 'dark' }, { name: 'fog', hue: 0, sat: 0, mode: 'light' }, { name: 'sage', hue: 140, sat: 15, mode: 'light' }, { name: 'lavender', hue: 260, sat: 20, mode: 'light' }, ]; ``` -------------------------------- ### Display Configuration Constants Source: https://github.com/hardikpandya/solari-split-flap/blob/main/index.html Defines constants for the split-flap display, including the number of columns and rows, flap animation duration, character delay for cascading effects, and the hold duration for displaying quotes. ```javascript var COLS = 20; var ROWS = 8; var FLIP_MS = 150; // single flap animation duration var CHAR_DELAY = 50; // ms stagger between cells in cascade var HOLD_MS = 5000; // hold finished quote before next ``` -------------------------------- ### Integrate Solari Split-Flap with React Source: https://github.com/hardikpandya/solari-split-flap/blob/main/README.md Use the Solari component for React applications. This component simplifies integration by accepting props for configuration. ```jsx import { Solari } from 'solari-split-flap/react'; function App() { return (