aboutsummaryrefslogtreecommitdiff
path: root/scripts/theme-studio/app.js
Commit message (Collapse)AuthorAgeFilesLines
* refactor(theme-studio): fold the box control into mkLineStyleControlCraig Jennings26 hours1-17/+10
| | | | mkBoxControl duplicated the whole cluster/dropdown/paint/syncLocked machinery that mkLineStyleControl already provides for underline/strike/overline; it differed only in that its state object carries a width. I gave mkLineStyleControl an optional toState builder and reduced mkBoxControl to a wrapper that supplies it. The clear/reset tier functions already delegate their shared loop to clearUnlockedRows, so they were left as is. The buildTable/buildUITable/buildPkgTable skeleton merge is deferred: their shared control/expander/detail-editor/CSS machinery is now all extracted, and what remains is genuine per-tier column divergence that the browser gates pin by exact cell position.
* refactor(theme-studio): extract per-package previews into previews.jsCraig Jennings26 hours1-459/+3
| | | | The ~28 renderXxxPreview functions plus ofs/os/previewLines were ~460 lines of bespoke sample content sitting in the middle of the controller. I moved them to a new previews.js, spliced into the page through a PREVIEWS_J token the same way the other inlined libs are, and left the PACKAGE_PREVIEWS registry and dispatcher in app.js. app.js drops from 1233 to 759 lines, and the sample data now lives apart from the table/control machinery.
* refactor(theme-studio): unify the face CSS builders in app-coreCraig Jennings26 hours1-23/+6
| | | | syntaxStyle, uiCss, and ofs each assembled the same color/background/weight/style/text-decoration/box-shadow string by hand, differing only in how they resolved fg/bg and whether they added a font-size. I promoted one faceCss(face, fg, bg, opts) plus cssWeight, boxCss, and a faceDecoration helper into app-core (all pure, no DOM), and reduced the three builders to thin wrappers that resolve fg/bg and call it. styleEx and paintUI now use the promoted cssWeight/boxCss too. udeco keeps its own untrimmed decoration form, so it stays in app.js.
* refactor(theme-studio): polish the expander (underline inside, dynamic ↵Craig Jennings35 hours1-7/+20
| | | | | | | | | | | | | | colspan, nd flag) Three cleanups to the per-row expander from 3B-2. The underline control moves from the in-row style cell into the expander, next to overline. The row keeps weight, slant, and strike inline, so the style cell drops from three wrapped rows to two and the table reads flatter. mkExpander no longer hardcodes each table's colspan. tableColCount reads the column count from the table's header, so a detail row spans correctly even if a column is added later. A collapsed expander now flags itself when it hides an attribute that differs from the face's default, so a non-default value is never invisible. overflowNonDefault (app-core.js, unit-tested) compares the expander's attributes against the default. The toggle re-checks after every edit and gets the gold marker when any differ. faceBoxNonDefaults drops underline from the in-row style box in the same move, since underline is now the expander's concern. The #expandtest gate covers the underline control in its new home, its wavy write, and the flag appearing then clearing. Full suite green: Python 59, Node 201, ERT 41, plus the browser hash gates.
* feat(theme-studio): add a per-row expander for the overflow face attributesCraig Jennings35 hours1-10/+60
| | | | | | | | | | Each row in the syntax, UI, and package tables gets a "more" toggle that reveals a detail row beneath it, holding the attributes that don't fit a column: distant-fg, family, overline, inverse, and extend. The syntax and UI tables also get inherit and height there, since they have no inline column for those. Packages already do, so their expander leaves them out. One mkDetailEditor builds the editor and one mkExpander wires the toggle plus the hidden detail row, both shared across the three tables. The detail controls join the row's lock cell, so locking a row disables them too. Detail rows ride along when a table is sorted: applyTableSort now sorts only the main rows and re-attaches each detail row right after its parent (matched by data-detail-for), so a sort never separates the pair. The new #expandtest browser gate covers the toggle, the field set, the model writes, and the package expander dropping inherit/height. This is the last editor piece for the face-attribute work. Every attribute the model and emitter support is now reachable from the UI. Full suite green: Python 59, Node 198, ERT 41, plus the browser hash gates.
* feat(theme-studio): replace the style toggles with ↵Craig Jennings37 hours1-18/+44
| | | | | | | | | | | | weight/slant/underline/strike controls The B/I/U/S toggle buttons in the syntax, UI, and package tables become a weight selector (light/normal/medium/semibold/bold/heavy), a slant selector (normal/italic/oblique), and box-like underline and strike controls. The underline control sets line or wave plus a color, and the strike control sets a color. A face can now reach the full weight range and a wavy or colored underline, not just bold and italic on-off. All four controls come from one mkStyleControls helper shared across the three tables, and underline and strike share mkLineStyleControl (the box-control pattern, parameterized for a styled line vs a plain toggle). With the real controls in place I dropped the transitional legacyStyleOn/toggleLegacyStyle shim and its tests. The overflow attributes (distant-fg, family, overline, inverse, extend, and inherit/height for ui and syntax) move into a per-row expander next. Verified by screenshot and the browser style gate, which now drives a weight-select change and an underline-wave click through the model. Full suite green: Python 59, Node 198, ERT 41, plus the browser hash gates.
* refactor(theme-studio): cut the face model over to weight/slant/objectsCraig Jennings37 hours1-16/+20
| | | | | | | | | | I replaced the legacy bold/italic/underline/strike booleans with the final model shape across both sides of the tool. weight (light/normal/medium/semibold/bold/heavy) and slant (normal/italic/oblique) replace the bold/italic flags, underline becomes {style: line|wave, color}, strike becomes {color}, and null means unset. A single migration converts a legacy face on the way in, mirrored as migrateLegacyFace in app-core.js and migrate_legacy in face_specs.py so the JS and Python models can't drift. It runs on import (applyImported, mergePackagesInto) and on every seed that face_spec touches. The captured-snapshot seed (default_faces.seed) narrows the same way it did before. Only bold and italic survive, as weight "bold" and slant "italic", so the generated themes stay byte-identical. The B/I/U/S toggle buttons keep working through a transitional bridge (legacyStyleOn / toggleLegacyStyle). The weight/slant dropdowns and underline/strike controls that replace them land next. The live previews read the new shape, with a weight name mapped to a numeric CSS font-weight. The cutover is proven emit-neutral two ways. An ERT test asserts the migrated shapes emit the same attributes as the legacy booleans, and deep-migrating every face in dupre, distinguished, sterling, now, theme, and WIP then running build-theme yields byte-identical output. Full suite green: Python 59, Node 200, ERT 41, plus the browser hash gates.
* feat(theme-studio): widen the face model with the additive attributesCraig Jennings38 hours1-3/+3
| | | | | | | | | | This is Phase 2 of the face-attribute expansion. The model now carries distant-fg, family, overline, inverse, and extend in final shape across all three tiers, and inherit and height are no longer package-only (a ui or syntax face can set them too). I kept bold/italic/underline/strike as the legacy booleans for now. The cutover to weight/slant and the underline/strike object forms lands in the next phase with the editor widgets that force it, so the representation and the controls that drive it move together. face_specs.py holds the canonical defaults. In app-core.js, normalizePkgFace and packagesForExport carry and emit the new attrs: distant-fg resolves through the palette like fg/bg, and each attr exports only when set, so existing presets re-export unchanged. app.js syntaxBlank, uiFaceBlank, and seedFace match the shape. Nothing changed shape, so dupre, distinguished, sterling, now, theme, and WIP all emit byte-identical themes. make check green: Python 58, Node 193, ERT 40.
* feat(theme-studio): add mode-line-highlight as an editable faceCraig Jennings40 hours1-2/+3
| | | | | | | | The mode-line hover box (the raised bevel on clickable mode-line segments) came from mode-line-highlight, a face the studio never managed, so it fell through to Emacs's stock released-button default with no way to change it. I added it to the generated UI face list, between mode-line and mode-line-inactive. The row and box control are already generic over that list, so they appear automatically. build-theme.el's UI emission is generic too, so the elisp side needs nothing. The face isn't in the captured Emacs snapshot, so apply_hover_box_default seeds its box to the raised default in both build_uimap branches. That matches current behavior and leaves the user free to flatten or recolor it. The mock frame previews the hover by wrapping a mode-line segment in the face.
* fix(theme-studio): open the palette collapsed to base colorsCraig Jennings4 days1-0/+1
| | | | The studio opened with every column's span tints expanded, so the first view was crowded with colors the user hadn't asked to see. I set paletteShowFull to false in initApp, so the palette opens showing one tile per column and the existing arrow control expands the spans. The flip lives in the boot path rather than the module default, so the palette gates keep their full-palette baseline. The two that assert span tiles (#counttest, #paltoggletest) now opt into full mode explicitly. A new #paldefaulttest gate asserts the opening collapsed state.
* feat(theme-studio): add gnus as a view packageCraig Jennings4 days1-1/+30
| | | | mu4e renders the open message with gnus, so the article-view headers, quote levels, signature, and inline emphasis are all gnus faces, not mu4e ones. gnus ships them as bright greens on a dark background, and the theme had no way to reach them. I added gnus as a bespoke view package: the article-view face set in face_data.py with palette seeds that mirror the mu4e header treatment, a realistic preview (header block, emphasized body, an 11-level quoted reply chain, signature), and a #gnustest gate that asserts every emitted face is a real gnus face. Theming and exporting gnus in the studio retires the green in the live view.
* fix(theme-studio): redesign the mu4e preview as a realistic headers listCraig Jennings4 days1-15/+25
| | | | The old mu4e preview was cramped and referenced faces that aren't in the mu4e inventory (mu4e-moved-face, mu4e-attach-number-face, mu4e-cited-1..7, mu4e-compose-header-face), so those rendered unthemed. I rebuilt it as a realistic mu4e screen: a status bar, a column header, and one row per message state (unread, replied, flagged, forwarded, draft, trashed, related) with the current line on the highlight background, then a compact message view and the compose separator. It now exercises all 27 mu4e inventory faces and only those. The new #mupreviewtest gate asserts every data-face is a real mu4e face.
* feat(theme-studio): realistic README preview for markdown-modeCraig Jennings4 days1-1/+40
| | | | markdown-mode fell back to the generic preview (bare face names). I added renderMarkdownPreview, a realistic README that exercises the markdown faces in context: front matter, headers, bold/italic, inline and fenced code, links, lists and checkboxes, a blockquote with a footnote, a table, strikethrough, highlight, math, and inline HTML. A PREVIEW_KEYS map in app_inventory routes markdown-mode to the renderer, and the #mdtest gate checks every data-face it emits is a real markdown face.
* feat(theme-studio): prev/next arrows to step the view dropdownCraig Jennings4 days1-0/+7
| | | | I added left and right arrow buttons flanking the view dropdown. They step the selection to the previous or next item and re-render the faces table and preview, so you can walk the list without reopening the dropdown. A pure stepViewIndex helper clamps the index to the option range, no wrap. stepView sets the selection and calls onViewChange.
* feat(theme-studio): move the contrast verdict into a hoverCraig Jennings4 days1-1/+1
| | | | The contrast column showed "5.4 PASS". The number's color already encodes the tier (green AAA, grey AA, red fail), so the PASS/FAIL word was redundant. I dropped it and put the WCAG meaning in the cell's hover via a pure contrastTitle helper. crHtml now renders just the colored number. verdictFor stays for the covered-overlay worst-case readout, which is unchanged.
* feat(theme-studio): mark per-face setting boxes that differ from defaultCraig Jennings4 days1-1/+8
| | | | A non-default height looks identical to the default in the size input, so a stray 1.1 hides in plain sight. I added a small gold corner flag on any per-face setting cell (fg, bg, style, inherit, size, box) whose value differs from the face's seed default. A pure faceBoxNonDefaults helper computes the per-box flags. buildPkgTable resolves fg/bg to hex before comparing, so a palette-name-vs-hex difference doesn't read as a change.
* feat(theme-studio): alphabetize packages in the assignment dropdownCraig Jennings4 days1-3/+3
| | | | The assignment-view dropdown listed package faces in APPS build order (bespoke apps first, then inventory). generate.py builds them that way, so the list wasn't alphabetical. I added a pure appViewKeysSorted helper that orders the app keys by display label, and buildViewSel uses it. The @code and @ui editor entries above the divider are unchanged.
* refactor(theme-studio): extract a groundPair() helperCraig Jennings5 days1-7/+11
| | | | The literal {bg:MAP['bg'],fg:MAP['p']} repeated 32 times across app.js, palette-actions.js, and the browser gates. Replace it with a groundPair() helper. Named groundPair, not ground, to avoid colliding with the local ground bindings destructured from columnsFromPalette. No behavior change; node tests and browser gates are the safety net.
* feat(theme-studio): 2D gallery color picker for the assignment dropdownsCraig Jennings5 days1-7/+23
| | | | | | | | | | - The color dropdown opens a grid, not a long list. - The grid mirrors the palette: ground strip, then a row per family. - Members run dark to light, with the current color outlined. - A default chip clears the assignment. - A (gone) cell shows a color no longer in the palette. - The trigger and step buttons stay the same. - All three tiers share the one dropdown.
* feat(theme-studio): flag gone color assignments with a borderCraig Jennings5 days1-1/+1
| | | | An assignment pointing at a color no longer in the palette showed only as "(gone)" on hover. I added a distinct solid border to the swatch whenever its current value resolves to "(gone)", so a broken assignment reads at a glance. The solid red outline is set apart from the dashed unused-tile flag, keeping the two palette-state cues distinguishable. A #gonetest gate covers the flagged and unflagged cases.
* refactor(theme-studio): rename preview samples and match cluster button sizesCraig Jennings5 days1-6/+6
| | | | | | I renamed the preview personas to Christine (was Alice) and Evan (was Eve), trimming the mu4e header spacing so those rows stay aligned. I shrank the style cluster buttons from 26x24 to the 17x15 box-button size, so the two clusters match and the assignment row returns to roughly its pre-cluster height.
* refactor(theme-studio): drop dead bindings and CSS left by the cluster workCraig Jennings5 days1-1/+1
|
* feat(theme-studio): reflow the B/I/U/S style buttons into a 2x2 clusterCraig Jennings5 days1-3/+3
| | | | | | The four style buttons sat in a horizontal row, the widest part of the style column. I wrapped them in the same 2x2 grid the box control uses, so they form a square (still multi-toggle, since bold and italic combine). The column narrows to roughly half its width across all three tiers. A #styletest gate confirms the four buttons live in a .stylecluster.
* feat(theme-studio): compact the box control into a 2x2 button clusterCraig Jennings5 days1-8/+18
| | | | | | | | The box control was a wide select plus a color swatch, pinning the box column at 166px. I replaced the select with a 2x2 cluster of radio buttons for the four styles: blank (no box), □ (line), ▼ (pressed), ▲ (raised). The color swatch now shows only while a box style is active, so the no-box case stays narrow. The column drops to 76px across all three tiers. A #boxtest gate covers the cluster: four buttons, radio selection, and the swatch hiding when no box is set. #beveltest now drives the style through the cluster button instead of the removed select. The same cluster shape sets up the B/I/U/S style column next.
* refactor(theme-studio): drop the per-row reset column from package facesCraig Jennings5 days1-4/+3
| | | | | | Package faces was the only tier with a per-row reset button, in its own column. The syntax and ui tiers rely on the bulk reset alone, and the column cost horizontal space the table needs. I removed the per-row cell and its header, so the bulk reset (next to "lock all") is the single reset path now, matching the other tiers. A #viewtest assertion confirms the package rows carry no per-row reset button. The two weren't equivalent: the per-row button reset one face to its default, the bulk reset clears every unlocked face in the app. Losing single-face reset is the accepted tradeoff.
* refactor(theme-studio): collapse assignment views into one dropdown panelCraig Jennings5 days1-3/+19
| | | | | | The assignment area was three stacked sections (color/code, ui faces, package faces), and package faces carried its own application selector. I merged them into one panel driven by a single dropdown: color/code assignments, ui faces, then a non-selectable "package faces" optgroup holding every app in order. Picking an entry swaps the left table and right preview, so only one view shows at a time. curApp now reads the selected app from that dropdown, and the old appsel is gone. A #viewtest browser gate locks in the dropdown order, the optgroup, and the one-view-at-a-time switching.
* chore(theme-studio): label highlighted preview line (process highlights)Craig Jennings5 days1-1/+1
|
* feat(theme-studio): add org-faces app for agenda keyword and priority colorsCraig Jennings5 days1-1/+28
| | | | Surface the org-faces-config.el header-row faces as their own theme-studio app, placed beside elfeed and mu4e so it reads as a custom layer rather than built-in org. The seed mirrors the module defaults exactly across all 28 faces (10 keywords, 4 priorities, and their dim variants), so the editor opens on the live colors. The preview shows a focused agenda block and an auto-dim block covering every face.
* refactor(theme-studio): extract the shared package-preview wrapperCraig Jennings6 days1-20/+23
| | | | The 20 line-based renderXxxPreview functions each ended with a byte-identical monospace-pre wrapper. They now build their L array and return previewLines(L), so the wrapper lives in one place and can't drift across the family.
* feat(theme-studio): auto-dim split previewCraig Jennings6 days1-0/+40
| | | | | | | | auto-dim-other-buffers is a package face, not a theme face, so build-inventory.el (it scans only elpa/straight packages) never listed it and the studio couldn't theme it. This adds it as a bespoke app. The preview is a vertical split: the focused window on the left in real syntax colors, the same code on the right collapsed to the single auto-dim-other-buffers face, the way Emacs renders a non-selected window. Both panes follow the language selector. A trailing row shows auto-dim-other-buffers-hide, whose foreground matches the background so it vanishes when dimmed. A #autodimtest gate covers the split, the uniform recolor, and language sync.
* fix(theme-studio): keep dropdown color names legibleCraig Jennings6 days1-1/+1
| | | | | | The color-picker popup colored each row's name and hex for contrast against the swatch, but the rows sit on the popup's fixed dark background. A mid or dark swatch (the blues past blue-1) got near-black text that vanished on the dark popup. The text now inherits the popup foreground for every real palette color. Only the solid "default" row, whose background is the color itself, still contrasts against its own fill. I moved the decision into dropdownRowTextColor with unit coverage, including a dark-swatch regression case.
* feat(theme-studio): palette generator and preview fidelityCraig Jennings6 days1-35/+82
| | | | | | | | | | Two strands land together because the generated theme-studio.html bundles every source file into one page and can't be split cleanly. The palette generator is a preview-first panel: palette-generator-core.js plans the palette and palette-generator-ui.js draws it. Generated colors stay inspectable and tunable through the existing selector, and committing one creates a normal base column. It adds source-mode and scheme controls, a configurable accent count, and color names from color-names.json. For preview fidelity, syntax and UI colors now resolve through the real Emacs inherit chains, so the preview matches how Emacs renders the theme. resolveSyntaxFg pins dec to ty (Emacs has no decorator face) and otherwise follows comment-delimiter to comment, doc to string, property to variable, function-call to function-name. resolveUiAttr walks mode-line-inactive to mode-line and line-number-current-line to line-number. The decorator label now reads "decorator to type" to match the type face Emacs uses for it. Design recorded in the two theme-studio specs under docs/.
* Update theme studio palette workflowCraig Jennings6 days1-62/+102
|
* Add theme studio box color controlsCraig Jennings7 days1-13/+19
|
* Shorten theme studio reset erase labelsCraig Jennings7 days1-7/+7
|
* Clarify theme studio reset and erase actionsCraig Jennings7 days1-5/+15
|
* Add theme studio face color step arrowsCraig Jennings7 days1-4/+19
|
* Preview selected theme studio chip while pickingCraig Jennings7 days1-6/+7
|
* Remove theme studio save buttonCraig Jennings7 days1-12/+4
|
* Fix theme studio ground endpoint editCraig Jennings7 days1-3/+4
|
* Refactor theme studio palette testsCraig Jennings7 days1-644/+5
|
* Add theme studio palette clear and lock togglesCraig Jennings7 days1-3/+52
|
* Fix theme studio ground column orderCraig Jennings7 days1-6/+17
|
* Fix theme studio bg-prefixed span inferenceCraig Jennings7 days1-3/+3
|
* Fix theme studio style button stateCraig Jennings7 days1-1/+13
|
* Fix theme studio bg-like imported colorsCraig Jennings7 days1-14/+21
|
* Add theme studio column selection and reorder controlsCraig Jennings7 days1-4/+54
|
* Set theme studio default picker colorCraig Jennings7 days1-3/+4
|
* Pin theme studio preview links and column exportsCraig Jennings7 days1-4/+28
|
* Rename theme studio column browser gateCraig Jennings7 days1-4/+4
|