Preserve the implicit `src/**/*.ts` coverage when `tsconfig.app.json` has no
`include` key, so seeding the array for the generated libs no longer drops the
app's own `src` from the editor program.
Use a strict `!== null` guard before pinning `embla-carousel-angular` so the
intent is explicit rather than relying on Angular majors never being 0.
ng g @spartan-ng/cli:ui generates libraries under the configured directory (e.g.
libs/ui), outside the app's src. The app still builds - the Angular builder
follows the path-mapped imports into the libs - but the TS language server treats
the generated files as orphans compiled without the root paths mapping, so
cross-lib imports (@spartan-ng/helm/utils, ...) show as "cannot find module" in
the editor.
Add the components base dir to tsconfig.app.json's include so the generated files
belong to the app project and resolve in-editor. Idempotent and a no-op when there
is no tsconfig.app.json.
The carousel primitive declared embla-carousel-angular as ">=21.0.0 <23.0.0".
That package's major tracks the Angular major (v21 -> Angular 21, v22 -> Angular
22), so on an Angular 21 workspace npm resolved the highest match (22.x), whose
peer is @angular/common >=22.0.0, and the install failed with ERESOLVE.
A static range in supported-ui-libraries.json can't know the consumer's Angular
version, so pin embla-carousel-angular to the installed Angular major at generate
time. Falls back to the declared range when Angular can't be resolved.
The release job ran in parallel with cli-smoke. Because release publishes new
@spartan-ng versions to npm mid-run, the smoke healthcheck saw the package
"latest" change underneath it and the angular-cli cells failed.
Add commitlint and cli-smoke to the release job's `needs` so a red suite blocks
the publish, and so release waits for cli-smoke to finish before publishing -
which removes the concurrent-publish race.
The dependency healthcheck hardcoded registry.npmjs.org when resolving the
latest @spartan-ng/brain and @spartan-ng/cli versions. Under cli-smoke this
flagged the locally published packages as outdated, and `--auto-fix` then
rewrote package.json to a version absent from the local registry, so the
Angular CLI's post-generate install failed and the smoke test errored.
Resolve the latest version against npm_config_registry (falling back to npmjs)
so the check matches whatever registry the project installs from - the smoke
local registry, or a private registry for real users.
Addresses review feedback:
- dedupeEntrypointGlobs now only treats a pattern as an entrypoint variant when it
contains a `/**/` segment (the shape nx prepends), so flat custom globs like
`tools/*.ts` are preserved rather than widened to `**/*.ts`.
- Load the @nx/workspace remove generator with `require(absolutePath)` instead of
dynamic import: it bypasses the package exports gate and accepts native Windows
paths without a file:// URL (this generator runs as CommonJS).
No cell exercised the headline command as a published package, so the deep-import
breakage above shipped undetected. Each nx cell now runs migrate-helm-libraries
against the freshly scaffolded workspace before generating anything: with no spartan
libraries it no-ops ("No libraries to migrate") without prompting, but loading it
resolves the @nx/workspace/@nx/devkit deep imports in the installed CLI - so a
consumer's stricter exports map turns the cell red instead of reaching users.
- Normalize tsconfig.lib.json before the nx secondary-entrypoint call as well as
after: a workspace left bloated by an earlier run would otherwise re-double its
arrays and could throw "Invalid string length" before the post-call cleanup runs.
- dedupeEntrypointGlobs now restores a recursive glob only when a scoped variant of
it was present, and no longer treats a root-only `*.ts` as redundant. This stops it
injecting spec/test excludes a tsconfig never had and stops it widening `*.ts` to
`**/*.ts`. Exported with unit tests covering these cases.
migrate-helm-libraries imported removeGenerator from the deep path
@nx/workspace/src/generators/remove/remove at module top level. On nx 23 that
specifier is blocked by the package's exports map (and the compiled file moved to
dist/), so the generator failed to load with "Package subpath ... is not defined by
exports" - in every mode, before doing any work. The package entry point can't be
used either: it eagerly evaluates convert-to-nx-project whose output.js crashes
("Cannot read properties of undefined (reading 'inverse')").
Load it lazily, only when a library is actually removed (generateAs: library), and
resolve the compiled file by absolute path - bypassing the exports gate and never
loading the crashing barrel - trying dist/ (nx 23+) then src/ (nx <= 22).
- Add an all-components-nx-entry cell: all primitives as buildable secondary
entrypoints on nx. This is the shape that previously crashed with "Invalid string
length" and is now the regression guard for that fix. The existing all-components
cell stays on angular-cli.
- Fix per-cell filtering: describe.each('$id') rendered the id wrapped in quotes
(e.g. 'nx-entry-buildable'), so the CI --testNamePattern matched nothing and every
cell silently skipped. Use a plain describe(cell.id) loop for clean names.
- Disable the nx daemon in the throwaway workspaces. Under 50+ back-to-back generators
it intermittently crashed with "Failed to process project graph"; daemonless is
reliable and faster (no slow daemon retries).
- Register the new cell in the cli-smoke workflow matrix so the drift-guard passes.
migrate-icon and migrate-scroll-area imported applyChangesToString/ChangeType from
the deep path @nx/devkit/src/utils/string-change. That resolves inside this monorepo
(the dev @nx/devkit has no exports map) but throws "Package subpath ./src/utils/
string-change is not defined by exports" once the CLI is installed against a devkit
that declares exports, crashing the healthcheck generator that loads these migrations.
Those helpers are not part of devkit's public entry, so vendor the small (MIT) impl
locally and import it instead.
nx's librarySecondaryEntryPointGenerator appends an entrypoint-prefixed copy of
every existing include/exclude glob each time it runs. Generating many entrypoints
into one buildable library (migrate-helm-libraries or ui with "all") doubles these
arrays on every primitive until JSON.stringify throws "Invalid string length",
surfaced as "NX Invalid string length". A few primitives stay under the limit, so
the failure only showed up with ~22+ components.
Collapse the redundant prefixed globs back to their recursive equivalents after each
secondary entrypoint is generated. The library's recursive **/*.ts include already
matches every entrypoint subdirectory, so the per-entrypoint copies add nothing. The
normalization is idempotent, so the arrays stay bounded regardless of primitive count.
Angular CLI is unaffected: it never generates buildable secondary entrypoints.
In Angular 21, the CDK overlay defaults to using the popover attribute,
which causes overlay-based components (sheets, dialogs, tooltips) to
always render above position: fixed elements like hlm-toaster. This
adds a provideSpartanHlm() utility that configures OVERLAY_DEFAULT_CONFIG
with usePopover: false, and documents the issue in the sonner docs.
Closes#1280
selectActiveItem() guarded the commit with a truthiness check (if (value)), so an
option whose value is falsy (false, 0, '') was dropped: pressing Enter just closed
the panel without selecting. Check value !== null && value !== undefined instead, so
a defined falsy value is committed while a missing active item still closes. Applies
to both BrnSelect and BrnSelectMultiple.
Co-authored-by: Benjamin <benjamin@amcbanking.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Panel stays mounted through the exit animation then disposes, reopen cancels a
pending teardown, no-animation disposes promptly; plus non-modal (no backdrop),
autoFocus opt-out, outside-pointer gating, unique overlay ids, and the
destroyed-output guard.
Exercises the getPositionStrategy() override for bottom/top/left/right and the
modal backdrop, guarding the drawer's adaptation to the new dialog lifecycle.
Regression coverage for the overlay lifecycle work: autoFocus moves focus to
the first tabbable element on open, leaves focus on the trigger when the
content has none (the select/combobox keyboard model), restores focus to the
trigger on Escape, and a nested popover does not dismiss its parent while it is
the topmost overlay.
Destroying a host while its overlay/dialog is open ran the onDestroy
forceClose(), which emits on closed$/stateChanged$. The subscriptions
forwarded those to the component outputs after the directive was destroyed,
logging NG0953 in dev mode. Set a destroyed flag (registered before the
forceClose teardown) and skip the emits once it is set.
Moving popover-backed controls off CDK Dialog dropped the dialog's
autoFocus: 'first-tabbable', so popovers no longer moved focus to their
content on open (form fields were left unfocused, comboboxes could not be
typed into immediately).
Add an opt-in autoFocus option to BrnOverlay that focuses the first tabbable
element once the content renders, and enable it in the popover defaults. The
select keeps focus on its trigger because its listbox has no tabbable element,
preserving the aria-activedescendant keyboard model. Re-expose the autoFocus
input on the helm popover wrapper and its CLI template, and refresh the docs
API snapshot.
Address review feedback on the overlay lifecycle:
- the select trigger re-read its expanded state after selectActiveItem() had
already closed the panel, so Enter/Tab fell through and re-opened the
overlay via reopen(); capture the expansion state up-front so a commit no
longer re-opens on the same keypress
- make the overlay id atomic (++overlaySequence) so the duplicate-id guard and
the ref share the same counter, matching brn-dialog.service.ts
The drawer landed on main against the old BrnDialog API. Reconcile it with
this branch's refactor:
- override getPositionStrategy() for the directional position instead of the
removed mutablePositionStrategy/positionBuilder members (matches BrnSheet)
- constrain BrnDrawerContent<T extends Record<string, unknown>> to satisfy
BrnDialogContent's tightened generic
- drop the removed closeDelay-era 'delay' input from the drawer close wrapper
and its CLI template
Resolve brn-dialog.service.ts conflict: drop the deprecated injectBrnDialogCtx
alias (removed on main during the pre-1.0 audit) and keep the typed
injectBrnDialogContext with the unknown default.
* feat(command): add style and rtl support #1399
* fix: comments
* feat(command): remove custom data-hidden is built in
* remove important from rounded
* docs(command): fix typo
* fix(command): check has search input for separator
* otherwise shows multiple separator while searching in the scrollable example
---------
Co-authored-by: Merlin <merlin.moos@oldendorff.com>
Co-authored-by: Marc Stammerjohann <8985933+marcjulian@users.noreply.github.com>
* fix(cli): handle interrupts in healthcheck prompt and harden generators
Replace the raw-stdin prompt in the healthcheck generator with the standard
enquirer confirm prompt so Ctrl+C correctly aborts the run instead of leaving
the generator running. Isolate each healthcheck so one throwing does not abort
the rest, and report registry fetch failures instead of throwing.
Make getImportAlias throw on a present-but-invalid config rather than silently
falling back to the default alias, guard against the coerce() NPE in
version-utils, and switch migrate-hlm to readJson. Add unit tests across these
paths and stub network access so the suite runs offline.
Closes#906
* fix(cli): guard version healthcheck fix against missing dependencies section
The fix writeback read packageJson.dependencies[dep] directly, which threw when
a package.json had no dependencies section and the dependency lived only in
devDependencies. Guard both sections with optional chaining so the writeback is
symmetrical and never touches an undefined section.