599 Commits
Author SHA1 Message Date
Norbert de Langen d842a38d06 CLI: Remove preview-url and ignorePreview so Storybook always ships iframe.html
The custom canvas URL path forked CLI, manager, and builders; Storybook 11 always builds and loads its own preview.
2026-09-25 14:52:13 +02:00
Obvious f7725f5ede refactor(angular): fold standalone fallback into the declaration
Fold the separate `if (isStandalone === undefined)` fallback into the
declaration as `?? true` per review feedback. The `??` operand is
parenthesized because nullish coalescing cannot be mixed with `&&`
without parentheses; semantics are unchanged (false is not nullish).

Also link the Angular update guide (https://angular.dev/update-guide)
from the MIGRATION.md section, mirroring the Next.js section.
2026-09-07 07:46:07 +00:00
Obvious b6239ed207 refactor(angular): collapse builders' zoneless defaults to the 21 floor
The experimentalZoneless version checks in build-storybook and
start-storybook were constant-true under the 21 floor; both now default
to true, matching the PropertyExtractor collapse. Explicit
experimentalZoneless: false in project options is still honored.
2026-09-07 07:45:33 +00:00
Valentin Palkovic 026e109e10 Apply suggestion from @valentinpalkovic 2026-09-07 07:45:33 +00:00
Valentin Palkovic 8b70bf9c55 Apply suggestion from @valentinpalkovic 2026-09-07 07:45:33 +00:00
Obvious ba961b6265 refactor(angular): treat standalone default as constant 2026-09-07 07:44:49 +00:00
Norbert de Langen aa5790bb34 Core: Resolve tsconfig paths from the defining config
tsconfig-paths treats a missing baseUrl as the leaf tsconfig directory, so Nx-style path maps in tsconfig.base.json fail under webpack, the indexer, and react-docgen. Pass TypeScript's pathsBasePath instead so aliases work without restoring baseUrl.
2026-08-19 14:58:31 +02:00
Valentin Palkovic 86ff80b8a6 Angular: Stop reading alias collisions as two-way bindings
Compodoc reports a `model()` under the same bare name in both its input
and output lists, so the parser treated a name in both lists as two-way:
it dropped the output and synthesized `${name}Change`.

An `@Input('shared')` declared next to an `@Output('shared')` collides the
same way with no `model()` involved, so a real output was being deleted
and a phantom one invented. Requiring the declaration line to match too
separates the cases, since a `model()` is one property on one line.

The rule is lifted into a named function and the quirk is written up,
rather than resting on a comment that claimed the name alone was
sufficient. A collision now costs the aliased input its row instead of
its output, which the README records as a known limitation.
2026-08-06 10:20:00 +02:00
Valentin Palkovic f5ea811512 Angular: Derive required inputs from Compodoc's own flag
Compodoc reports whether an input is required, and we never read it. We
computed requiredness from the TypeScript-optional marker instead, so every
signal input rendered as required regardless of how it was declared.

Requiredness now comes from Compodoc's flag, with the optional marker still
consulted. Both are needed: Compodoc derives its flag from the presence of the
`required` key in an `@Input({...})` argument rather than its value, so
`@Input({ required: false })` reports itself as required and optional at once,
and only requiring the two to agree keeps that case right.

A `model()` signal's synthesized change output is now always optional. It used
to inherit the requiredness of the input it derives from, which disagreed with
how every real output reads.

Plain decorator inputs still read as required. Compodoc emits neither flag for
them, which is an upstream gap; when it is fixed they correct themselves.
2026-08-04 21:24:02 +02:00
Valentin Palkovic 53f11373f0 Angular: Extract Compodoc parsing into its own package
The code that turns Compodoc's output into argTypes existed twice, once in
each of the two Angular framework packages, as byte-identical copies. Any
fix applied to one had to be remembered for the other, and in practice they
drifted. It now lives in one place both of them share.

The extracted module no longer assumes a browser. What differs between
environments is passed in rather than reached for: the Compodoc data, the
feature flag, a logger, and the helper that unwraps Compodoc's
HTML-rendered JSDoc. Each framework's preview supplies its own.

The shared package is private and compiled into both framework packages
rather than published, so nothing new appears on npm and neither package
gains a runtime dependency.

No behaviour changes. Both frameworks' existing test suites pass untouched,
and the preview still unwraps HTML with DOMParser exactly as before.
2026-08-04 18:17:46 +02:00
Julien Huang 3504ec0659 Build: Remove eslint-disable directives that are unused under oxlint
oxlint reports these directives as unused: they suppress rules that are
either not enabled in the oxlint config (type-aware rules, dropped
plugins) or implemented with different heuristics. Verified with
`oxlint --report-unused-disable-directives` reporting zero findings in
both code/ and scripts/ afterwards.
2026-07-03 13:32:08 +02:00
Valentin Palkovic c6fa1d3fc3 Merge branch 'next' into type-fest-upgrade 2026-05-21 13:50:14 +02:00
Valentin PalkovicandClaude Opus 4.7 9bf6059062 chore(angular): fix formatting in NgComponentAnalyzer.test.ts
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 11:46:57 +02:00
copilot-swe-agent[bot] a6d171537a chore(angular): apply review feedback for model-signal stories/tests
Agent-Logs-Url: https://github.com/storybookjs/storybook/sessions/ed8009ed-8fac-4deb-97ba-aad80ca78257
2026-05-21 09:19:09 +00:00
Valentin Palkovic a6d29d04e5 Apply suggestion from @valentinpalkovic 2026-05-20 08:19:18 +02:00
Valentin Palkovic 1fc92e8521 Apply suggestion from @valentinpalkovic 2026-05-20 08:18:01 +02:00
Valentin Palkovic 27538e4405 Merge branch 'next' into valentin/angular-model-signal-outputs 2026-05-19 17:07:19 +02:00
Valentin Palkovic 5b66f0f76f Apply suggestion from @valentinpalkovic 2026-05-19 15:34:41 +02:00
Valentin Palkovic 436e31ca4c Apply suggestion from @valentinpalkovic 2026-05-19 15:32:31 +02:00
Valentin PalkovicandClaude Opus 4.7 19175ef710 docs(angular): trim transcript prose, drop changelog entry
- Remove the CHANGELOG.prerelease.md entry (reverts to next).
- public-types.test-d.ts: drop "Layer A"/"AC-X3" transcript prose,
  tighten the transform-input comment.
- public-types.ts: condense the TransformComponentType JSDoc to the
  load-bearing do-NOT-reorder constraint.
- compodoc.ts: broaden the model() false-positive note (inherited /
  accessor splits) and document the aliased-model() autodocs gap.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 13:34:52 +02:00
Valentin PalkovicandClaude Opus 4.7 2f86d33a76 docs(angular): trim redundant comments in model() detection
Cut comments that restated the code or repeated the rationale across call site
and JSDoc; kept the load-bearing ones (ɵcmp shape, type-composition order,
compodoc both-arrays heuristic + its limitation).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 13:17:11 +02:00
Valentin PalkovicandClaude Opus 4.7 a74018a97b refactor(angular): remove component instantiation from analyzer; static ɵcmp only
Address review feedback (Karpathy + Pragmatic):

- NgComponentAnalyzer: drop the new-instance fallback (runInInjectionContext +
  new component()) and its orphaned imports. Signal I/O is now read purely
  statically from the compiled component definition (ɵcmp), so the analysis
  path never executes user constructor code. Verified the fallback was
  test-harness-only (ComputesTemplateFromComponent/compodoc/angular-properties
  unaffected).
- Tests: assert the production ɵcmp reader via a synthetic ɵcmp mirroring the
  AOT shape (now also covers aliased model() resolution). Drop the
  over-engineered throws-if-called resolveComponentFactory guard; restore
  pre-existing imports.
- Strip internal investigation jargon (Probe/AC/R6/Lxxx) from comments in
  NgComponentAnalyzer, compodoc, public-types, and the model-signal stories.
- CHANGELOG: collapse to the repo one-line convention.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 12:53:20 +02:00
Valentin PalkovicandClaude Opus 4.7 332fe51688 refactor(angular): address review feedback for model() detection (docs, comments, limitations)
comment-only repoint to committed compodoc-input.json fixture; document same-name @Input/@Output discriminator false-positive (compodoc.ts + changelog); synthesized ${name}Change output no longer inherits misleading input defaultValue/type summary (Docs-table only, detection logic unchanged); reference https://github.com/storybookjs/storybook/issues/34831.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 11:45:35 +02:00
Valentin PalkovicandClaude Sonnet 4.6 5a92ef8f33 Fix implicit-any type error and add missing statsJson path test for start-storybook
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 11:24:40 +02:00
Valentin PalkovicandClaude Opus 4.7 0588d2f5ee feat(angular): detect model() signal output in compodoc autodocs (Layer B)
Refs https://github.com/storybookjs/storybook/issues/34831

Angular `model()` two-way binding signals were not surfaced in compodoc
autodocs. compodoc (verified against the captured v1.2.1 output) emits a
`model()` member as an IDENTICAL entry — same bare name, no decorators/
jsdoctags, ModelSignal<T> wrapper erased — in BOTH `inputsClass` AND
`outputsClass`. Plain @Input/input() only land in inputsClass; plain
@Output/output()/EventEmitter only in outputsClass. The reliable,
version-tolerant discriminator is therefore a property whose name appears
in BOTH arrays of the same component (the both-arrays discriminator);
compodoc emits no model() marker, so compodoc-types.ts Property is unchanged.

- extractArgTypesFromData now detects model props via the both-arrays
  discriminator, suppresses compodoc's spurious bare-name outputsClass
  duplicate (model surfaces as an input control), and synthesizes a
  `${name}Change` output (action: '${name}Change') reusing the per-item
  output shape.
- Deterministic angularFilterNonInputControls re-surface branch: the
  synthesized `${name}Change` output + companion input are present with the
  flag OFF, and still re-surfaced with the flag ON despite iteration being
  restricted to ['inputsClass'].
- New __testfixtures__/doc-model fixture (mirrors doc-button) with the
  captured compodoc JSON; angular-properties.test.ts now asserts the
  synthesized colorChange/showTextChange rows for both filter states.
- doc-button EventEmitter fixture regression-guarded (untouched, still green).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 11:09:34 +02:00
Valentin PalkovicandClaude Opus 4.7 21c245e965 feat(angular): detect model() signal binding at runtime (Layer C)
Extends getComponentInputsOutputs with an additive dual detection path so a
model() field surfaces BOTH its `color` input and the compiler-synthesized
`colorChange` output, without altering @Input/@Output/input()/output()/
EventEmitter results from the decorator path.

Strategy (Probe C: esbuild/JIT strips signal AOT metadata in the unit-test
harness, so `ecmp` I/O maps are empty for signal members / `signals===false`):
- Primary: read the Angular component def via ɵgetComponentDef; ɵcmp keys the
  I/O maps by template name -> propName (verified empirically), so aliased
  model(x,{alias}) and model.required() resolve to their real binding names.
- Fallback: synthesize from the component instance brand (writable+subscribable
  signal => model() input + ${name}Change output) for non-AOT/JIT classes.

All 3 consumers verified (no edits needed): computesTemplateFromComponent and
computesTemplateSourceFromComponent emit [color]+(colorChange) via the existing
pure I/O builders; StorybookWrapperComponent filter-inversion confirmed -- the
model input now reaches the instance through the template Input binding
(initial render + live storyProps$ updates) instead of the dropped
getNonInputsOutputsProps direct-assignment path.

Adds a NEW factory-free test block covering @Input/@Output, input(), output(),
EventEmitter, model(), model.required(), aliased model(), plus a throws-if-called
ComponentFactoryResolver guard proving zero factory invocation in model()
detection. L50-212 kept commented with a tracked TODO(angular-22).

Refs https://github.com/storybookjs/storybook/issues/34831

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 10:55:57 +02:00
Valentin PalkovicandClaude Opus 4.7 fd4a51dfbc feat(angular): detect model() signal output in type inference (Layer A)
Adds Layer A native detection of Angular model() signal outputs in the
@storybook/angular public type inference.

Refs https://github.com/storybookjs/storybook/issues/34831

- Adds AngularModelSignal / AngularHasModelSignal / ModelSignal aliases
  mirroring the existing InputSignal/OutputEmitterRef conditional style.
- Adds TransformModelSignalType<T>: maps each ModelSignal<E> field to E and
  synthesizes an intersection member `${prop}Change`: (e: E) => void (the
  xChange member is compiler-synthesized, never a real keyof T member).
- Pins TransformComponentType composition with TransformModelSignalType as the
  INNERMOST wrapper (do not reorder): the synthesized `${prop}Change` is
  (e:E)=>void so it passes the outer Input/Output/Event transforms unchanged,
  and since ModelSignal extends InputSignal the model value field is
  idempotently re-collapsed by the outer TransformInputSignalType (no
  double-transform divergence).
- Adds public-types.test-d.ts asserting the FINAL composed
  TransformComponentType<C> (composed, NOT TransformModelSignalType in
  isolation) for color/colorChange + model.required() + full no-regression
  coverage (input(), transform input(), output(), EventEmitter, @Input,
  @Output) resolving simultaneously in one type.

Documented limitation (for the AC-X3 changelog): aliased
model(prop, { alias: 'a' }) produces aChange at runtime, but Layer A can only
synthesize ${propName}Change because TypeScript cannot observe the runtime
alias. Runtime detection (Layer C) handles the alias via the resolved binding
name on ɵcmp. model.required() is fully covered.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 00:08:56 +02:00
Tobias Diez 92dda65db2 Build: upgrade type-fest to latest version 5.6.0 2026-05-14 20:46:31 +02:00
Bill Collins ebc6514923 Fix types 2026-05-06 12:49:51 +01:00
Valentin Palkovic 2b11cd13b8 Merge branch 'next' into bill/fix-stats-json 2026-05-06 12:12:52 +02:00
Kyle Gach ce4f91bd12 Merge branch 'next' into docs/code_snipper
* next: (719 commits)
  Bump version from 10.4.0-alpha.14 to 10.4.0-alpha.15 [skip ci]
  Write changelog for 10.4.0-alpha.15 [skip ci]
  move agent detection to config hook instead of configureVitest
  Bump version from 10.4.0-alpha.13 to 10.4.0-alpha.14 [skip ci]
  Write changelog for 10.4.0-alpha.14 [skip ci]
  Bump version from 10.4.0-alpha.12 to 10.4.0-alpha.13 [skip ci]
  Revert revert
  Write changelog for 10.4.0-alpha.13 [skip ci]
  fix tests
  revert
  fix steps collection
  fix formatting
  Use same icon for modified and related
  Replace icon for related changes
  always resolve telemetry state immediately
  add addon-mcp to internal UI Storybook
  await the call
  cleanup
  fix init telemetry being delayed
  Bump version from 10.4.0-alpha.11 to 10.4.0-alpha.12 [skip ci]
  ...
2026-05-01 11:17:18 -06:00
Bill Collins 67659cedc1 Improve assertions 2026-04-16 10:14:49 +01:00
Bill Collins c57311e584 Fix start-storybook tests too 2026-04-16 10:13:09 +01:00
Bill Collins 095e1256c4 fmt 2026-04-16 10:01:33 +01:00
Bill Collins 31ddb2fb8e Fix remaining tests 2026-04-16 10:00:28 +01:00
Bill Collins 242839e9b6 Fix mocking so tests run 2026-04-16 09:46:32 +01:00
Bill Collins c7d163d1a1 Add what should be a failing test for parsing custom stats.json paths 2026-04-15 12:34:37 +01:00
Jeppe Reinhold b058e0169a Remove tests and stories depending on the ComponentFactoryResolver from core angular 2026-04-14 11:38:58 +02:00
Kasper Peulen d2d1bc622c Build: Rewrite relative imports with explicit extensions 2026-04-01 18:11:33 +07:00
alex-js-ltd c52ca909cb refactor(angular): simplify core preset and remove builder.options 2026-03-30 14:18:12 +01:00
alex-js-ltd a203ab17d2 refactor: deduplicate framework builder options logic across presets 2026-03-30 12:56:02 +01:00
alex-js-ltd 1913a7093d fix: apply oxfmt formatting 2026-03-30 12:56:02 +01:00
alex-js-ltd c77a598b15 refactor(frameworks): extract getBuilderOptions helper across framework presets 2026-03-30 12:56:02 +01:00
Valentin Palkovic cc5f09300b Merge pull request #33982 from ValentinFunk/next
Angular: Use Story ID for renderer IDs (including standalone stories)
2026-03-19 20:54:33 +01:00
Valentin Funk a8b2c770bd fix RenderFactory test by passing story ids and fix type error in CanvasRenderer 2026-03-19 10:58:43 +01:00
Valentin Funk 17a5ab1c87 Merge remote-tracking branch 'upstream' into next 2026-03-19 10:13:14 +01:00
Julien Huang 0ab8035484 remove prettier 2026-03-17 16:16:32 +01:00
Alexander von Weiss cfa8f41494 Angular: only load webpack dependencies on demand
The dependencies `@angular-devkit/build-angular`, `@storybook/builder-webpack5` and `webpack` are only needed if you use webpack.

But if you use https://analogjs.org/docs/integrations/storybook to use angular + storybook via vite, then you only need `@angular/build` and `@storybook/vite` instead.

The analogjs plugin stil relies on `@storybook/angular`, but loading webpack dependencies on demand allows one to drop webpack dependencies.
2026-03-06 15:36:24 +01:00
Valentin Funk 52e0a6b8d9 update angular id gen 2026-03-03 11:58:58 +01:00
Jeppe Reinhold ea030b0534 fix missing channel on options everywhere 2026-01-20 11:16:15 +01:00