Repository navigation
feat(web): Choy UI kit rewrite and Element Plus retirement - #514
Conversation
* ci(pr-gate): also run on PRs targeting feat/choy-ui-kit Stacked kit PRs merge into the integration branch first; without this base in the pull_request filter, PR Gate never starts (only main matched). * ci(pr-gate): run on every pull request base Drop the pull_request.branches allowlist so stacked PRs into integration branches get the same discover-routed gate as PRs into main.
* feat(choy_ui): scaffold isolation kit with Tailwind Go gate Add installable choy_ui module (tokens, gallery shell, /web/__choy_gallery), wire tailwind-go generate into web builds, and fold dialect/candidate hashes into the web input digest so skip stays stable under the 500ms budget. * chore(choy_ui): stop tracking Tailwind generated CSS Keep choy-tailwind.generated.css as a web-build artifact only so class churn does not pollute git; EnsureChoyTailwindCSS still writes it before bundle. * chore: re-sync PR #430 to trigger PR Gate * ci(pr-gate): run gate on every pull request (#431) * ci(pr-gate): also run on PRs targeting feat/choy-ui-kit Stacked kit PRs merge into the integration branch first; without this base in the pull_request filter, PR Gate never starts (only main matched). * ci(pr-gate): run on every pull request base Drop the pull_request.branches allowlist so stacked PRs into integration branches get the same discover-routed gate as PRs into main. * fix(choy_ui): address PR #430 review on isolation and Tailwind scan Drop multi-line TS/JS scanner leaks from generated CSS, scope gallery theme/density to .choy-gallery-root, tighten digest/write/stat handling, and keep route registration idempotent. * fix(choy_ui): address PR suggestions and raise Tailwind patch coverage Adopt Sync-before-rename atomic writes, rename the directory-theme test, and assert theme-mapped utilities. Expand unit coverage so the PR1 Tailwind/digest/webBuilder hook patch lines are fully exercised. * fix(choy_ui): scope Tailwind theme/utilities and harden generate checks Propagate LoadCSS errors, emit ThemeCSS aliases with utilities, scope both under .choy-gallery-root for isolation, and fail tests if preflight reset CSS appears in the generated output. * fix(choy_ui): harden CSS scoping and hit 100% Tailwind patch coverage Scope nested @media utilities, split selectors only at top level, skip quoted braces/comments, guard AppLayout, fail incomplete kits loudly, and make chmod permission tests root-tolerant. * fix(choy_ui): scope past bare at-rules and harden theme/tests Copy block-less @-rules through before brace scanning, normalize all :root/:host spellings, reuse the generated CSS name constant, rename the shadowed setupApp param, and make chmod-based permission tests root-tolerant. * fix(choy_ui): skip leading CSS comments and harden write-failure tests Emit leading /* */ before selector scoping, force rename failure when the generated CSS path is a directory, and warn when AppLayout is missing. * fix(choy_ui): restore router if-parens and align Tailwind digest guards Repair a Go-style if that broke typecheck, and mirror EnsureChoyTailwindCSS path checks in TailwindInputDigest for non-dir web/ and dialect paths. * test(choy_ui): cover Tailwind digest path guards and no-brace CSS Exercise missing-dialect and permission-denied digest paths, plus selector fragments without a block, so patch coverage on tailwind_generate.go is 100%. * fix(choy_ui): scope unknown at-rules and spare functional :host Default-scope nested selectors in unrecognized block at-rules while keeping declaration bodies verbatim, and rebind only standalone :root/:host tokens. * fix(choy_ui): scope tokens to gallery and tighten Tailwind digests Move light tokens off :root onto .choy-gallery-root, exclude only the kit's generated CSS from source walks, and include the tailwind-go module version in the web input digest schema (v7). * fix(choy_ui): quote-aware bare at-rules and cover digest version helper Scan block-less @-rule terminators with quote/paren awareness, raise the candidate length cap for long arbitrary utilities, and unit-test the injectable tailwind-go version reader for 100% digest patch coverage. * fix(choy_ui): match relative kit CSS paths and harden CSS helpers Recognize root-relative choy_ui/web generated CSS in digest exclusion, close temp files before cleanup on write failure, and skip commas inside selector comments when splitting. * fix(choy_ui): drop empty selectors and honor go.mod replaces Omit empty slots from scoped selector lists, skip comments when finding bare at-rule terminators, and prefer replace version/path for the tailwind-go digest stamp. * fix(choy_ui): rebind utility :root/:host and tighten dialect checks Stamp replace as path@version, map bare :root/:host onto the gallery scope in utility lists, error when theme.css is a directory, and add SPDX to theme.css. * fix(choy_ui): tighten :root/:host boundaries and log budget overruns Reject identifier continuations when rebinding theme selectors, add SPDX headers to tokens/policy CSS, and warn when Tailwind generation exceeds the soft wall-clock budget. * fix(choy_ui): reject empty Tailwind output and stamp engine in header Refuse to write blank generated CSS, record the tailwind-go version in the file header, and use t.Skip for permission probes that cannot run as root. * test(choy_ui): cover Tailwind soft-budget warn path Inject ensureChoyTailwindCSS so BuildCtx can exercise the over-budget Warn log without waiting on a slow generate. * fix(choy_ui): align Tailwind scan extensions with digest sources Scan .mts/.cts/.mjs/.cjs for class candidates, fail digest when theme.css is a directory (same as Ensure), and assert engine bumps invalidate digests. * fix(choy_ui): harden at-rule open-brace scan and digest helpers Skip braces inside prelude comments/quotes when scoping nested utilities, guard nil BuildInfo, and lock choy_ui_extra out of kit CSS exclusion. * fix(choy_ui): tolerate vanished files during Tailwind candidate scan Skip NotExist between WalkDir and ReadFile instead of aborting the build, matching hashFile's missing-input behavior.
* feat(choy_ui): PR2 L2 primitives, Reka peers, and domain import bans Vendor first-batch ui/* with cn() and VENDOR.json, pin reka-ui/lucide peers, expand the gallery control matrix, and fail typecheck on forbidden domain imports of ui/*, reka-ui, @unovis/*, and kit deep paths. * refactor(choy_ui): nest L2 primitives under components/vendor/ui Make the vendored shadcn tree obvious at the path level, update Gallery imports and cn() relatives, extend forbidden-import matching, and point PR-Agent/Codecov/CodeQL ignores at the new location. * chore(choy_ui): keep vendor/ui cutover-ready for web merge Use module-agnostic ignore globs, document the stable components/vendor/ui layout, and structure kit-host exemption so only choy_ui is exempt until the kit moves under modules/web. * chore: ignore vendor/ui in CodeRabbit and Sourcery reviews Exclude the module-agnostic L2 vendor tree from bot review noise, matching PR-Agent/Codecov/CodeQL filters and surviving the choy_ui → web cutover. * fix(choy_ui): address PR #432 review on policy scan and gallery Harden forbidden UI import scanning (Vue line offsets, re-exports, JSX virtual paths, missing roots) and fix gallery portal token scope plus a few clear L2 bugs called out in review. * ci: let CodeRabbit auto-review PRs to any base branch Default auto_review only covers main; stacked bases like feat/choy-ui-kit were skipped. Match all targets with base_branches: [".*"]. * fix(choy_ui): harden policy scan from review and hit 100% coverage Accept PR-Agent items on HTML-comment scripts, declaration skips, virtual-path uniqueness, type-only alignment, gallery host theme restore, and typecheck web Stat errors; cover forbidden_ui_* and TypecheckApp web gate at 100%. * fix(policy): skip empty web sources and harden re-export scan Empty .ts under web/ no longer fails typecheck; wildcard re-exports fall back to the parent ModuleSpecPath; add disk coverage and SPDX on CodeRabbit/Sourcery configs. * fix(policy): tighten Vue script extraction and gallery color-scheme Only blank HTML comments that embed <script>, require line-anchored </script> so string literals cannot hide imports, keep color-scheme on .choy-gallery-root, and cover type-only re-exports on disk. * fix(choy_ui): harden web scan skips and portal dark color-scheme Guard nil parse results, skip web/public and coverage trees, pin reka-ui to the vendored 2.10.4 snapshot, and apply color-scheme: dark on the html token scope so Reka portals match gallery dark mode. * fix(choy_ui): dedupe import violations and harden Vue/script gates Guard gallery theme restore without capture, dedupe per-line ban noise, use RE2-safe script close matching for compact SFCs, align Input v-model to string, pin lucide, and run the web import gate before type-asset prep. * test(policy): cover violation sort by rule for dedupe path * test(policy): cover SpecText sort when columns collide * fix(choy_ui): CRLF-safe Vue script scan and toast duration ownership Handle CRLF SFCs and quoted script attrs with '>', trim backtick specifiers, let Reka ToastRoot own duration, widen gallery checkbox model typing, and avoid clobbering host theme on unmount. * test(policy): assert backtick import specs via appendForbiddenUiSpec * fix(choy_ui): tighten kit bans, SFC close tags, and toast duration zero Allow </script > whitespace, ban bare choy_ui package imports, map toast duration 0 to Infinity, fix decorative Separator roles, keep vendor/ui in CodeQL, and replace hand-rolled itoa / fmt.Errorf with stdlib helpers. * fix(choy_ui): same-line Vue scripts, toast clear, and small a11y fixes Rewind after script matches that consume a trailing '<', clear the toast store on Toaster unmount, gate disabled to real buttons, omit :0 columns in ban errors, and add SPDX fields on VENDOR.json. * fix(choy_ui): full scan coverage, indent-safe scripts, toast timer hygiene - Drop unreachable Vue script-scan stall branches so patch coverage is 100%. - Preserve first-line script indentation when extracting SFC bodies. - Track toast removal timers and clear them in clearToasts. - Narrow review/coverage ignores to vendored *.vue (Sourcery stays dir-wide). * fix(policy): fail closed when Vue script blocks fail to parse Refuse to skip .vue files that still contain a real <script> tag after comment masking but yield no captured blocks, so the kit import ban cannot fail open on awkward close-tag shapes.
* feat(choy_ui): PR3 L1 shells, FormView skeleton, and DogfoodLogin Add public ChoyLayout/Page/Card/Grid/Tabs/Button/Message and a chrome-only ChoyFormView, plus gallery coverage and a dogfood login route for button and toast smoke. * fix(choy_ui): harden L1 page IO, tabs selection, and dogfood styles Forward ChoyPage import/export events, reconcile tab selection when panels unregister, re-register on value changes, clamp grid cols/span, fix bell a11y/clicks, and load Choy styles on DogfoodLogin. * fix(choy_ui): defer default tab pick and tidy L1 edge cases Wait for a late-registering defaultValue before auto-selecting tabs, skip disabled-only picks, normalize bell counts, read Card header slots at render time, announce page loading, and drop redundant dogfood clearToasts. * fix(choy_ui): refine tab selection edges and form loading a11y Only defer defaultValue while nothing is selected, rename tabs in place on value change, watch defaultValue, cover disabled/stale cases, ceil bell counts, and announce FormView loading with role=status. * fix(choy_ui): block duplicate tab rename and embed form border Reject ChoyTab value renames that collide with an existing registration, apply FormView border classes mutually exclusively for embedded mode, and cover the empty registration-list selection path. * fix(choy_ui): own tab registrations and clamp grid spans Track whether a ChoyTab owns its registration so refused duplicates do not unregister survivors, bind panes to registeredValue, and extract resolveChoyColSpan with unit coverage. * refactor(choy_ui): render-time slots, shared grid cols, testable tabs registry Read Layout/Page slot visibility at render time, map ChoyMessage levels via an exhaustive Record, extract createChoyTabsContext and normalizeChoyGridCols with direct unit coverage. * fix(choy_ui): harden tab ownership edges and unread a11y Fail update on unknown values, hide duplicate ChoyTab panes, announce exact unread counts, treat null span as full width, and cover the unknown registry path. * fix(choy_ui): retry refused tabs and tidy page/message helpers Allow duplicate-refused ChoyTabs to re-register on value change, keep tab identity when patch.value is undefined, shallow-watch the registry, omit unset ChoyMessage options, extract ChoyPageTitleActions, and cover defaults. * fix(choy_ui): retry free tabs, clamp grid, inert loading body Watch the shared registry so refused ChoyTabs reclaim a freed value; merge tab updates field-by-field; reject empty values; cap grid cols; mark loading page/form bodies inert for a11y. * fix(choy_ui): inert chrome while loading, cover tab reclaim Keep FormView header/button-box and Page header/toolbar/footer unreachable during load; pin duplicate-register recovery after unregister. * fix(choy_ui): retry collided tab renames; inert messages Retry pending value renames once the conflict clears; drop redundant Tabs default-value under v-model; inert FormView messages while loading. * fix(choy_ui): clamp toast duration; sync label on rename miss Reject non-finite/negative ChoyMessage durations before the store, and keep label/disabled patched when a tab value rename collides. * fix(choy_ui): settle tab default, isolate loading status Fall back after ChoyTabs mounts when defaultValue never registers; keep loading status outside aria-busy; fix failed-rename label; drop dead Dogfood submitting guard; plain pane without ChoyTabs parent. * fix(choy_ui): announce bell count; drop sticky invalid duration Add string span/cols coercion coverage; live-status unread count on the notification bell; leave invalid ChoyMessage durations to the store default. * fix(choy_ui): breadcrumb with header slot; clarify dogfood toast Render breadcrumb above a custom header slot; mark dogfood success as no-auth; cover stale→default tab selection and sub-ms toast duration. * fix(choy_ui): blank grid attrs, toast bounds, rename partials Treat blank cols/span as unset; trim toast titles and cap duration at the 32-bit timer limit; apply label/disabled on colliding tab renames.
* feat(choy_ui): PR4 L3 DataTable, DatePicker, RelationCombobox Add TanStack table/virtualizer and @internationalized/date peers with internal engines for Gallery dogfood; keep helpers unit-tested and out of the public barrel for PR5 List/Date/ManyToOne assembly. * fix(choy_ui): harden L3 DataTable and RelationCombobox edges Reject empty row ids, restore original selection id types, sync header scroll, show indeterminate select-all, fix search races, and pin the selected relation label across remote pages. * fix(choy_ui): cover L3 helpers and harden review edges Reach full helper coverage; catch relation search failures; harden row ids; fix clear/select emit duplication and calendar clear key bubbling. * fix(choy_ui): address L3 a11y, filter, and selection review edges Move DatePicker clear out of the trigger; ignore remote combobox filtering; prune stale row selection; encode typed row keys; debounce and surface relation search failures. * fix(choy_ui): harden L3 id decode, date parse, and NameSearch map Decode typed row keys on registry miss, reject non-finite ids, validate impossible calendar days, dedupe relation options, and keep Clear for unparsable models. * fix(choy_ui): polish L3 scroll sync, prune, and id edge cases Compare scrollLeft for header/body sync, extract selection pruning, trim string row ids, broaden row-click guards, and keep search errors generic in the UI. * fix(choy_ui): support controlled DataTable selection and stale search reset Declare rowSelection for v-model pairing, clear RelationCombobox caches when the search target changes, and cover the blank-query NameSearch path. * fix(choy_ui): stop open-search cancel and polish L3 UX edges Do not bump searchSeq while the combobox is open; keep prior options visible during loading; skip controlled selection echo emits; and expose aria-sort on column headers. * fix(choy_ui): harden controlled DataTable selection and a11y Keep prop-authoritative selection with off-page id merge, complete table roles plus keyboard row activation, and clear RelationCombobox host errors whenever local error state resets. * test(choy_ui): cover date parse clamp rejection path Inject a clamping parser in unit tests so the exact YYYY-MM-DD parts guard stays reachable under the current @internationalized/date behavior. * fix(choy_ui): normalize selection ids and polish RelationCombobox UX Trim controlled row ids before encoding/merging, show selected labels via display-value, skip empty virtual items, pad years for date round-trip, and clear debounce timers on watcher cleanup. * fix(choy_ui): sort Date columns by timestamp in DataTable Default sortingFn uses compareDataTableValues; compare Date instances via getTime so weekday-name string ordering no longer wins. * fix(choy_ui): stabilize DataTable columns and RelationCombobox edges Memoize column defs and defaultColumn, measure virtual rows, abort stale searches on watcher cleanup, normalize NameSearch rows, and avoid emitting select(null) for unresolved ids. * fix(choy_ui): harden L3 selection merge, a11y, and RelationCombobox UX Dedupe controlled selection ids, memoize presentKeys, announce virtual table counts, keep search options on error, and round-trip date/key edges. * fix(choy_ui): align date/relation edges and dogfood controlled selection Clear unformattable dates to null, normalize upsert ids, coerce Date/number sorts, pin labels on close, and bind gallery DataTable via v-model. * fix(choy_ui): tighten date/row-key edges and virtualizer identity Validate day-of-month on format, ignore object NameSearch labels, guard malformed n: keys, key virtual rows by id, and clamp Relation debounce. * fix(choy_ui): trim relation ids and deep-watch controlled selection Match padded model ids to pinned/selectedOption labels, skip blank DisplayName overshadowing label, and deep-watch rowSelection/presentKeys. * fix(choy_ui): detect duplicate row ids and stabilize Relation search Reject colliding DataTable ids, tolerate null selection, skip false-only prune writes, hide empty-on-error, and watch searchKey for target identity. * fix(choy_ui): drop ghost selection ids and polish DataTable a11y Skip unnormalizable controlled ids on merge, re-measure on estimateSize change, align leaf headers, and coerce DatePicker display/clear guards. * fix(choy_ui): keep invalid date picks and stabilize list scroll Reject out-of-range DatePicker writes without clearing, reset pins only on searchIdentity, preserve option raw, and reset scroll on data/search. * fix(choy_ui): fix empty-table ARIA count and Infinity sort Count the empty-state placeholder row, compare numbers with < / >, disable non-sortable headers, and validate month length via UTC leap-safe days. * fix(choy_ui): align date year parse and use grid for selection a11y Reject out-of-range years on parse, switch DataTable to role=grid with gridcell, clamp estimateSize, and add encode/decode round-trip coverage. * fix(choy_ui): advertise multi-select and harden numeric string sort Add aria-multiselectable, compare numeric-looking strings without ICU, clear stale sort when columns swap, and route Today through calendarValue. * fix(choy_ui): reset scroll on key signature and label calendar nav Watch presentKeys instead of data identity for scroll reset, key Relation virtual rows by option id, and cover throwing date parsers. * fix(choy_ui): break unsafe-int string ties and Space-toggle rows Tie-break collapsed MAX_SAFE_INTEGER string ids, ignore unusable ids in selection equality, Space toggles selection, and bound the DatePicker calendar.
* feat(choy_ui): PR5 Form/List/Search and field main set Wire ChoyFormView/ListView/SearchView/Pagination/Breadcrumb and the field main set onto L3 engines, with DogfoodCompanyForm and Gallery dogfood. * fix(choy_ui): address PR5 review a11y/bugs and helper coverage Restore image preview object-URL ownership, wire field control a11y IDs, harden dogfood save/pagination, and cover remaining helper branches. * fix(choy_ui): address follow-up PR5 review a11y and dogfood save Round monetary commits, wire field slot a11y across controls, keep invalid number drafts, sync pagination page, and harden dialog/dogfood saves. * fix(choy_ui): harden monetary rounding, draft sync, and field a11y ids Keep invalid drafts visible, round decimal strings half-away-from-zero, unique-suffix control ids, and avoid disabling readonly text inputs. * fix(choy_ui): sync monetary draft on host model and polish PR5 edges Clear stale edited drafts on unfocused model updates, normalize search keywords, unify numeric monetary rounding, and fix breadcrumb/number UX. * fix(choy_ui): preserve host monetary updates and tighten field a11y Allow unfocused-or-unedited model sync while typing, expose aria-required, keep non-exponential number drafts, and filter empty Select options. * fix(choy_ui): sync monetary host updates and cover helper edges Only keep focused drafts when they match the host value, harden checkbox typing, drop blank search fields, and exercise remaining helper branches. * test(choy_ui): cover exponential monetary string fallback branches Exercise Number()-canonicalized decimals and -0 formatting so formatChoyMonetary patch coverage reaches 100%. * fix(choy_ui): cover decimal carry paths and tighten monetary edges Exercise full rounding carry, drop an unreachable frac pad loop, reject non-decimal literals, and prefer local image object URLs over stale hosts. * fix(choy_ui): harden PR5 field edges from review Keep host clears over stale monetary drafts, guard readonly date/time inputs, reject lossy monetary magnitudes and non-image picks, expose help via sr-only aria-describedby, reset page on pageSize change, and normalize empty selection to null. * fix(choy_ui): address PR435 follow-up review edges Move Binary/Image a11y attrs onto the visible Choose control, reject lossy float/decimal parses and monetary display fallbacks, commit number drafts on Enter, guard monetary input when readonly, and keep list rowSelection as a non-null array. * fix(choy_ui): reject unrepresentable fractions near 2^52 Guard parse/round helpers when typed fractions vanish at unit spacing, reuse choyTotalPages in dogfood paging, and watch only File for image object URLs. * fix(choy_ui): skip monetary rewrite on idle blur Do not round the host model on focus/blur without edits, align number formatting with the string lossy-reject path, clear list selection on search in dogfood/gallery, and drop the unused keywordFields prop. * fix(choy_ui): drop dogfood USD fallback and pin round-trip Stop implying USD when currency is cleared, and assert roundChoyDecimal text still parses back through parseChoyNumber. * fix(choy_ui): tolerate trailing dots and harden select/enter Normalize trailing decimal points on parse/round commit paths, de-dupe selection option values, prevent Enter form submit on number fields, and announce pagination changes to assistive tech. * fix(choy_ui): mark invalid drafts and export view helpers Surface uncommitted invalid monetary/number drafts via aria-invalid, navigate Gallery→dogfood by named route, re-export search/pagination helpers from the public barrel, and pin negative half-away round-trip. * fix(choy_ui): ignore idle exponential blur and tighten format Skip invalidDraft when the number draft still mirrors the host value, reject lossy exponential monetary strings, fall back to a single list checkbox on dogfood save, and drop unsupported aria-required on statusbar. * fix(choy_ui): quiet virtual attrs and harden field edges Disable VirtualField attr inheritance, deep-watch dialog rows while pristine, hide non-finite binary sizes, and skip non-string selection option values. * fix(choy_ui): restore select placeholder and leading-dot parse Bridge null↔empty for Reka Select so unset shows the placeholder, accept leading-dot decimals in parse/round helpers, and surface invalid number drafts as field error text. * fix(choy_ui): tighten dogfood search and file accept checks Clear selectedRowId on search, accept leading +, validate empty-MIME images by extension, enforce Binary accept tokens, and disable Save while the mock request is pending. * fix(choy_ui): pin round stability, block SVG, export helpers Add idempotent roundChoyDecimal coverage, reject SVG image uploads by default, bind statusbar controlId for label association, and re-export field helpers from the public barrel. * fix(choy_ui): normalize -0.00 display and file reject UX Collapse signed-zero monetary formatting, keep invalid amount visible on focus, align image accept with raster validation, surface rejected file picks as field errors, and skip non-primitive cells in keyword filter. * fix(choy_ui): stop lossy monetary fallback and harden accept Restrict monetary numeric fallback to exponential text, fix Binary accept wildcards and empty MIME, clear stale file errors on host model updates, require visible page rows for dogfood save, and allow named routes in breadcrumbs. * fix(choy_ui): reject inexact doubles and keep form save target Replace the 2^52 fraction guard with a canonical round-trip check so values in [2^51, 2^52) cannot commit a different amount, and validate dogfood selectedRowId against allRows while checkbox stays page-local. * fix(choy_ui): harden field UX and cover decimal expansion - map image/jpeg empty-type fallback to .jpg/.jpeg; allow empty MIME on wildcards - normalize datetime-local display; keep unmatched selection values visible - commit monetary draft on Enter; pin list row ids; export choyFieldChromeDefaults - expand exponential literals in canonicalChoyDecimal and cover all branches * fix(choy_ui): align monetary e-paths and harden field edges - gate exponential string formatting on digit exactness so 1e21 matches the number path - bound expandExponentialDecimalText padding to avoid RangeError - guard number draft updates when readonly/disabled; skip datetime display echo writes - type Gallery select as string | null instead of weakening Select empty→null * fix(choy_ui): harden accept, IME Enter, and e-form exactness - accept *.ext and map image/svg+xml empty-type fallback to .svg - filter empty statusbar options; skip Enter while IME is composing - require expandable exponential literals so 9007199254740993.e0 stays rejected * fix(choy_ui): harden datetime/time, accept, and e-forms - compare datetime/time writes at input precision; sanitize field control ids - align image validation with accept; normalize *.ext for the file picker - skip selection ''→null on mount; revalidate number draft on mode change; dedupe statusbar - expand leading-dot exponentials; drop unreachable expandFiniteNumber fallback * fix(choy_ui): pad time hours and keep monetary draft - pad single-digit hours for native time inputs; treat octet-stream as extension fallback - keep focused monetary draft when it already matches the committed value - cover primitive number/boolean keyword filter matching * fix(choy_ui): GB sizes, stable row ids, mode-invalid - add GB tier for binary size; reset pagination to page 1 explicitly - hoist stable list row-id callbacks; drop SelectionField ''→null watcher - flag number draft invalid when mode cannot parse the host value - drop unreachable expand empty-digits / isSafeInteger pad branches for coverage * fix(choy_ui): cover expandFiniteNumber and harden picks - export/test expandFiniteNumberToPlainDecimal for zero and exponential paths - ignore bare accept tokens unless a restrictive token fails to match - flag number mode/value mismatch on mount; unify image raster allow-list * fix(choy_ui): validate host number by value not String() - avoid marking exponential host values like 1e-22 invalid on mount/mode switch - keep mode incompatibility (e.g. 12.5 under integer) flagged for host and edits
* feat(choy_ui): PR6 Kanban, O2M/M2M, Html/Json/Properties Add isolated data-view and remaining field main path for cutover 门槛: Kanban board, relation widgets, TipTap Html, Json, and Properties. * fix(choy_ui): address PR6 review bugs and reach helper coverage Fix nested JSON key loss, O2M edit/remove guards, Properties defaults, Html plaintext separators, Kanban same-lane drop index, and TipTap initial sync; expand helper unit tests for Codecov patch 100%. * fix(choy_ui): harden JSON sort and close coverage gaps Preserve __proto__/toJSON in stringify, skip TipTap empty reset, pin TipTap peers, and cover buildFullPropertiesMap default branch. * fix(choy_ui): validate Html links, dedupe lanes and property names Reject non-http(s)/mailto link schemes before TipTap setLink; skip duplicate Kanban laneDefs; reject duplicate property definition names. * fix(choy_ui): harden sanitize/stringify and normalize selections Guard missing purify.sanitize with tag strip, coalesce undefined JSON.stringify results, and persist only usable selection options. * fix(choy_ui): correct Kanban move index and link/host parsing Emit post-move Kanban toIndex, treat host:port as host not scheme, separate void hr in plaintext, and uniquify synthetic O2M row ids. * fix(choy_ui): harden no-DOM strip and keep unrenderable props Strip unterminated tags when purify.sanitize is missing, and carry forward previous values for non-V1 property schema items on rewrite. * fix(choy_ui): sync JSON draft on reset and skip blank defaults Let external model updates overwrite invalid JSON drafts, ignore whitespace-only numeric defaults, assert rel via sanitize hook, and re-seed definition drafts only when items content changes. * fix(choy_ui): fix protocol-relative links and kanban add races Reset hr-only Html on null, preserve generated Id when titleField is Id, and compare normalized property definition drafts. * fix(choy_ui): fail-closed sanitize and tighten definition defaults Hide Kanban create when readonly and reject selection defaults outside options.
* feat(choy_ui): PR7 Chatter, theme persistence, and xpath dogfood Add isolation ChoyChatter*, applyChoyThemePreference + theme.override.css, and Partner-style data-anchor dogfood with xpath-injected Bank tab. * fix(choy_ui): cover timeline id sort and harden theme prefs Rebind xpath dogfood setup after IMD merge and clear dogfood timers on unmount. * fix(choy_ui): parse digit epoch strings and clear gallery timers Persist normalized theme modes; use locale-independent id tie-breaks. * fix(choy_ui): accept signed digit epoch timestamp strings * fix(choy_ui): reject array theme prefs and allow field-change labels * fix(choy_ui): default timeline entries and expose chatter clear * fix(choy_ui): merge stored theme prefs on partial apply Keep Gallery auto mode when only density changes. * fix(choy_ui): reject unsafe epoch strings and prune dogfood timers * fix(choy_ui): bind partner tab anchor and validate persisted theme Reject unsafe numeric timestamps consistently with digit-string parsing. * fix(choy_ui): ignore invalid theme prefs and case-fold change kinds Keep empty action: labels aligned with product; cover fieldFallback. * fix(choy_ui): reject out-of-range timestamps and avoid theme clobber Dedupe timeline identities and preserve drafts on empty-string post errors. * fix(choy_ui): skip unset theme attrs on partial preference apply * test(choy_ui): cover partial theme apply leaving host dark class * fix(choy_ui): persist only expressed theme preference fields * fix(choy_ui): restore document theme after dogfood partner unmount * fix(choy_ui): do not invent theme when gallery persists density * fix(choy_ui): restore dogfood theme only when still page-owned * test(choy_ui): pin cross-kind chatter timeline id dedupe * fix(choy_ui): do not invent density when gallery persists theme * fix(choy_ui): accept only ISO chatter wire timestamps * fix(choy_ui): clear chatter draft on resId change; require ISO T separator * fix(choy_ui): pin naive ISO times to UTC; deterministic timeline dedupe * fix(choy_ui): enforce ISO timestamp case; guard stale post draft clear * fix(choy_ui): sync-flush chatter posting watcher for same-tick hosts * fix(choy_ui): capture in-flight posting on chatter mount * fix(choy_ui): defer chatter draft clear past same-tick postError * test(choy_ui): fix year-pad assertion for formatChoyUtcIso * fix(choy_ui): static IMD tab anchor; reject impossible ISO dates * fix(choy_ui): reject out-of-range chatter ISO time components * fix(choy_ui): keep chatter composer mounted when disabled * fix(choy_ui): ignore chatter submit shortcut during IME composition * fix(choy_ui): validate ISO offset ranges; ignore overlapping gallery posts * fix(choy_ui): default timeline author resolver; treat empty postError as ok * test(choy_ui): cover author label overrides; guard dogfood overlap posts * fix(choy_ui): keep timeline on refresh; clear draft on model change * fix(choy_ui): truncate ISO fractional seconds; IME-safe submit prevent * fix(choy_ui): normalize minute-precision chatter ISO timestamps
* feat(choy_ui): PR8 ChartView with Unovis (no ECharts) * fix(choy_ui): address PR8 review, Tailwind gate, and chart coverage Wire Unovis click via events, sort before percent stack, unique series keys, and fix the Tailwind leak check false positive on clip-path. * fix(choy_ui): correct Unovis click callbacks and chartType guard Align bar/line/pie handlers with VisEventCallback(datum, event, index), resolve stacked stackIndex and grouped flat series, and reject unsupported host chartType values. * fix(choy_ui): harden chart metric default, line click, and finite values Fall back to the first metric when the alias is unknown, bail on unresolved line-click SVG targets, and coerce non-finite series values to 0 for Unovis. * fix(choy_ui): polish chart pie slices, metrics watch, and click helpers Filter non-positive pie slices, deep-watch metrics, label sort toggles, and extract unit-tested Unovis click index mapping helpers. * fix(choy_ui): gate disallowed chart types and harden percent/click mapping Skip rendering when the host allowlist empties availableTypes, clamp negatives out of percent stacks, and prefer row.index for stacked click categories. * fix(choy_ui): empty pie state, safer grouped clicks, round percents Treat all-non-positive pie slices as empty, only map grouped series when the flat index agrees with the row category, and round percent stacks to 2 dp. * fix(choy_ui): cover rowCategoryIndex edge and polish chart type UX Cover invalid row.index paths for patch coverage, allow pie when multi-series even with groupDepth 0, map line clicks via path bounds, and preserve host chartTypes order. * fix(choy_ui): chart overlay precedence, shared fallback color, line click helper Prefer error over loading overlay, harden Tailwind *-path leak sanitization, centralize chart fallback color, and unit-test line-click category mapping. * fix(choy_ui): harden line click width, path leak detect, percent align Bail on zero-width line clicks, detect bare path: leaks without stripping CSS *-path, pin sort-before-percent, and align percent series to categories. * fix(choy_ui): finite sort totals and validate chart click indexes Coerce Infinity/NaN before sorting and percent math, bounds-check emitted series indexes, and guard non-finite line-click positions. * fix(choy_ui): preserve pie categoryIndex and harden chart helpers Resolve adapters via registry own-keys, optional-chain sparse series data, and emit the original category index after pie slice filtering. * fix(choy_ui): touch line clicks, axis metric label, slot disabled Normalize line-click X from changedTouches, surface metricLabel on the Y axis, and forward disabled into stacked/sort switcher slots. * fix(choy_ui): harden stacked/pie clicks and clientX fallback Guard undefined stacked-bar datums, prefer pie slice key/name identity, and fall through to event.clientX when touch X is non-finite. * fix(choy_ui): percent column remainder, blank index, noop emits Use largest-remainder percent rounding so stacks hit 100, reject whitespace-only row indexes, and skip redundant type/sort change events. * fix(choy_ui): disambiguate pie click indexes and validate metrics Emit distinct category vs series indexes for single/multi-series pies, validate metric alias selection like other controls, and tighten the Tailwind path: leak check to only exempt clip/offset-path. * test(web): use hyphen-aware path: leak regex again Prefer [^a-z-] so any CSS *-path: (including vendor-prefixed) is exempted without an ad-hoc clip/offset Replacer list. * fix(choy_ui): stable sorted categoryIndex and safer stubs/ticks Guard FE stub resolve on lookup ok, map XY click indexes through the sort permutation, and skip fractional/out-of-range axis tick labels. * fix(choy_ui): key-first pie match and overflow-safe percents Resolve donut clicks by unique slice key before name/index, coerce non-finite values on the unsorted sort path, and scale percent totals before the 10000 factor so large finite inputs cannot overflow.
* chore(choy_ui): put template before script in product SFCs IMD/xpath reviewers open markup first; keep vendor/ui on shadcn's script-first order so upstream diffs stay small. * docs(agents): document Vue SFC template-first convention Record IMD-first template → script → style for product SFCs, with vendor/ui keeping shadcn script-first; point at the local Cursor rule. * revert(docs): drop Vue SFC convention note from AGENTS.md Keep the rule local under gitignored .cursor/rules only. * fix(web): escape ErrorView message; clarify SFC order docs Render error details as text so route query cannot inject HTML, and document that template-first applies to module web pages too.
* feat(web): PR9a merge Choy kit tree into modules/web
Move vendor/view/field/layout/chatter/internal, styles, gallery/dogfood
into modules/web; keep a thin choy_ui re-export shell. Prefer web for
Tailwind generation with kit-only candidate scan, exempt web as kit
host, and mask PascalCase Textarea tags so template-first SFCs parse.
* fix(web): pin exact package.json peers for esm.sh web builds
Bare @tanstack/vue-table resolved to latest v9 (useTable) and broke
DataTable named imports after the kit merged into web. Apply exact
peer/dependency versions from the module package.json as bare-import
pins so global web build stays on the declared 8.21.3 API.
* fix(web): pin kit peers in FE host bundle; harden gallery setup
unit-shard (web) still resolved versionless @tanstack/vue-table via the
vue host bundle. Merge exact modules/web peers into host/e2e esm pins,
and skip Choy gallery registration when router is missing so setupApp
unit tests stay isolated.
* fix(web): scope SFC raw-text mask to templates; raise PR441 patch coverage
Limit PascalCase Textarea/Title masking to unquoted template bodies so script
literals and attributes stay intact; declare choy_ui→web depends and cover the
Codecov patch gaps.
* fix(web): harden SFC raw-text mask and e2e peer pins
Only skip quotes inside tags so apostrophes in template text cannot leave
Textarea unmasked; ignore script/style-embedded template literals; skip
test/spec files in Tailwind scans; fail e2e bundles on pin read errors.
* fix(web): harden SFC template depth, pins, and kit host guards
Ignore self-closing nested templates when masking; fail when a kit tree
lacks theme.css; gate web Reka exemption on vendor/ui; propagate FE pin
errors; dedupe ExactPins wiring in webBuilder.
* fix(web): require kit ui path to be a directory
Harden vendor/ui probes with IsDir, skip the Choy Vue parse scan when the
kit tree is absent, and assert ExactPins are actually consumed in builds.
* test(web): cover remaining PR441 patch branches
Exercise nil ExactPins receiver, empty modulesPath kit-host gate,
self-closing tag edges, and FE host bundle pin read failures.
* fix(web): harden SFC mask tag detection and kit scan fallbacks
Require a real tag name after '<' so interpolations cannot derail quoting;
pair script/style blocks independently; prefer-web kit root test; Choy*
fallback for unlisted kit dirs; derive FE pin asserts from package.json.
* fix(web): confirm tag openers before masking; guard addRoute
Require a closing '>' (quote-aware) before treating '<' as a tag so
comparisons like '{{ a <b }}' cannot derail Textarea masking; assert
Tailwind walk errors return no partials; require router.addRoute.
* fix(web): broaden Choy page scan; cover SFC tag-opener edges
Allow pages/Choy* in kit Tailwind candidates; normalize generated CSS
exclusions case-insensitively; harden escape handling and unit-cover
looksLikeHTMLTagOpener branches for Codecov patch 100%.
* fix(web): quote-aware SFC openers; prefer dependency pins
Make template/script/style open tags quote-aware so '>' inside attrs does
not truncate matches; let exact dependencies override peers; skip
__tests__/ paths in Tailwind candidate scans.
* fix(web): harden SFC mask boundaries and kit UI Stat errors
Skip HTML comments when scanning template depth and masking; clamp
unbalanced fallback before script/style; cover mixed-case raw-text tags;
unmask comment nodes; surface non-not-exist vendor/ui Stat errors.
* fix(web): ignore script/style when scanning HTML comments
An unclosed "<!--" inside a script string must not open a comment span
through EOF that skips masking the following template Textarea.
* test(web): cover SFC mask comment edge branches
Exercise close-inside-comment, unclosed HTML comments, and OutsideQuotes
unclosed-comment paths so parser.go patch coverage reaches 100%.
* fix(web): ignore commented script/style openers in SFC mask
A <!-- <script> --> must not pair with a later real </script> and treat
the template as script body, leaving PascalCase raw-text tags unmasked.
* fix(web): prefer nested template open before comment close
Checking inComment(close) first skipped a preceding nested <template>
opener when the next </template> sat inside a comment, corrupting depth.
* fix(web): protect template depth from mustache/attr literals
Ignore </template> inside mustaches and quoted attrs when scanning SFC
template depth; cover choy_ui kit fallback; avoid digest path allocs.
* test(web): cover mustache/attr range helper edges
* fix(web): restore chatter edge tests; harden kit host + unmask
Restore formatFieldChangeSummary edge assertions; derive ModulesPath from
ModuleRoot for kit-host exemption; strip VueSfcRaw masks from text nodes.
* fix(web): merge kit pins; harden SFC script/mustache ranges
Domain module builds inherit modules/web exact pins (own pins win);
drop mustache ranges that start in script/style; ignore cross-script
comment markers when discovering script blocks.
* fix(web): Clean ModuleRoot; mask ALLCAPS; warn pin conflicts
Derive kit-host ModulesPath via filepath.Clean; mask all-caps raw-text
tags; log when a module exact pin overrides the kit host version.
* fix(web): unmask only tag sentinels; harden pins and choy fallback
Restore VueSfcRaw only after < or </ in text/comments; Clean module path
before kit-host pin lookup; accept lowercase choy* in unknown-dir scan.
* perf(web): skip SFC raw-text masking when no candidate tags
Avoid the multi-pass masker when pascalCaseRawTextTag does not match,
which is the common case for product SFCs without Textarea-like tags.
* test(web): cover top-level self-closing template mask path
* fix(web): drop comment mustaches; harden kit host Stat and O*.vue
Ignore mustache ranges that start in HTML comments; treat only IsNotExist
as non-kit for web; limit capital-O exclusion to .vue product views.
* fix(web): guard empty pin path; case-insensitive raw-text mask
Bail on blank module Path before kit pin lookup; match generated CSS by
exact kit-host suffix; mask any non-lowercase raw-text tag spelling;
treat only permission Stat errors as web kit-host.
* fix(web): fail closed on kit Stat; TrimSpace pin paths
Any kit-dir Stat failure keeps the web import ban; trim module Path
before Clean so whitespace-padded paths still resolve kit pins.
* fix(web): drop exact vue pins from module package.json
Mirror vueHostBareImportPins so module builds cannot pin a second Vue
instance away from the embedded host.
* fix(web): harden kit path/mask edges from PR review
Require a directory boundary for generated CSS digest skips, scope
Tailwind scan to vendor/ui, interleave comment/mustache discovery so
attr <!-- and comment {{ cannot unmask Textarea, drop e2e vue pins,
and tighten the kit Stat fail-closed test.
* feat(web): PR9b main-bundle Choy CSS, product scan, cutover bans Emit unscoped Tailwind theme/utilities into the SPA entry, scan kit plus domain web trees for candidates, and add gated cutover import bans (element-plus / @/web lib) while keeping dual-stack typecheck green. * fix(web): harden PR9b product scan and cutover lib bans Drop Parallel on the shared ReadDir hook test, align exported Generate hashes with product digest under modules/, and normalize import paths so bare and ../-escaped @/web/web/lib deep imports stay banned. * fix(web): align kit root, CSS order, symlink scan, query strip Resolve preferred kit root before generate so dialect/hash match digest, import generated utilities after index.scss, scan symlink modules, and strip ?/# before cutover lib-path normalization. * fix(web): skip file symlinks, filter sibling kits, normalize EP bans Stat module roots before web/ so ENOTDIR cannot abort product scans, route sibling kit hosts through kit-filtered candidates, and normalize element-plus specs the same way as deep-lib bans. * fix(web): accept custom modules dirs; assert domain Stat errors Resolve-back modulesPathForKitRoot so Generate matches digest outside a literal modules/ name, and force domain web Stat failures via the test seam instead of flaky chmod 000 probes. * test(web): cover modulesPathForKitRoot parent==root edge * fix(web): normalize import specs before all forbidden UI bans Hoist path cleaning so ui/internal/choy_ui-deep rules cannot be bypassed with ./ ../ or ?/#, matching the cutover element-plus / lib protection. * fix(web): reject directory sibling dialects; cover cutover scan Treat a directory theme.css on sibling kits as an error (same as preferred kit resolve), replace flaky chmod probes with deterministic fixtures, and assert cutover bans plus kit-host exemption through AssertNoForbiddenUiImports. * fix(web): gate sibling kits on vendor/ui; scope dark tokens Align product Tailwind sibling-kit detection with isKitHostModule so domain modules that only ship theme.css keep full scanning, and drop unanchored .dark / [data-density] selectors that could theme EP subtrees. * fix(web): pin theme override cascade; anchor web-lib bans Import theme.override.css from the app entry after tokens so it is not reorderable by route chunks, and match cutover web/web/lib bans by leading segments to avoid embedded-path false positives. * fix(web): keep dir trailing slash in import bans; digest domain classes Preserve directory-style trailing slashes after path.Clean so @/choy_ui/ still matches choy_ui-deep markers, ban bare @/choy_ui, and assert TailwindInputDigest changes when a domain module adds a class. * fix(web): close web-lib prefix bypass; kit-filter without dialect Strip @/, ../, and ./ in any order for cutover web/web/lib bans, and treat vendor/ui ownership as the kit-host marker independent of styles/theme.css so sibling hosts stay kit-filtered. * fix(web): align custom kit-root product scan; harden host filtering Accept either web or choy_ui under a custom modules parent for product scans, treat choy_ui as a kit host by name, load theme.override after index.scss, and wrap per-module candidate scan errors with context. * fix(web): ignore non-kit directory dialects; lock domain spec skip Keep directory-dialect hard errors for web/choy_ui only so a stray styles/theme.css directory on an unrelated sibling cannot abort product Tailwind generation, and assert Ensure skips domain *.spec*/__tests__ classes. * fix(web): ban package-form @choysum-dev/web/web/lib deep imports Rewrite @choysum-dev/web/* package subpaths into web/* so cutover web-lib-deep matches the published package specifier the same way as @/web/web/lib aliases.
…443) * feat(web): PR9c cut shell to Choy runtime (setupApp, peers, barrel) Drop Element Plus from the web SPA host and CSS entry, apply Choy theme preferences at startup, route shell pages through ChoyShellLayout, and trim echarts/EP icon peers while keeping the public barrel Choy*-only. * fix(web): restore echarts peers; cover shell; restore theme on boot Keep echarts/vue-echarts peers for dual-stack OChartView typecheck, apply persisted Choy theme at startup, keep link hover/active distinct via color-mix, and add HomeView/ChoyShellLayout unit coverage. * fix(web): resolve ErrorView codes from path; allow shell default slot Static /error/403 redirects had no :code param, so ErrorView always fell through to 404. Parse the path segment, and wrap router-view in a default slot so hosts can override the main pane. * fix(web): prefer ErrorView path code over query; clarify tick read Static /error/NNN redirects must win over a stray ?code=; mark the HomeView tick dependency with void for intentional reactive reads. * fix(web): hide empty shell aside; harden ErrorView codes and link hover Skip aside chrome unless a slot is provided, normalize array route codes, and add plain color fallbacks before color-mix for older engines. * fix(web): restore EP for dual-stack; harden ErrorView query picks Keep Element Plus registered for O*/TerminologyEditor during cutover, normalize repeated ErrorView query values, and store HomeView prefs in a ref. * fix(web): restore reactive ElConfigProvider; clarify AppLayout sidebar Dual-stack O* locale switching needs a live ConfigProvider; AppLayout keeps showSidebar off until menu chrome can fill the aside slot. * fix(web): gate empty footer; resync Home theme; sanitize ErrorView from Skip footer chrome without a slot, refresh keepAlive Home prefs on activate, and only offer Go back for same-app absolute from paths. * fix(web): restore shell KeepAlive; harden from paths; drop App data-test Honor route.meta.keepAlive like OLayout, reject backslash open-redirect forms, and remove a non-inheritable data-test on ElConfigProvider. * fix(web): keep KeepAlive mounted; drop dead footer; cover WelcomeView Preserve cached shell views across non-keepAlive navigations, remove route showFooter that cannot fill slots, and add WelcomeView step tests. * fix(web): skip shell view render when router-view Component is empty AppLayout and similar hosts can match with no child component; guard both KeepAlive and plain branches to avoid invalid :is="undefined" vnodes. * fix(web): key keepAlive by fullPath; mix hover from base primary Parameterized cached routes need distinct instances per fullPath, and color-mix hover/active should start from --el-color-primary not a light tint. * fix(web): key keepAlive views by path, not fullPath Reuse one cached instance across query variants while still remounting when parameterized path segments change. * fix(web): honor link theme tokens; harden ErrorView and shell meta Nest color-mix under primary-light/dark vars, reject /error from targets, optional-chain keepAlive meta, and open external links with noopener. * fix(web): harden ErrorView from paths; cap KeepAlive cache Reject control chars and backslashes anywhere in redirect targets, and bound shell KeepAlive retention so parameterized paths cannot grow unbounded. * revert(web): drop KeepAlive max cap on ChoyShellLayout Cache bounding is unnecessary for the current keepAlive route set. * fix(web): gate color-mix with @supports; harden sameAppPath encodings
* feat(web): PR9d store-bound Choy engine (Page/Form/List/fields) Wire optional WebModelStore binding into ChoyPage/Form/List/Search and key fields via store+prop (hosting O* engines); keep chrome/Dogfood defineModel paths when store is absent. Export ChoyVColumn/ViewScope/ ButtonBox/StatInfo from the public barrel. * fix(web): restore Choy chrome attrs fallthrough and cover store hosts inheritAttrs:false was dropping chrome-mode attrs/listeners; ManyToOne chrome now uses a noop search fallback. Mount tests exercise store-mode hosts and patch paths for Codecov. * fix(web): forward Choy store engine events and page-store fields Declared emits were not forwarded in store mode; attrs+v-on double-bound listeners. Fields under ChoyPage now resolve the page store; VColumn forwards scoped slot props; nested pages keep the ancestor store. * fix(web): strip on prefix in splitChoyAttrsListeners for v-on Vue toHandlers prepends on again; keep v-on object keys as event names so undeclared store-mode listeners actually fire. * fix(web): forward Search store props and conditional VColumn slot Store-mode ChoySearchView now passes placeholder/disabled to OSearchView (inert when disabled). ChoyVColumn forwards the cell slot only when the consumer provides one. Field hosts share useChoyStoreFieldBinding. * fix(web): align O2M inheritAttrs and listener on* detection ChoyOneToManyField now disables attr fallthrough like sibling fields. splitChoyAttrsListeners matches Vue's /^on[^a-z]/ heuristic so camelCase props such as onchangeSessionId stay in bind. Mount tests assert forwarded prop. * fix(web): share ViewScope provide keys and harden filter flatten OViewScope/ChoyViewScope provide via shared viewScopeKeys constants. flattenChoySearchFilters accepts a singleton group without throwing. * fix(web): keep List chrome under page store; harden filter leaves Explicit columns/data force ChoyListView chrome even when ChoyPage provides a store. Leaf filters with empty children are no longer dropped. ViewScope uses toRef; O2M row helpers use Record indexing. * fix(web): harden disabled search fallback and list row-click Add pointer-events/select-none when OSearchView is disabled for browsers without inert, and skip nullish store row-click payloads instead of forwarding the wrapper object. * fix(web): block disabled search keys; omit chrome model from storeBind Capture keydown when OSearchView is disabled so older browsers without inert cannot submit via keyboard, and strip defineModel keys from storeBind so chrome defaults do not reach the O* engine.
* feat(auth): PR9e cut domain web to Choy* from @/web Replace auth O*/Element Plus product surface with store-bound Choy* (Page/Form/List/Search/fields) and Choy chrome for Login/Register/Logout. Wire header actions into ChoyShellLayout via data-anchor xpath; host TokenKanban on ChoyKanbanView lanes. Split public @/web barrel to kit.ts so domain imports do not pull the web app instance. * refactor(auth): rename local O* components without O prefix Auth-owned layout/preferences components are no longer named like the legacy web O* stack: AuthHeader, SwitchCompany, PreferencesDialog. * fix(auth): harden PR9e cutover review follow-ups and i18n CI Remove Enter double-submit, wire real notifications, fix token kanban query/flat-lane/move races, hide stub IO actions, restore Login patch coverage, and sync auth/web gettext catalogs for CI. * fix(auth): address PR9e open-redirect and kanban resync reviews Restrict login/register redirect to same-origin paths, drain pending kanban lane syncs, dismiss the user menu on Escape, and tighten Login success assertions. * fix(auth): harden login redirect against backslash open redirects Parse redirect targets with URL origin checks, reject backslash payloads, and tighten Login mount tests to assert real form affordances. * fix(auth): trim login username and harden kanban/company UX Trim username before login submit, navigate kanban cards only on real record ids, and replace the multi-select company list with additive checkboxes. * feat(web): add ChoyKanbanView lane load-more API Expose lane.remain and lane-load-more on the Choy kanban chrome, wire TokenKanbanView through kanbanController.loadMoreLane, and cover the helper contract with unit tests. * fix(auth): close login redirect bypasses and cover login_form 100% Reject normalization-induced protocol-relative redirects, harden kanban card ids/moves, localize New, restore SwitchCompany Escape, and expand login_form unit coverage for origin/error edge paths. * feat(web): host inbox engine behind ChoyNotificationBell ChoyNotificationBell omits deep O* imports from auth by hosting ONotificationBell when count is unset; Gallery keeps chrome mode via explicit count, and AuthHeader imports the public kit export only. * fix(auth): accept raw kanban rows and dim preferences backdrop Normalize RecordRow and raw model records into card payloads, and add a semi-transparent PreferencesDialog overlay for modal contrast. * fix(web): cover notification bell chrome and harden PR9e follow-ups - Extract ChoyNotificationBell badge/aria helpers with unit and mount coverage - Assert login redirect target via router.replace spy - Resync kanban lanes when move record id cannot be resolved - Cap SwitchCompany company list height with overflow scroll * fix(auth): harden kanban labels, search filters, and dialog a11y - Preserve string UserId fallback on token kanban username labels - Keep singleton appliedFilters objects in ChoySearchQuery payloads - Restore focus to popup triggers on Escape; trap Tab in PreferencesDialog * fix(auth): clear typecheck errors and cover dialog focus trap - Cast dialog root for trapDialogTabKey; cover all focus-trap branches - Avoid [object Object] username labels; trim kanban card ids - Always resync lanes after a failed move even if reload rejects - Exclude hidden inputs from dialog Tab order * fix(auth): harden kanban move/load races and list row navigation - Resync optimistic lanes when a move is skipped (pending/unknown lane) - Re-apply late first-frame search after the initial empty kanban load - Fail closed on blank list row ids; normalize notification badge counts * fix(auth): normalize login origin and tighten company/focus UX - Compare login redirects against a normalized origin base - Treat any negative tabindex as outside dialog Tab order - Lock the active company checkbox so active stays in enabled * fix(auth): harden login redirect decoding and focus/inbox polish - Reject percent-encoded // and \\ in login redirect paths - Skip hidden controls in the preferences dialog focus trap - Forward ChoyNotificationBell class in inbox mode - Prefer row key over synthetic id when payload Id is blank * fix(auth): cover login origin catch and polish PR9e follow-ups - Cover normalizeLoginRedirectOrigin parse failures; clear errors before validate - Disable kanban load-more while a move write is in flight - Normalize notification aria counts; skip aria-hidden ancestor tab stops * fix(auth): reset header popups and harden kanban/login edges - Clear AuthHeader menu/preferences on logout; focus dialog before load - Reject malformed percent-encoded login redirects; prefer non-blank usernames - Block kanban moves during search apply; treat summary/contenteditable as tabbable - Disable TokenListView attr fallthrough onto the wrapper root * fix(auth): harden multi-decode redirects and dialog focus restore - Decode login redirect paths until stable before safety checks - Allow hosts to localize kanban load-more labels via a formatter - Skip focus restore when the pre-dialog trigger is detached * test(auth): cover multi-pass login redirect decode fallthrough
* feat(base,meta): PR9f cut domain web to Choy* from @/web
Migrate base/meta pages and views off O*/Element Plus onto named Choy*
imports, with ModuleKanban hosted on createKanbanController + ChoyKanbanView.
* fix(base,meta): harden PR9f review follow-ups and patch coverage
Wire ChoyNumberField/ChoyDateField store hosts, fix ModuleKanban dialog
a11y and search races, restore list route guard, and expand FE mount/unit
coverage for cutover pages and helpers.
* fix(web,meta): cover ChoyNumberField chrome helpers and date parse edges
Extract number-mode helpers with unit tests, harden kanban date formatting
for epoch numbers, and exercise chrome NumberField inputmode in mounts.
* fix(web,meta,base): cover NumberField chrome and PR-Agent follow-ups
- exercise ChoyNumberField chrome commit/host sync for patch coverage
- fall back empty op summary message to code; log lane preload errors
- assert Lucide menu icon identity; drop vacuous ModuleDetailView smoke
* fix(web,base,meta): unbreak typecheck and harden id/nav follow-ups
- replace Array.at in NumberField mount test for current TS lib
- reject non-scalar list/kanban ids; share resolver; catch lane sync errors
- unmount page coverage wrappers in finally with named failure errors
* fix(web,base,meta): harden review follow-ups for ids, dates, and plan races
- fail-closed non-finite ids; keep epoch-0 dates; scalar-only op summaries
- gate PlanOperation by dialog session; date-only store valueFormat
- route float to ONumberField (default decimal); collect page mount failures
* fix(meta,web): coalesce lane sync waiters and fail-closed card/number ids
- reuse fail-closed id helper for kanban card keys; await in-flight lane sync
- count recovery search as in-flight; reject silently-rounded integer drafts
* fix(meta): treat non-finite timestamps as empty in kanban date format
* fix(web): drop unreachable integer BigInt parse guard for patch coverage
Number.isSafeInteger already rejects drafts that Number rounds past the safe range.
* fix(meta): harden kanban chrome fallbacks and invalidate plan on unmount
- ignore in-flight PlanOperation after unmount; unwrap {row} for card ModuleName
- avoid object/[hostile] string fallthrough in date and op summary formatters
* feat(partner): PR9g cut domain web to Choy* + xpath anchors Migrate partner/partner_bank/partner_commercial product surfaces from O*/EP to @/web Choy*, hang partner.detail.tab-panels for IMD, and fill store-bound O2M kanban + ChoyChatter / FormView slot gaps needed by the cut. * fix(partner,web): PR9g typecheck, chatter races, and patch coverage Fix PartnerListView row-click typing and ChoyOneToMany kanban slot typing for CI typecheck; harden ChoyChatter bindStore post/follower races; cover ChoyChatter plus partner list navigation helpers at 100% patch.
* feat(domain): PR9h close remaining domain cutover (peers + e2e) document/task/message/audit stay service-only; drop stale Element Plus peers from cut domain modules and align auth/meta e2e selectors with Choy chrome. * fix(web,auth,meta): PR9h forward ChoyButton attrs and harden e2e hooks ChoyButton/L2 Button now forward data-testid and aria-* so auth header e2e can find company switch and user menu. Also apply review follow-ups: wait for company options, register-terms testid, and scoped op-status rows. * fix(auth,meta,web): harden PR9h e2e selectors from review follow-ups Exclude JWT-active company when picking a switch target, pin module op status/result badges via data-testid, scope kanban search by data-anchor, and always unmount ChoyButton mount wrappers. * fix(auth,web): merge AuthHeader into ChoyShellLayout for e2e hooks Auth header actions never reached the shell because AuthHeader was a standalone SFC; extend ChoyShellLayout so xpath merge and testids work, and apply PR-agent attr/testid hardenings with coverage. * refactor(web,auth): rename ChoyShellLayout to ChoyWebShell Align file and component names on both sides of the xpath inheritance chain; keep choy.shell.header-actions anchors unchanged. * fix(auth,web): harden company-switch pick and reload e2e wait Preserve an already-selected alternative on switch-company retries, and restore auto-waiting reload-row assertion in module management e2e. * fix(i18n,web,auth): clear pot drift and harden review follow-ups Resync base/meta catalogs for ModuleKanban strings, re-emit ChoyButton click through the nested host, and tighten web-builder/e2e guards from review suggestions. * fix(auth,web): harden company pick and ChoyButton handleClick coverage Require a known JWT active company before reusing the draft selection, scope switch-company DOM lookups to the open panel, and cover ChoyButton.handleClick for patch coverage. * fix(web,auth): suppress disabled ChoyButton clicks Keep non-button disabled hosts from emitting click, and use an explicit .ts import for the e2e company-pick helper. * fix(web,auth): inert disabled anchors and tighten e2e races PreventDefault on disabled non-button hosts, read JWT active after the company draft, flush before timezone select success, and restore stub attrs. * fix(web): keep disabled link buttons out of tab order Non-button hosts ignore disabled: styles; set tabindex=-1 with aria-disabled and cover the enabled as=a click re-emit path. * fix(web,auth): drop disabled link href and harden review follow-ups Prevent middle-click navigation on disabled as=a hosts, scope company select visibility to the switch panel, settle timezone draft before Save, and match xpath placeholders with whitespace-tolerant regex. * fix(web,auth): style disabled link hosts and harden company pick Apply pointer-events/opacity on disabled non-button Button hosts, skip disabled company options, and re-assert the select value inside the poll. * fix(auth,web): tighten shell merge assert and setup reuse Require the parent double-quoted header-actions anchor after merge, poll JWT active company through token rotation, and only reuse plain parent setup state (skip script-setup render functions). * fix(web): stop disabled click bubble and broaden xpath assert Match leftover Xpath placeholders in any components-object position, and stopPropagation on disabled Button/ChoyButton hosts so ancestors do not treat the control as enabled. * fix(auth,web): assert ChoyLayout registration and plain setup reuse Require ChoyLayout inside the merged components map, surface the active company JWT error via a bounded wait loop, and reject non-plain parent setup results (Map/class/Ref). * fix(auth,web): re-read company draft and fail async setup reuse Re-read the company select after the JWT wait, reject Promise parent setup results instead of silently dropping them, and hoist merged components regexes used by the shell merge asserts. * fix(web,auth): settle company draft and harden disabled nav attrs Flush Vue before declaring the company select settled, drop to/target on disabled non-button hosts, fail fast when the reload status row is missing, and reject thenable parent setup results. * fix(web,auth): refresh company options and harden disabled clicks Re-read company option values after the JWT wait, guard disabled handleClick against non-Event payloads, and bind data-anchor explicitly so caller attrs cannot override the framework anchor. * fix(auth): pick company option from a single post-wait snapshot Drop the pre-wait values fallback so current and options always come from one post-JWT-wait read, and cover picks when current is absent from the values list. * fix(auth,web): stabilize JWT reads and tighten setup/key checks Require two consecutive identical active-company JWT reads, settle the company select draft before Apply, drop reactive/readonly parent setup state, and anchor merged-components regexes on real component keys. * fix(web,auth): harden JWT retry, noopener blank targets, and setup copy Catch transient evaluate failures in the active-company JWT loop, add noopener for enabled _blank hosts (and strip rel when disabled), and return a shallow copy from reuseParentSetupState. * fix(web,auth): merge noopener into rel and harden setup/JWT diagnostics Merge noopener into existing _blank rel tokens, fail fast when the base shell exposes no setup, surface last JWT read errors after the retry budget, and use a realm-agnostic plain-object prototype check. * test(web): lock components regex against later value references Assert that ChoyLayout as a value after another entry does not satisfy the merged-components key matcher (the claimed false-positive case).
…451) * feat(web): PR9z cutover — absorb engines, drop EP/echarts/choy_ui, CI bans Finish the Choy UI kit cutover on the integration branch: merge O* engines into Choy*/neutral internals, remove Element Plus/echarts/choy_ui dual-stack, wire Dialog confirm + Lucide, enable CutoverImportBans with CI grep gates. BREAKING CHANGE: out-of-tree O*/el-* and legacy slot anchors are intentionally removed ahead of feat/choy-ui-kit → main. * fix(web): unblock PR9z CI after choy_ui cutover Add missing lucide FE stub exports, close PropertiesField textarea for SFC parse, and align Tailwind kit tests with web-only resolveChoyKitModuleRoot. * refactor(web): camelCase helpers/i18n modules and Choy* test names Align web file names with component-side camelCase, retarget Choy* SUT tests, and drop obsolete ohtml/oproperties/tiptap helpers. * feat(web): finish PR9z Choy field absorb and domain wiring - Absorb store engines into Choy* fields; drop parallel *Engine/Page/Form/List leftovers - Add Int/Bigint/Decimal/Ref/Kanban field exports; restore store StatusbarField - Merge properties helpers; unify bare field i18n scopes and sync PO - Wire domain views to correct Choy* types (decimal, ManyToOne vs Ref) * refactor(web): drop product SCSS and ambient dayjs plugin types - Convert modules/web styles to plain CSS; strip lang=scss from web/auth Vue SFCs - Declare dayjs/plugin/* (and locale/*) for IDE; CLI typecheck already stubbed these * refactor(web): route list tables through DataTable via ChoyTableHost Replace the legacy VTable engine with an adapter host so List, O2M, and M2M share the L3 DataTable path while ChoyVColumn registration stays unchanged. Gallery keeps a direct DataTable dogfood. * refactor(web): move column DSL to components/table as ChoyTableColumn * refactor(web): rename ChoyVColumn to ChoyTableColumn across kit and domains Finish the public column DSL rename after the table/ path move so List, O2M/M2M, FieldBase, and domain list views share one semantic export. * refactor(web): rename table composable and choy-* CSS classes - rename useVTable to useTable and TableColumnMeta helpers - replace o-* DOM/CSS and --o-* tokens with choy-* - drop dead el-tag deep styles in Search and M2M tags - refresh gallery boot comment after choy_ui removal * feat(web): add optional store engine to ChoyKanbanView - extract useChoyKanbanStoreEngine and shared kanban store helpers - migrate Token/Module kanban hosts off chrome-only lane glue - keep Gallery chrome-only via v-model:lanes without store * refactor(web)!: drop Gallery/Dogfood and make views store-only - remove Gallery/Dogfood pages, choyGallery routes, and gallery token scopes - require store for Kanban/Search; wire ChartView to createChartController - document Form/List as store-only; keep field dual-mode for FE unit BREAKING CHANGE: /web/__choy_gallery and Dogfood pages are gone; ChoyKanbanView, ChoySearchView, and ChoyChartView require :store or a page store (no chrome dual-mode). * fix(web): address PR #451 review bugs and raise field coverage Wire native field bindings (value/onInput, checkbox checked/change), confirm cancel/dismiss + pending settle, SearchFilterGroup AND/OR, import remapping, image/binary drop, properties date ISO round-trip, and kanban bootstrap retry. Add mount tests for scalar/temporal/relation Choy fields to close Codecov gaps. * test(web): tighten M2O and O2M field mount coverage Cover remaining ManyToOne search/keydown edges via setupState and expand OneToMany add/display/ensureArray paths so patch misses stay near zero. * fix(web): address PR review, typecheck, and patch coverage Drop inert FieldBase cell prop/rules bindings, catch Chart bootstrap and List search/sort/paginate rejections, fix O2M handle typecheck, and raise field/tailwind unit coverage toward Codecov patch 100%. * fix(web): resolve ViewScope tag, typecheck, and server sort toggle Align ChoyViewScope imports with template tags, fix M2M mount typecheck, mark CommitStrategy as type-only, cycle server-side DataTable sort, and drop leftover Search tooltip attrs. * fix(ci): clear web i18n pot-dirty and harden legacy-import gate Re-extract Search after dropping _t('Search'), scope skip-dir checks to modules_root, and strip comments only outside string literals. * fix(web): restore client field rules and harden IO/image UX Wire FieldBase RuleItem evaluation into FormView submit, warn on Import/Export without a model, align attachment value types, and reject non-raster image uploads. * fix(web): drop remaining el-* fields, gate tags, unblock partner e2e Replace M2O/Tags select-v2 with RelationCombobox and M2M tree with RelationTree; scan Vue el-* tags in CI; allow Language:read on Login and wait for ChoyPage loading in e2e login. * fix(web): clear i18n pot-dirty, tighten validation/gate, cover Tags/Tree Sync web pot/po after RelationCombobox cutover; treat empty arrays as required-empty; ban export-star re-exports; add Tags/Tree mount coverage. * fix(web): native textarea, per-instance validators, drop v-loading Replace invalid input type=textarea, isolate FieldBase client-validator map keys, replace Element Plus v-loading with aria-busy, and keep search filter field select controlled via the parent update path. * fix(web): accurate el-tag lines, keep host blob URLs, enforce binary accept Blank HTML comments in place for vue tag line mapping; stop revoking host-owned blob previews on image replace/remove; reject files outside the accept allow-list for binary upload/drop. * fix(web): carry template quotes in import gate; honor Ref baseIndex Keep backtick string state across lines in the legacy-import scanner, unwrap Ref baseIndex in ChoyTableHost, drop duplicate StatInfo class, and rename FieldBase defineOptions off the legacy OFieldBase name.
* refactor(web): migrate Vue styles off --el-* onto --choy-* + Tailwind Replace dead Element Plus CSS vars/selectors with Choy tokens, move layout chrome to utilities, share field display styles, and CI-ban leftover --el-/.el- in product vue/css. * refactor(web): clear product Vue styles via Tailwind (waves 1–4) - migrate auth/meta/web scoped CSS to utilities; drop field-display.css - keep BEM/test hooks (Search, Filter, tags, image preview, etc.) * refactor(web): point boot spinner at --choy-* with hex fallbacks * refactor(web): slim styles to tokens + index (+ theme dialect) - drop empty preflight/override and unused transition/a11y/variable CSS - fold direction defaults and fade/a11y residuals into tokens/index - unify motion tokens; simplify link hover/active colors * fix(web): address PR #452 review on a11y, truncate, el-* scan - theme-aware high-contrast focus outline - inline-block max-w-full so display truncate can ellipsize - detect .el-* in compound CSS selectors; extend scanner tests * fix(web): address PR-agent style suggestions from #452 - map info-subtle in theme; restore dialog/upload/properties/inline layouts - bold m2m suggestion hits; highlight unread notifications; drop dead mdd-card * fix(web): typecheck DropdownMenuItem class; split m2o display colors - avoid object-key with spaces on unread menu item class binding - mutually exclusive text-foreground vs text-primary for clickable m2o * test(web): target search leading button by BEM class in behavior test
* fix(web): pin host Vue for reka-ui single-instance mounts Web builds skipped a host vue bare-import pin, so reka-ui peers floated extra Vue runtimes and Toaster/ConfirmHost crashed with renderSlot `.ce`. * fix(web): take exact vue pin from modules/web package.json Make modules/web's exact vue peer the SSOT for host Vue/@vue/* pins; choysummount.VuePackageVersion remains fallback + sync-checked. * fix(web): narrow host Vue pin skip and cover BareImportPin Address PR review: only skip the five host-owned Vue runtime packages, normalize VueBareImportPinsFor input, and add tests for patch coverage. * refactor(web): generate VuePackageVersion from modules/web Keep modules/web/package.json as the only hand-edited Vue pin; go generate writes the choysummount fallback const and syncs bootstrap-web. * fix(web): dedupe Vue host pins and cover kit-host build path Address PR review: shared host package list, stricter exactVuePin, cached package.json reads, fallback warn, ReplaceAll bootstrap sync, and tests for building modules/web as the kit host. * fix(web): tighten exactVuePin SemVer checks for host pins Reject surplus core segments and empty prerelease/build suffixes so malformed versions fall back to the generated host pin; cover script.go fully. * fix(web): align Vue pin generator with exactVuePin rules Use IsExactVuePin in go generate, find repo root via go.mod, suppress misleading missing-pin warns on unreadable package.json, and assert domain @vue/runtime-dom cannot override the host. * fix(web): harden Vue pin fallback warn and generator safety - Warn when kit exact vue fails host exactVuePin and falls back - Resolve gen output via runtime.Caller; require unique bootstrap vue rewrite * fix(web): harden Vue pin validation and generator ordering - Fail FE host when kit exact vue fails IsExactVuePin - Normalize declared vue before rejection warn; sync bootstrap before write - Assert IsExactVuePin with explicit expected booleans * fix(web): harden Vue pin sync formatting and SemVer checks - Tolerate compact JSON when syncing bootstrap vue; write vue_version.go atomically - Fail FE host when kit package.json lacks an exact vue pin - Reject leading-zero SemVer core components in exactVuePin * fix(web): align Vue pin warn with IsExactVuePin and harden generate - Reuse IsExactVuePin for kit rejection warn; chmod generated file to 0644 - Assert full fallback Vue bare-import pin map in FE host tests * fix(web): atomic bootstrap vue sync and pin prerelease coverage - Write bootstrap package.json via temp+rename like vue_version.go - Assert WithBareImportPins keeps prerelease/build Vue host pins
* fix(web): avoid aria-hidden on focused ChoyPage during loading - Prefer inert + aria-busy over aria-hidden so login submit focus cannot warn - Blur focused descendants before loading masks the page chrome * fix(web): unstick ChoyPage loading focus typecheck and coverage - Widen blur root typing to avoid ParentNode vs Vue/TipTap HTMLElement mismatch - Blur on immediate watch + onMounted; cover nested/throwing blur and loading reverse * test(web): assert ChoyPage loading watcher invokes blur helper - Add a test seam so mount tests observe blurFocusedDescendant calls - Clarify sync-throw coverage; skip speculative aria-hidden/thenable changes
* feat(web): emerald shell redesign with built-in sidebar and denser chrome Wire ChoyWebShell to own brand header + sidebar menu, switch tokens to emerald primary, and polish Login/Register/Home plus Form/List density so the ERP shell reads as one usable product surface. * fix(web): address PR #455 review findings and patch coverage Expand inactive sidebar groups in useMenu, skip disabled shortcut entries, harden soft router guards, fix auth calc/@layer/separator, and add Home/Grid/Shell tests for full patch coverage. * test(web): cover useMenu sidebar expand and harden shortcuts Add useMenu/ChoyWebShell coverage for manual submenu expand/collapse, accept root-relative shortcut paths with cycle guards, and fall back sidebar width to 15rem when the layout token is unset.
* feat(web): bind L2 controls to density control-height tokens Introduce --choy-control-height (32/28) and theme utilities h-control / size-control so Button, Input, Select, Combobox, and Tabs share one ruler without stray h-9/h-10, and use logical inset/padding for RTL overlays. * docs(web): record vendor/ui product patch history Document the allowed L2 contract-patch policy and the control-height / logical-chrome changes so upstream refreshes can replay them from vendor/ui/HISTORY.md instead of rediscovering diffs. * fix(web): address W0 review feedback on control ruler Unify sm/lg under --choy-control-height-*, make Switch LTR/RTL thumb rules mutually exclusive, align ToastClose to focus-visible, fix the HISTORY rg word-boundary pattern, and lock h-control emission with a Go theme dialect test (stock TW spacing rename would invent p-control).
* feat(web): W1 Dense Admin App shell with rail attribution Wire ChoyWebShell to layoutStore for expanded/collapsed/mobile drawer, pin open-source attribution in the nav rail foot, keep auth header-actions xpath anchors, and stub brand land path via resolveDefaultLandPath until W4. * fix(web): bind Top bar height to control ruler Dense Admin contract expects Top bar height ≈ control; point --choy-layout-header-height at --choy-control-height so comfortable/ compact density stays one source of truth. * fix(web): harden W1 mobile drawer a11y and patch coverage Address PR #457 review feedback: modal drawer semantics, header above backdrop, body scroll lock, Escape guard, deterministic layoutStore viewport pins, and FE tests to cover the shell/layout patch at 100%. * fix(web): preserve scroll lock and inert header on drawer Address PR-agent follow-ups: restore prior body overflow on unlock, make pinViewportWidth writable, mark overlay header inert, and reset overflow after drawer tests. * fix(web): post-flush drawer focus and robust viewport media pin Restore menu-trigger focus after inert clears (watch flush post), and teach pinViewportWidth to ignore non-width media clauses and fractional px thresholds used by VueUse breakpoints.
* feat(web): W2 Page chrome, Feedback, Pagination, table density Dense Admin W2: densify Page chrome, add ActionTray/Skeleton/Badge, export Confirm with destructive option, unify kit Pagination with pageSize reset, bind list/table row defaults to control height, and fix Boolean display to plain text (no disabled input wall). * fix(web): address PR #458 review and patch coverage gaps Wire destructive confirms on delete callers, include description in ChoyPage header, merge out-of-range pageSize into select options, and cover ActionTray/Badge/ConfirmHost/Pagination/estimateSize helpers.
* feat(web): W3 List/Form/Search chrome and remaining field families Wire Action tray on List/Form, adapt ListPagination to ChoyPagination, add Search Clear-all with locked instant strategy, summarize O2M/M2M in list cells, and densify Properties/scalars/Statusbar/Terminology. * fix(web): address PR #459 review feedback Singular relation counts, defer ListPagination until total is known, name action toolbars, cancel Clear-all debounce, coerce pageSize, and tighten Clear-all / Properties a11y assertions. * fix(web): tighten pagination guards and Properties a11y Sanitize non-finite totals, skip no-op pageSize emits, short-circuit empty Clear-all, use dt/dd for readonly Properties, and assert exact relation summary text.
* feat(web): W3b Kanban/Chart dense page chrome Rewrite Kanban with ActionTray, vuedraggable, mobile lane select, and move-to-lane menu; densify Chart controls with i18n empty/load/error. * fix(web): address W3b review and raise Kanban patch coverage Scope card Enter to .self, clear chart no-group stale errors, and cover drag/move/error/mobile paths plus the vuedraggable FE stub.
* feat(web): W4 default land path and retire Home/Welcome Implement menu DFS → Module Board land path for /, catch-all, and brand click; register Error routes; remove Home/Welcome/shortcuts and /home soft-land special case. * fix(web): harden default land path and cover remaining branches Add menu DFS cycle guards, skip route-denied leaves at runtime via canRoute, strengthen Home retirement assertions, and hit order-tie / empty-subtree coverage paths. * fix(web): harden land-path catch-all and fail-closed canNavigate Prevent CatchAll self-redirect loops, filter nullish menu nodes before sort, and skip unverifiable resolve paths so DFS can fall through; cover to 100%.
…es (#497) (#502) * chore: bump the go-minor-patch group across 1 directory with 20 updates Bumps the go-minor-patch group with 20 updates in the / directory: | Package | From | To | | --- | --- | --- | | [github.com/antchfx/htmlquery](https://github.com/antchfx/htmlquery) | `1.3.6` | `1.3.7` | | [github.com/chromedp/cdproto](https://github.com/chromedp/cdproto) | `0.0.0-20260714215040-dc233986426f` | `0.158.0` | | [github.com/chromedp/chromedp](https://github.com/chromedp/chromedp) | `0.16.0` | `0.21.0` | | [github.com/leonelquinteros/gotext](https://github.com/leonelquinteros/gotext) | `1.7.2` | `1.8.0` | | [github.com/minio/minio-go/v7](https://github.com/minio/minio-go) | `7.3.0` | `7.4.1` | | [github.com/shopspring/decimal](https://github.com/shopspring/decimal) | `1.4.0` | `1.5.0` | | [go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc](https://github.com/open-telemetry/opentelemetry-go-contrib) | `0.71.0` | `0.72.0` | | [go.opentelemetry.io/otel](https://github.com/open-telemetry/opentelemetry-go) | `1.46.0` | `1.47.0` | | [go.opentelemetry.io/otel/exporters/stdout/stdoutmetric](https://github.com/open-telemetry/opentelemetry-go) | `1.46.0` | `1.47.0` | | [go.opentelemetry.io/otel/exporters/stdout/stdouttrace](https://github.com/open-telemetry/opentelemetry-go) | `1.46.0` | `1.47.0` | | [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go) | `1.46.0` | `1.47.0` | | [go.opentelemetry.io/otel/sdk/metric](https://github.com/open-telemetry/opentelemetry-go) | `1.46.0` | `1.47.0` | | [go.opentelemetry.io/otel/trace](https://github.com/open-telemetry/opentelemetry-go) | `1.46.0` | `1.47.0` | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.57.0` | `0.58.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.59.0` | `0.60.0` | | [golang.org/x/sync](https://github.com/golang/sync) | `0.23.0` | `0.24.0` | | [golang.org/x/term](https://github.com/golang/term) | `0.46.0` | `0.47.0` | | [golang.org/x/text](https://github.com/golang/text) | `0.42.0` | `0.43.0` | | [go.opentelemetry.io/otel/metric](https://github.com/open-telemetry/opentelemetry-go) | `1.46.0` | `1.47.0` | | [golang.org/x/mod](https://github.com/golang/mod) | `0.41.0` | `0.42.0` | Updates `github.com/antchfx/htmlquery` from 1.3.6 to 1.3.7 - [Release notes](https://github.com/antchfx/htmlquery/releases) - [Commits](antchfx/htmlquery@v1.3.6...v1.3.7) Updates `github.com/chromedp/cdproto` from 0.0.0-20260714215040-dc233986426f to 0.158.0 - [Changelog](https://github.com/chromedp/cdproto/blob/main/CHANGELOG.md) - [Commits](https://github.com/chromedp/cdproto/commits/v0.158.0) Updates `github.com/chromedp/chromedp` from 0.16.0 to 0.21.0 - [Release notes](https://github.com/chromedp/chromedp/releases) - [Commits](chromedp/chromedp@v0.16.0...v0.21.0) Updates `github.com/leonelquinteros/gotext` from 1.7.2 to 1.8.0 - [Release notes](https://github.com/leonelquinteros/gotext/releases) - [Commits](leonelquinteros/gotext@v1.7.2...v1.8.0) Updates `github.com/minio/minio-go/v7` from 7.3.0 to 7.4.1 - [Release notes](https://github.com/minio/minio-go/releases) - [Commits](minio/minio-go@v7.3.0...v7.4.1) Updates `github.com/shopspring/decimal` from 1.4.0 to 1.5.0 - [Release notes](https://github.com/shopspring/decimal/releases) - [Changelog](https://github.com/shopspring/decimal/blob/master/CHANGELOG.md) - [Commits](shopspring/decimal@v1.4.0...v1.5.0) Updates `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc` from 0.71.0 to 0.72.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go-contrib@zpages/v0.71.0...zpages/v0.72.0) Updates `go.opentelemetry.io/otel` from 1.46.0 to 1.47.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.46.0...v1.47.0) Updates `go.opentelemetry.io/otel/exporters/stdout/stdoutmetric` from 1.46.0 to 1.47.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.46.0...v1.47.0) Updates `go.opentelemetry.io/otel/exporters/stdout/stdouttrace` from 1.46.0 to 1.47.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.46.0...v1.47.0) Updates `go.opentelemetry.io/otel/sdk` from 1.46.0 to 1.47.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.46.0...v1.47.0) Updates `go.opentelemetry.io/otel/sdk/metric` from 1.46.0 to 1.47.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.46.0...v1.47.0) Updates `go.opentelemetry.io/otel/trace` from 1.46.0 to 1.47.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.46.0...v1.47.0) Updates `golang.org/x/crypto` from 0.57.0 to 0.58.0 - [Commits](golang/crypto@v0.57.0...v0.58.0) Updates `golang.org/x/net` from 0.59.0 to 0.60.0 - [Commits](golang/net@v0.59.0...v0.60.0) Updates `golang.org/x/sync` from 0.23.0 to 0.24.0 - [Commits](golang/sync@v0.23.0...v0.24.0) Updates `golang.org/x/term` from 0.46.0 to 0.47.0 - [Commits](golang/term@v0.46.0...v0.47.0) Updates `golang.org/x/text` from 0.42.0 to 0.43.0 - [Release notes](https://github.com/golang/text/releases) - [Commits](golang/text@v0.42.0...v0.43.0) Updates `go.opentelemetry.io/otel/metric` from 1.46.0 to 1.47.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-go@v1.46.0...v1.47.0) Updates `golang.org/x/mod` from 0.41.0 to 0.42.0 - [Commits](golang/mod@v0.41.0...v0.42.0) --- updated-dependencies: - dependency-name: github.com/antchfx/htmlquery dependency-version: 1.3.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-minor-patch - dependency-name: github.com/chromedp/cdproto dependency-version: 0.158.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: github.com/chromedp/chromedp dependency-version: 0.21.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: github.com/leonelquinteros/gotext dependency-version: 1.8.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: github.com/minio/minio-go/v7 dependency-version: 7.4.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: github.com/shopspring/decimal dependency-version: 1.5.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc dependency-version: 0.72.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: go.opentelemetry.io/otel dependency-version: 1.47.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: go.opentelemetry.io/otel/exporters/stdout/stdoutmetric dependency-version: 1.47.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: go.opentelemetry.io/otel/exporters/stdout/stdouttrace dependency-version: 1.47.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: go.opentelemetry.io/otel/sdk dependency-version: 1.47.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: go.opentelemetry.io/otel/sdk/metric dependency-version: 1.47.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: go.opentelemetry.io/otel/trace dependency-version: 1.47.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: golang.org/x/crypto dependency-version: 0.58.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: golang.org/x/net dependency-version: 0.60.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: golang.org/x/sync dependency-version: 0.24.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: golang.org/x/term dependency-version: 0.47.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: golang.org/x/text dependency-version: 0.43.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: go.opentelemetry.io/otel/metric dependency-version: 1.47.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch - dependency-name: golang.org/x/mod dependency-version: 0.42.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-patch ... * fix(e2e): adapt CDP wrapper to chromedp v0.21 generic API Dependabot's chromedp/cdproto bump replaced Action/Run builders and ListenTarget with Do/Run generics, Command+Call, and Events iterators. Update the e2e CDP host so the go-minor-patch PR compiles again. * fix(e2e): cover pageEvaluate errors and harden network finish race Exercise the default pageEvaluate error path for Codecov patch coverage, and remember early LoadingFinished IDs so ResponseReceived still completes waiters under chromedp's unordered Events iterators. * fix(e2e): subscribe chromedp Events before enable/wait Hoist Events construction onto the calling goroutine so Fetch/Network cannot miss events between Enable and ranging; document Go 1.27.x required by gotext. * fix(e2e): bound finishedEarly and fail NewPage setup errors Only record LoadingFinished in finishedEarly for pending requests, and clear pending/early entries on match filter; propagate cookie clear and about:blank reset failures from NewPage. * test(e2e): cover NewPage setup errors and finishedEarly pending Add injectable hooks for cookie clear / about:blank reset, and unit-test noteFinishedEarlyIfPending so patch coverage reaches 100%. --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* refactor(web): collapse field chrome into FieldBase - Inline vendor Field chrome in the FieldBase form branch - Make ChoyHtmlField a store field - Remove ChoyFormItem, ChoyFieldBase, and their kit exports * fix(web): typecheck Html aggregates and cover the editor - Pass one type argument to NarrowAggProp so web typecheck succeeds - Keep the editor id on the content node and forward aria-required - Exercise TipTap edit, link prompts, and empty-doc sync in FE tests - Size the reserved error line like FieldError * fix(testing): hold CDP responses until request method is known - Stop inventing ResponseMatch.Method from the filter when RequestWillBeSent races behind ResponseReceived - Put Html field a11y attrs on the TipTap contenteditable node - Merge Statusbar formItemProps.class through cn; avoid empty FieldLabel markup * fix(testing): finish held CDP responses after early LoadingFinished - Keep a pending placeholder while the method is unknown so LoadingFinished is not lost - Bind the TipTap stub view.dom to the mounted contenteditable for live a11y attrs - Cover matching hold replay and stub attribute helpers
* refactor(web): rename FieldBase to ChoyFieldBase Align the field shell with the Choy*Field naming so third-party modules can treat ChoyFieldBase as the stable kit extension point. Export the component and FormItemProps/FieldStateExpr from kit.ts; keep choy-field-base CSS/anchor tokens unchanged. * fix(web): sync ChoyFieldBase i18n scopes after rename Update zh_CN.po/web.pot msgctxt and source refs so translate lookups match createTranslate scope, and clarify the component-name test title.
* refactor(web): field FW1 naming and display hygiene
Hard-cut Choy* defineOptions/i18n scopes, rename O*Cell internals,
drop EP display padding magic, and align destructive text tokens.
* feat(web): field form chrome, Combobox selection, and temporal pickers
- horizontal ChoyFieldBase label|value with orientation and start-align so errors do not shift labels
- rewrite scalar cells onto L2 controls; Selection uses Combobox with sticky search and check
- Date/Time/Datetime Popover pickers with UI locale, i18n, and in-trigger clear
- record Combobox kit patches in vendor/ui HISTORY and sync zh_CN terms
* feat(web): typed view switching, row payloads, and sandbox kitchen-sink
- add opt-in sandbox module (list/kanban/chart/form) with FE unit coverage
- introduce useChoyViewRouteSwitch plus route meta (viewKind/viewPaths/defaultGroups)
- type list/kanban row clicks via RowEventPayload; drop ad-hoc list_row_nav helpers
- fix data-loader topo tie-break to compare recordIndex numerically
- clear column metadata on virtual related fields so repository SELECT stays honest
- harden Register mount selectors for Reka checkbox and submit button
* feat(web): polish Text-family fields with Char wrapper and editor chrome
- add ChoyCharField thin wrap and trim char pads for accurate word counts
- wire word-limit, autosize resize-none, form empty placeholders, varchar widgets
- HTML toolbar icons with tooltips and link popover; JSON edit shell plus Format
* fix(web): show selection Combobox search text as option label
* fix(core): resolve monetary currencyField and ManyToOneRef write ids
Keep Amount.currencyField through parser/codegen, fall back to the row
currency when the patch companion is display-only, soft-skip onchange
preview stamp without a resolvable currency, and treat ManyToOneRef like
ManyToOne in update diffs so hydrated objects do not enter write patches.
* fix(web): attach monetary currency companions on form submit
When Amount (or other monetary fields) is written, ensure the currencyField
id is stamped from draft/original so display-only CurrencyId objects cannot
clear the FK and trip scale-stamp E1 on create/update.
* fix(web): keep CurrencyId selectable with nested monetary companions
exportFieldSelection previously dropped bare CurrencyId once nested paths
like CurrencyId.DecimalDigits were registered, so Browse omitted the FK and
ManyToOneRef never hydrated DisplayName. Keep parent leaf paths, register
DisplayName with currency siblings, and load labels via field-local Browse
into options without rewriting draft.
* feat(web): align numeric columns end and media/boolean columns center
Drive list/form cell justification from field type helpers so Number and
Monetary values sit at the end, while boolean/binary/image cells center.
Normalize index columns to align end across host tables.
* chore(sandbox): use FlaskConical icon for field playground menu
Distinguish the kitchen-sink sandbox entry from meta's Boxes icon and
stub FlaskConical in the FE lucide stub set.
* fix(web): toast on copyable VarcharField clipboard copy
Surface success/failure via ChoyMessage so form display copy is not silent.
* feat(web): add seconds column to DateTimePicker
Align datetime wire format with TimePicker (YYYY-MM-DDTHH:mm:ss) while
still accepting legacy minute-only values.
* feat(web): restyle Statusbar as chevron ribbon and unify field help
- replace ToggleGroup with a radiogroup chevron ribbon using primary soft tokens
- share Tooltip + cursor-help for form and inline help; drop native title doubles
* feat(web): rewrite Html/Json fields with TipTap polish and CodeMirror
- expand Html toolbar (headings, quote, code, undo/redo) and editor chrome
- edit Json with CM6 + localized lint tips; keep vue-json-pretty for form display
* fix(web): clear field label a11y issues and polish attachments
- Wire FieldBase label for/id/name; composite fields use aria-labelledby
- Extract AttachmentFieldChrome for Binary/Image upload and preview
- Drop TipTap extension-link peer (StarterKit already includes Link)
- Coerce legacy RoleRecordRule domain lists; wrap message RR in And
- Skip gzip on /_document/ and ASCII-sanitize Content-Disposition filenames
- Default image Bind disposition to inline; enrich descriptors with sizeBytes
* feat(web): hard-cut Properties to L2 single path (FW8)
- Merge definition editor onto L2+RPC; delete Draft parallel UI
- Rewrite ChoyPropertiesField with L2 controls, display formatting, and text numeric drafts (resync like Int/Number)
- Add sandbox PropertyDefinition model plus bootstrap schema for kitchen-sink hand tests
* fix(lifecycle): cascade-delete MetaModelData seed rows on uninstall
Hard-delete business rows pointed at by a module's xml_id mappings before
clearing the mappings (E15), so reinstall can Create without unique conflicts.
Use SAVEPOINTs on Postgres/MySQL so FK multi-pass deletes do not abort the
uninstall transaction.
* chore(sandbox): drop handwritten PropertyDefinition store
Rely on the forced per-app PropertyDefinition inject instead of a
duplicate hand-written model.
* fix(web): stop properties update patches from wiping sibling keys
Form UpdateById used nested microdiff for Properties maps, so changing
one key sent a partial column that the BE whole-replace write cleared.
Send original∪current for properties/jsonobject maps, collapse nested
plain-map diffs, and keep prior values when ResolveProperties is empty.
* fix(orm): inject related/compute on Browse and blank empty displays
Browse left LineCount/CategoryName empty because compute/related inject could
not see $rel$ (M2O FK scalars shadowed objects); keep PrimaryLineId virtual
and stop wrapping injected M2O records as {Id: object}. Form/StatInfo/chatter
empty states render blank instead of em dash or "No content".
* fix(web): polish field controls and Odoo-like M2O typeahead
- Unify Input/Select/Combobox/DateTime open chrome (thin border-ring, flush popover)
- RelationCombobox: keep options on reopen, skip short-list virtual flicker
- Search with empty keyword until the user edits (full page on focus)
* perf(web): memoize identical ManyToOne NameSearch requests
- Reuse the last NameSearch when query, searchKey, and pageSize match
- Short-circuit empty-prefix queries; fingerprint domain in searchKey
* fix(web): align M2O Search more with NameSearch conditions
- thread relationConditionSource through List Search/Count (and BE Count)
- use forcedCondition in the picker; reset leftover keyword/filters on open
- hide page title and selection column; drop blank combobox options
* fix(web): polish Search more and calendar selected hover
- style Search more as a primary action like Create
- keep selected calendar days on primary through hover/focus
* feat(web): add same-app M2M Tags/Tree fields and harden relation pickers
- ship ChoyManyToManyTagsField and ChoyManyToManyTreeField with shared helpers
- polish M2M list chrome, empty-state layout, and Add a line… copy
- hide picker empty New; close picker before Create; add Tag create routes
* feat(sandbox): wire same-app M2M Tags and Tree widgets
- add TagChips and Categories ManyToMany fields with join models
- bind ChoyManyToManyTagsField / ChoyManyToManyTreeField on the form
- cover metadata and form widget wiring with unit tests
* feat(web): harden M2M Tags/Tree widgets and adaptive tree height
- rebuild Tags/RefTags with badge shell and plain RelationCombobox chrome
- land RelationTree checkbox cascade and keep TagChips sparse M2M diffs safe
- default treeHeight to auto via shared resolveTreeBoxStyle; drop min-height padding
- softDelete false on sandbox M2M joins; i18n for Tag Chips/Categories
* fix(server): keep run alive on hotreload upgrade failure
- soft-fail watch upgrade/build errors instead of exiting serve
- write bundles entry under _choysum_entry/ so it is not colocated with Outfile
* fix(web): align RelationTree first row with form field labels
* fix(web): remove double border above M2M add-line footer
* feat(web): restore M2M Ref list field and polish relation empty UX
- add ChoyManyToManyRefField (kit export, mount tests, sandbox TagTableRefIds)
- default vertical orientation and hideLabel on FieldBase / M2M / O2M list fields
- display empty: Tags blank; M2M/M2MRef/O2M keep header only (no None/No data)
- extract and translate RefField zh_CN terms (Add a line…, Actions, …)
* feat(web): polish O2M table/kanban and fix select-only saves
- strip select-only computes from Create/Update and collection follow-up writes
- mark FieldsGet select-only as isReadonly; Form/diff omit them from patches
- O2M kanban: host delete chrome, safe dialog delete, hover actions, Sequence drag
- ChoyTab forceMount keeps sibling O2M fields registered across table/kanban tabs
- align table confirm-on-remove; Sandbox Lines CASCADE and dual-tab wiring
- hotreload: ignore *.test.* and auto-retry module_management LEASE_CONFLICT
* feat(web): virtualize capped O2M/M2M tables and O2M kanban boards
- auto-virtualize embedded tables only when height is capped
- add wrap-grid row virtualization for O2M kanban (threshold 40)
- seed VIRT-LINES and Sandbox fill/clear tools for hand testing
* feat(sandbox): add kitchen-sink onchange handlers
- demo domain, selection, value writes, and warn messages on SandboxRecord
- clamp SandboxLine Quantity with onchange warnings for hand tests
- cover handlers with backend unit tests and Form hint copy
* fix(web): remasure virtual tables after layout and tab show
- schedule virtualizer measure when virtualize turns on or height changes
- observe scrollport resize; notify on forceMount tab activation
- remasure O2M kanban boards when virtualization enables
* feat(web): align onchange messages with Odoo-like toast vs field errors
Clarify warn/info toast vs error+field inline delivery, style Sonner by
level tokens, and update Sandbox demos (silent Quantity clamp, IntValue
field error, Progress statusbar via selection+disabled).
* feat(web): close FW12 field a11y, real-chrome samples, and FE fixes
Wire describedBy/invalid through FieldBase and composite fields, drop
field el-button stubs, silence unconfigured M2M picker toasts, and fix
blob download attributes plus buildDiffFieldsMeta caching.
* fix(ci): unblock PR #508 typecheck, unit, and seed-cascade reviews
- add @tiptap/extension-link and tighten Vue/TS casts for web/sandbox typecheck
- align base/core tests with DisplayName strip and join-link success semantics
- harden seed cascade savepoints, SQL idents, and missing-table detection
* fix(ci): clear i18n pot drift, harden reviews, raise patch coverage
- extract/sync web+sandbox catalogs and fill new zh_CN msgstr
- validate related.path leaf; chunk blob→data URL; pass undefined original on create
- cover seed-cascade savepoints and lease-retry edges; ignore FE test stubs in Codecov
* fix(ci): address Tags review nits and close remaining patch coverage gaps
- make __rowKey redefinable; tighten selectedIds; guard O2M kanban reorder write
- expand seed-cascade/gzip/hotreload/diff tests; cover AttachmentFieldChrome
- ignore sandbox kitchen-sink view shells in Codecov (demo-only hosts)
* fix(ci): harden seed-cascade/hotreload reviews and close patch misses
Narrow Postgres missing-table detection, uniquify savepoints, clear lease
retry on dropped enqueue, and normalize gzip document bypass paths; add
targeted tests so remaining Go patch lines are covered.
* fix(ci): clear lease retry on abort and close FE patch coverage gaps
Clear hotreload leaseRetries when a retry is canceled, and add FE unit
coverage for core/utils/diff plus Attachment/Binary/Datetime edge paths
so Codecov JS patch hits reach 100%.
* test(web): cover layout nav/guest chrome and tidy flyout props Add dedicated FE tests for AppRailFlyout, GuestHeader/MobileNav, ShellHeaderTools, and PageTitleActions; rename flyout on* callbacks to leafSelect/hoverEnter/hoverLeave so mount helpers do not treat them as vnode listeners; refresh componentHint example. * fix(ci): refresh typecheck pkg cache and harden layout FE tests Bump CLI pkg cache to v7 and type-fetch per typecheck shard so poisoned v6 entries missing @codemirror types cannot fail web typecheck; strengthen Guest/TitleActions assertions and soft-guard optional flyout leafSelect.
* test(web): cover view chrome and drop Element Plus stubs Add dedicated FE tests for ViewBusyHost/ActionBar/Container/ButtonBox and viewBusy helpers; remove leftover El* mount stubs and el-* class names from List/Form/Search/StatInfo tests now that Choy chrome is the real surface. * fix(web): harden view chrome tests and skip empty container bands Collapse empty header/footer slots in ChoyViewContainer, mark ActionBar leading column with data-slot, and tighten BusyHost/ActionBar/Container assertions so regressions cannot pass on wrappers alone. * fix(web): unblock view chrome typecheck and harden FE asserts
* fix(web): drop Element Plus adaptive-height and test stubs Point dialog auto/container height at ChoyDialog data-slot surfaces and remove leftover El* smoke stubs. * test(web): harden adaptive-height dialog footer coverage
* fix(auth): stack login fields and honor password input type * docs(web): record Input type-vs-attrs vendor patch in HISTORY * fix(web): keep varchar widget default while honoring type= aliases
* fix(web): type O2M kanban #card slot so item is not {}
* fix(sandbox): give record form sheet breathing room and clearer phases
* fix(web): type O2M kanban card slots from relation rows
Derive #card/#toolbar item types from V and expose remove as
void | Promise<boolean> so consumers get real field checking.
* fix(web): give ChoySection divided titles a trailing rule with gap
Replace legend-on-border hairlines with a plain title plus flex trailing
rule, and apply the same chrome to the sandbox Identity section.
* fix(web): keep ChoySection divided rule when title row is absent
Divided sections with #header or no title skipped the hairline after the
title-row redesign; render a full-width rule in that case.
Co-authored-by: Brian Wang <[email protected]>
---------
Co-authored-by: Cursor Agent <[email protected]>
WalkthroughWarning Review details and warnings were omitted to fit the comment limit. |
Standalone PR ReviewPR-Agent could not safely update the persistent review. This standalone result will not replace the canonical review. PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Explore these optional code suggestions:
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
PR Code Suggestions ✨Explore these optional code suggestions:
|
Repair partner* O2M kanban typing, auth e2e against kit checkbox/combobox, CodeQL HTML/regex findings, sandbox i18n pot drift, and minor review cleanups. Co-authored-by: Brian Wang <[email protected]>
Satisfy noImplicitAny on the preferences Combobox assertion helper. Co-authored-by: Brian Wang <[email protected]>
Build the breadcrumb computed via a helper so items is assigned once. Co-authored-by: Brian Wang <[email protected]>
Avoid the overwritten identity stub that code-quality flagged. Co-authored-by: Brian Wang <[email protected]>
User description
Summary
ChoyFieldBase/ Choy* widgets, unify the openviewKindregistry, and polish list / kanban / chart / form surfaces (virtual lanes, quieter cards, chart hover, form density).#cardslots from relation rows (includes feat(web): align auth and shell chrome with shadcn blocks #470–fix(web): type O2M kanban #card slot so item is not {} #513 close-out).Test plan
maindividedtitles), O2M table + kanban card slot fieldsel-*product imports outside allowed vendor pathsPR Type
Enhancement, Bug fix, Tests
Description
Retire Element Plus: rewrite web UI onto Choy/shadcn-vue kit with new shells, fields, views, and Tailwind FullCSS generation.
Go core: add Tailwind generate/digest pipeline, exact package pins, forbidden UI import policy, and typecheck gate.
Go core fixes: hotreload lease retry, seed cascade uninstall, gzip/document MIME, parser and loader corrections.
Tests: broad Go and TypeScript/unit coverage for new kit, Tailwind, policy, and lifecycle paths.
File Walkthrough
51 files
Rewrite web builder tests for Choy shells, Tailwind hook, exact pinsAdd Tailwind generate, scan, digest and scoping testsAdd coverage tests for Tailwind generate edge pathsAdd coverage tests for forbidden UI import policyAdd uninstaller seed-row cascade and savepoint testsAdd SFC parser masking and self-closing tag testsAdd hotreload ignore, lease-conflict retry testsAdds tests for forbidden UI import classification and disk scanUpdates FE stub coverage for Choy kit packages and Page shellTests held-response replay and unknown-method handlingTests Tailwind digest inputs, engine version, and schema saltAdds Postgres index and sqlite origin-unique coverageTests Vue host bare import pin resolutionTests lease acquire error branches and unique detectionTests Vue pin helpers and package version syncTests serve resilience to watch handler and lease failuresUpdates uninstaller test to seed effective modelTests destructured export name extractionTests destructured binding export names in parse ctxTests gzip bypass for document paths and header handlingTests exact pin extraction from package.jsonTests sandbox amount currency and scale field parsingUpdates gateway tests to assert no wire principalTests numeric record index tie-break in topo orderTests e2e bundle exact pin error pathsTests typecheck forbidden UI import gateTests bundles entry dir creation errorTests BareImportPin accessor and prerelease pinsAdds repo-wide Choy Vue SFC parse smoke testLocks control height theme utility emissionAsserts base.Language read allowlist on auth entriesTests ASCII filename in content dispositionTests backend exact pin option applicationUpdates bundles entry path expectationUpdates bundles entry path expectationUpdates bundles entry path expectationUpdates bundles entry path expectationTests property name empty-text fallbackTests narrowed missing-table error detectionAdds Search behavior unit tests for Choy kitAdds M2M ref field mount testsAdds unit tests for chart view helper utilitiesAdds mount tests for ManyToOne field behaviorAdds mount tests for ManyToMany ref tags fieldAdds mount tests for ManyToMany tags fieldAdds lifecycle tests for form view composableAdds mount tests for field base chromeAdds mount tests for native scalar field widgetsAdds mount tests for ManyToMany table fieldAdds breadcrumb store and shell trail testsAdds chrome and drag tests for kanban view25 files
Add Go-native Tailwind FullCSS generate and digest pipelineFold Tailwind dialect, candidates and engine into web digestAdds forbidden kit import policy with cutover bansWires Tailwind generation, exact pins, and type-only import filteringAdds on-disk web tree scan for forbidden importsSwaps FE stubs to Choy kit packages and adds exact pinsAdds seed row cascade delete with savepointsAdds generator for Vue version from web package.jsonReplaces Element Plus stubs with Choy kit stubsDefers watch reloads on lease conflict with retriesAdds Vue pin helpers and exact SemVer validationExtracts destructured export names and prefers Text()Adds watch path ignore rules and lease conflict detectionAdds exact pin extraction and merge from package.jsonExtracts destructured binding names for exportsApplies exact package pins to backend resolverApplies exact pins without vue to e2e bundleAdds forbidden UI import gate to typecheckAllows base.Language read for login and refreshTracks per-file lease retry countersAdds BareImportPin accessor to resolverAdds generated Vue package version constantIgnores generated artifacts when enqueuing watch eventsAdds chart view helper functions and tooltip formattingAdds vendored message scroller composable engine12 files
Mask PascalCase raw-text tags and expand self-closing HTML tagsStrip non-ASCII from filename Content-Disposition parameterHolds responses until request method is knownAdds Postgres index inspection and sqlite origin uniquenessUses ON CONFLICT DO NOTHING for lease insertCascades seed deletes and narrows missing-table detectionFixes numeric record index tie-break in topo orderSkips gzip for document paths and fixes header handlingMoves bundles entry into dedicated subdirectoryKeeps server running on watch reload failuresPropagates scaleField and currencyField to meta fieldPrefers Text() for property names to avoid comments6 files
Drops wire principal from upload authorize and commitDrops wire principal from download resolveRemoves unused enabled company ID helperRemoves Element Plus and echarts ambient stubsDrops wire principal from binding source readRenames i18n modules and drops Element Plus locale loading101 files
Summary
ChoyFieldBase/ Choy* widgets, unify the openviewKindregistry, and polish list / kanban / chart / form surfaces (virtual lanes, quieter cards, chart hover, form density).#cardslots from relation rows (includes feat(web): align auth and shell chrome with shadcn blocks #470–fix(web): type O2M kanban #card slot so item is not {} #513 close-out).Test plan
maindividedtitles), O2M table + kanban card slot fieldsel-*product imports outside allowed vendor pathsNotes
RecordIndex, thenmodule.name. This replaces lexicographic string keys where"10"sorted before"2". Intentional correctness fix (seeloader.go+loader_test.go); application order for same-file multi-record seeds follows declaration index. FK/ref edges still drive dependency order — only independent-node tie-breaks change.