Commit Graph

1594 Commits

Author SHA1 Message Date
Ashley Hunter 42ee5519a4 fix(cli): harden angular-cli tsconfig include and embla major guard
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.
2026-06-18 19:21:33 +01:00
Ashley Hunter 5fcd3fbd39 fix(cli): narrow angular-cli tsconfig include 2026-06-18 18:16:14 +01:00
Ashley Hunter ce25093007 fix(cli): include generated libs in tsconfig.app.json for angular-cli
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.
2026-06-18 17:39:19 +01:00
Ashley Hunter 9f94cea97c fix(cli): pin embla-carousel-angular to the installed Angular major
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.
2026-06-18 17:39:19 +01:00
Ashley Hunter be61667f17 fix(cli): respect configured npm registry in version healthcheck
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.
2026-06-17 23:48:28 +01:00
moosme 9236788c8f Merge pull request #1495 from mehrabix/feat/provide-spartan-hlm
feat(utils): add provideSpartanHlm utility to fix CDK overlay z-index…
2026-06-18 08:29:44 +02:00
moosme a7d13e0188 Merge pull request #1498 from spartan-ng/fix/migrate-helm-libraries-tsconfig-include-explosion
fix(cli): prevent tsconfig include explosion when migrating many helm libraries
2026-06-18 08:28:19 +02:00
Leonidas f1cdfcbc9b chore: nightly release 2026-06-18 ⚡ 2026-06-18 04:04:01 +00:00
Patrick bc471546ef fix(radio-group): restore native tab behavior (#1492)
* fix(radio-group): restore native tab behavior

* test(radio-group): cover disabled reset tab target
2026-06-18 00:48:00 +02:00
Ashley Hunter c5205c04a9 fix(cli): narrow glob-variant matching and require() the remove generator by path
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).
2026-06-17 19:42:52 +01:00
Ashley Hunter 859029b409 fix(cli): pre-normalize tsconfig and tighten entrypoint glob dedupe
- 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.
2026-06-17 19:29:54 +01:00
Ashley Hunter 57614d3488 fix(cli): resolve @nx/workspace remove generator robustly across nx versions
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).
2026-06-17 19:29:54 +01:00
Ashley Hunter 5eb1002765 fix(cli): vendor string-change util so healthcheck runs when the CLI is installed
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.
2026-06-17 18:54:10 +01:00
Ashley Hunter 7e243905a3 fix(cli): prevent tsconfig.lib.json include explosion when migrating helm libraries
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.
2026-06-17 18:54:10 +01:00
mehrabix f396e32df9 feat: add provideSpartanHlm utility to fix CDK overlay z-index conflict
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
2026-06-17 19:08:20 +03:30
Ban117 7ada58e03d fix(select): select option with a falsy value on enter keypress (#1493)
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>
2026-06-17 15:47:28 +02:00
moosme 01aeb5a231 feat(navigation-menu): add style support #1408 (#1490)
* feat(navigation-menu): add style support #1408

* fix: review

* feat(navigation-menu): add align input to navigation-menu-trigger

* add align example

* feat(navigation-menu): add navOffset

* docs(navigation-menu): update example ids

* feat(navigation-menu): add guard in updateAlign

* feat(navigation-menu): remove group from trigger

* feat(navigation-menu): remove unused data-popup-open classes

* navigation-menu doesn't have data-popup-open attribute

---------

Co-authored-by: Merlin <merlin.moos@oldendorff.com>
Co-authored-by: Marc Stammerjohann <8985933+marcjulian@users.noreply.github.com>
2026-06-17 15:43:07 +02:00
Ashley Hunter d2f40d3014 Merge pull request #1471 from PatrickLarocque/fix/overlay-lifecycle
refactor!: split dialog and overlay portal lifecycles
2026-06-17 10:16:35 +01:00
moosme 8cf3775943 Merge pull request #1489 from marcjulian/feat/remove-unused-styles 2026-06-17 08:07:19 +02:00
Leonidas b5e12f4140 chore: nightly release 2026-06-17 ⚡ 2026-06-17 04:12:35 +00:00
Ashley Hunter d4a0a31eb0 test(popover): cover animation-aware teardown and overlay behaviour
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.
2026-06-16 23:56:56 +01:00
Ashley Hunter ecb098bb3d test: cover wait-for-element-animations helper
Active-animation collection (filtering finished, subtree, null-safety) and the
finish/fallback-timer behaviour that replaced the fixed close delay.
2026-06-16 23:56:56 +01:00
Ashley Hunter 82b6f756de test(drawer): cover open/close and directional positioning
Exercises the getPositionStrategy() override for bottom/top/left/right and the
modal backdrop, guarding the drawer's adaptation to the new dialog lifecycle.
2026-06-16 23:56:56 +01:00
Ashley Hunter ed9328f867 test(select): cover keyboard open, commit-and-close, and focus model
Guards the regression where committing with Enter re-opened the panel, plus
Escape-to-close and the trigger keeping focus while navigating.
2026-06-16 23:56:56 +01:00
Ashley Hunter 4140fc6d9a test(popover): cover autofocus, focus restore, and nested dismissal
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.
2026-06-16 23:41:50 +01:00
Ashley Hunter 35f1a92586 fix: avoid emitting on destroyed overlay/dialog outputs
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.
2026-06-16 23:41:50 +01:00
Ashley Hunter 23f20bf4dd feat: restore overlay focus-into-content on open via opt-in autoFocus
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.
2026-06-16 23:23:29 +01:00
Ashley Hunter cd932da378 fix(select): keep panel closed after committing a value with the keyboard
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
2026-06-16 23:23:29 +01:00
Ashley Hunter 2e14efcde5 fix(drawer): adapt drawer to the new dialog/overlay lifecycle
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
2026-06-16 23:23:29 +01:00
Ashley Hunter 0c3b653902 Merge origin/main into fix/overlay-lifecycle
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.
2026-06-16 23:22:47 +01:00
moosme 263648ade1 feat(command): add style and rtl support #1399 (#1488)
* 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>
2026-06-16 18:48:35 +02:00
Marc Stammerjohann a0687ae64b feat(popover): add header, title and description 2026-06-16 17:21:28 +02:00
Marc Stammerjohann cc3a7578de chore: remove unused spartan-* classes 2026-06-16 17:09:52 +02:00
Marc Stammerjohann 27305c73c0 feat: dropdown and context menu styles, rtl example (#1486)
* feat(dropdown-menu): add style support, add sub trigger

* feat(dropdown-menu): update snapshot

* feat(context-menu): add rtl and more examples, enable styles

* remove spartan-context-* classes as it reuses dropdown-menu

* feat(menubar): remove unused spartan-menubar-* styles, update examples

* fix(dropdown-menu): remove duplicate styles which dropdown-menu-item already applies

* docs(context-menu): fix id

* docs: update examples

* feat(dropdown-menu): make checkbox/radio group scoped

* fix(dropdown-menu): fix rtl styles

* feat(dropdown-menu): add internal comment

* feat(dropdown-menu): add ng-icon styles for item-indicator

* docs(menubar): update preview
2026-06-16 16:33:33 +02:00
Marc Stammerjohann 05463a6955 fix: ignore copilot from contributors (#1487) 2026-06-16 16:13:34 +02:00
moosme 61a546f24a Merge pull request #1476 from spartan-ng/pre-1.0-audit
chore(repo): pre-1.0 audit - overlay leak fixes, data-slot, CLI drawer, naming
2026-06-16 11:43:11 +02:00
Leonidas bd321c9ab0 chore: nightly release 2026-06-16 ⚡ 2026-06-16 04:12:33 +00:00
moosme 457b7190cc feat(menubar): add style support (#1474)
* feat(menubar): add style support

* fix: review

---------

Co-authored-by: Merlin <merlin.moos@oldendorff.com>
2026-06-15 15:52:30 +02:00
Robin Goetz 70fb0e929f fix(cli): handle interrupts in healthcheck prompt and harden generators (#1479)
* 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.
2026-06-15 15:16:42 +02:00
Ahmad Mehrabi 715499fe4e feat(date-picker): add Jalali (Persian) calendar support (#1429)
* feat(date-picker): add Jalali (Persian) calendar support

- Add pure Jalali calendar math algorithms (no npm packages)
- Add JalaliDate class with valueOf() for reliable calendar comparison
- Add BrnJalaliDateAdapter implementing BrnDateAdapter<JalaliDate>
- Add comprehensive unit tests for all adapter methods
- Add Persian (Farsi) calendar i18n with RTL layout
- Add Jalali date picker example to docs page
- Add Storybook story with Persian locale
- Extend TranslateService to support 'fa' language

* feat(date-picker): add Jalali (Persian) calendar support

Add pure Jalali calendar math, JalaliDate class, and BrnJalaliDateAdapter with tests.

Move example from component docs to blocks/calendar page per PR review.

* refactor: clean up jalali date-time code

- Deduplicate JALALI_MONTHS array in calendar i18n files
- snake_case to camelCase in PersianDate (gregorianDaysInMonth, jalaliDaysInMonth)
- Expand cryptic param names (j_y to jalaliYear, g_y to gregorianYear, etc.)
- Remove parseInt() no-ops on typed number params
- Remove getMonthName (i18n concern, not calendrical)
- Destructure tuples with descriptive names across adapter/date/persian-date
- Fix month+day add drift: clamp day after month step before day arithmetic

* style: fix long line formatting to pass nx format check

* fix(date-picker): resolve merge conflicts from upstream and stashed changes

Merge descriptive variable names (_constrain, parseInt, getMonthName,
full descriptive names) with upstream descriptive names. All tests pass.

* refactor: remove parseInt unwrapping and getMonthName, add PersianDate tests
2026-06-15 15:05:30 +02:00
copilot-swe-agent[bot] aaf29b4e05 chore(repo): merge main into pre-1.0-audit (resolve drawer brain version conflict) 2026-06-15 11:47:09 +00:00
Marc Stammerjohann 9e825894d1 feat(native-select): generate to cli 2026-06-15 11:24:11 +02:00
Marc Stammerjohann 90d06b2f1b feat(native-select): update option and optgroup selector 2026-06-15 11:23:37 +02:00
Marc Stammerjohann 138a4d84c4 fix(native-select): apply system styles to option and optgroup 2026-06-15 11:21:06 +02:00
Ashley Hunter 603d213799 fix(resizable): end drag on touchcancel
A touch drag interrupted by the system fires touchcancel instead of touchend, so the drag teardown
(listeners + cursor) never ran until the next drag or destroy. Listen for touchcancel alongside
touchend and remove it in cleanup. Adds a regression test.
2026-06-15 08:04:00 +01:00
Leonidas 7da9d3e4c3 chore: nightly release 2026-06-15 ⚡ 2026-06-15 04:22:11 +00:00
Ashley Hunter 85bc4b74a2 test(repo): refresh ui-docs API snapshot for prefixed avatar exportAs
The generate-ui-docs snapshot captures each directive's exportAs, so the avatar exportAs rename
(avatarImage/avatarFallback -> brn*/hlm*) left it stale and failed the unit job. Diff is limited to
those four entries.
2026-06-15 00:05:00 +01:00
Ashley Hunter 66fafc4b16 fix(repo): drop redundant data-slot duplicating the brain layer
The data-slot pass added host/template data-slot to helm navigation-menu and slider, but the brain
directives those wrappers compose (BrnNavigationMenu* via hostDirectives, BrnSlider/brnSliderTrack/
brnSliderRange/brnSliderThumb in the slider template) already emit the identical data-slot on the
same elements. The helm copies were dead duplication and a future drift hazard. Removed them; the
slots remain in the DOM via the brain layer (verified in browser). The genuinely-new slots
(switch, input, progress, popover, calendar root) stay - the brain layer provides none for those.
2026-06-14 23:54:05 +01:00
Ashley Hunter f533fa426c refactor(dialog): remove deprecated injectBrnDialogCtx
Drop the deprecated `injectBrnDialogCtx` in favour of `injectBrnDialogContext`, which the helm
dialog, docs app and storybook already use exclusively. Removing it before 1.0 avoids carrying the
alias on the stable line. The `BrnDialogContext` type it returned stays - it is still used inside
the service.
2026-06-14 23:43:51 +01:00
Ashley Hunter 8cf9a9c868 style(repo): order host after hostDirectives in data-slot components
The data-slot additions inserted the `host` key directly after `selector`, violating the
workspace `@nx/workspace-component-directive-key-order` rule (host must follow hostDirectives).
Reorder the affected calendar/input/navigation-menu/popover/progress/slider metadata; no behavior
change.
2026-06-14 23:40:43 +01:00