@frame-kit/ui-ng 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/COMPONENTS.md +683 -0
  2. package/DEVELOPMENT_GUIDE.md +1102 -0
  3. package/LICENSE +21 -0
  4. package/README.md +69 -0
  5. package/THEMING.md +130 -0
  6. package/core/headline/README.md +121 -0
  7. package/core/icon/README.md +173 -0
  8. package/core/image/README.md +210 -0
  9. package/core/link/README.md +297 -0
  10. package/core/separator/README.md +145 -0
  11. package/core/text/README.md +240 -0
  12. package/directives/infinite-scroll/README.md +102 -0
  13. package/directives/spotlight/README.md +154 -0
  14. package/directives/tooltip/README.md +147 -0
  15. package/docs/endpoint-link/README.md +142 -0
  16. package/docs/method-badge/README.md +154 -0
  17. package/fesm2022/frame-kit-ui-ng-core-headline.mjs +122 -0
  18. package/fesm2022/frame-kit-ui-ng-core-headline.mjs.map +1 -0
  19. package/fesm2022/frame-kit-ui-ng-core-icon.mjs +189 -0
  20. package/fesm2022/frame-kit-ui-ng-core-icon.mjs.map +1 -0
  21. package/fesm2022/frame-kit-ui-ng-core-image.mjs +123 -0
  22. package/fesm2022/frame-kit-ui-ng-core-image.mjs.map +1 -0
  23. package/fesm2022/frame-kit-ui-ng-core-link.mjs +369 -0
  24. package/fesm2022/frame-kit-ui-ng-core-link.mjs.map +1 -0
  25. package/fesm2022/frame-kit-ui-ng-core-separator.mjs +59 -0
  26. package/fesm2022/frame-kit-ui-ng-core-separator.mjs.map +1 -0
  27. package/fesm2022/frame-kit-ui-ng-core-text.mjs +204 -0
  28. package/fesm2022/frame-kit-ui-ng-core-text.mjs.map +1 -0
  29. package/fesm2022/frame-kit-ui-ng-directives-infinite-scroll.mjs +74 -0
  30. package/fesm2022/frame-kit-ui-ng-directives-infinite-scroll.mjs.map +1 -0
  31. package/fesm2022/frame-kit-ui-ng-directives-spotlight.mjs +76 -0
  32. package/fesm2022/frame-kit-ui-ng-directives-spotlight.mjs.map +1 -0
  33. package/fesm2022/frame-kit-ui-ng-directives-tooltip.mjs +425 -0
  34. package/fesm2022/frame-kit-ui-ng-directives-tooltip.mjs.map +1 -0
  35. package/fesm2022/frame-kit-ui-ng-docs-endpoint-link.mjs +63 -0
  36. package/fesm2022/frame-kit-ui-ng-docs-endpoint-link.mjs.map +1 -0
  37. package/fesm2022/frame-kit-ui-ng-docs-method-badge.mjs +43 -0
  38. package/fesm2022/frame-kit-ui-ng-docs-method-badge.mjs.map +1 -0
  39. package/fesm2022/frame-kit-ui-ng-forms.mjs +3632 -0
  40. package/fesm2022/frame-kit-ui-ng-forms.mjs.map +1 -0
  41. package/fesm2022/frame-kit-ui-ng-layouts-app-shell.mjs +239 -0
  42. package/fesm2022/frame-kit-ui-ng-layouts-app-shell.mjs.map +1 -0
  43. package/fesm2022/frame-kit-ui-ng-layouts-content-split.mjs +132 -0
  44. package/fesm2022/frame-kit-ui-ng-layouts-content-split.mjs.map +1 -0
  45. package/fesm2022/frame-kit-ui-ng-services-overlay-orchestrator.mjs +133 -0
  46. package/fesm2022/frame-kit-ui-ng-services-overlay-orchestrator.mjs.map +1 -0
  47. package/fesm2022/frame-kit-ui-ng-services-spotlight.mjs +60 -0
  48. package/fesm2022/frame-kit-ui-ng-services-spotlight.mjs.map +1 -0
  49. package/fesm2022/frame-kit-ui-ng-services-toast.mjs +166 -0
  50. package/fesm2022/frame-kit-ui-ng-services-toast.mjs.map +1 -0
  51. package/fesm2022/frame-kit-ui-ng-ui-accordion.mjs +214 -0
  52. package/fesm2022/frame-kit-ui-ng-ui-accordion.mjs.map +1 -0
  53. package/fesm2022/frame-kit-ui-ng-ui-alert.mjs +82 -0
  54. package/fesm2022/frame-kit-ui-ng-ui-alert.mjs.map +1 -0
  55. package/fesm2022/frame-kit-ui-ng-ui-avatar-stack.mjs +76 -0
  56. package/fesm2022/frame-kit-ui-ng-ui-avatar-stack.mjs.map +1 -0
  57. package/fesm2022/frame-kit-ui-ng-ui-avatar.mjs +81 -0
  58. package/fesm2022/frame-kit-ui-ng-ui-avatar.mjs.map +1 -0
  59. package/fesm2022/frame-kit-ui-ng-ui-badge.mjs +81 -0
  60. package/fesm2022/frame-kit-ui-ng-ui-badge.mjs.map +1 -0
  61. package/fesm2022/frame-kit-ui-ng-ui-breadcrumb.mjs +68 -0
  62. package/fesm2022/frame-kit-ui-ng-ui-breadcrumb.mjs.map +1 -0
  63. package/fesm2022/frame-kit-ui-ng-ui-button.mjs +108 -0
  64. package/fesm2022/frame-kit-ui-ng-ui-button.mjs.map +1 -0
  65. package/fesm2022/frame-kit-ui-ng-ui-callout.mjs +58 -0
  66. package/fesm2022/frame-kit-ui-ng-ui-callout.mjs.map +1 -0
  67. package/fesm2022/frame-kit-ui-ng-ui-card.mjs +70 -0
  68. package/fesm2022/frame-kit-ui-ng-ui-card.mjs.map +1 -0
  69. package/fesm2022/frame-kit-ui-ng-ui-copyable-field.mjs +113 -0
  70. package/fesm2022/frame-kit-ui-ng-ui-copyable-field.mjs.map +1 -0
  71. package/fesm2022/frame-kit-ui-ng-ui-data-table.mjs +1288 -0
  72. package/fesm2022/frame-kit-ui-ng-ui-data-table.mjs.map +1 -0
  73. package/fesm2022/frame-kit-ui-ng-ui-dialog.mjs +456 -0
  74. package/fesm2022/frame-kit-ui-ng-ui-dialog.mjs.map +1 -0
  75. package/fesm2022/frame-kit-ui-ng-ui-drawer.mjs +398 -0
  76. package/fesm2022/frame-kit-ui-ng-ui-drawer.mjs.map +1 -0
  77. package/fesm2022/frame-kit-ui-ng-ui-dropdown-menu.mjs +398 -0
  78. package/fesm2022/frame-kit-ui-ng-ui-dropdown-menu.mjs.map +1 -0
  79. package/fesm2022/frame-kit-ui-ng-ui-editable-field.mjs +125 -0
  80. package/fesm2022/frame-kit-ui-ng-ui-editable-field.mjs.map +1 -0
  81. package/fesm2022/frame-kit-ui-ng-ui-icon-badge.mjs +113 -0
  82. package/fesm2022/frame-kit-ui-ng-ui-icon-badge.mjs.map +1 -0
  83. package/fesm2022/frame-kit-ui-ng-ui-icon-list.mjs +111 -0
  84. package/fesm2022/frame-kit-ui-ng-ui-icon-list.mjs.map +1 -0
  85. package/fesm2022/frame-kit-ui-ng-ui-inline-edit.mjs +103 -0
  86. package/fesm2022/frame-kit-ui-ng-ui-inline-edit.mjs.map +1 -0
  87. package/fesm2022/frame-kit-ui-ng-ui-list-editor.mjs +135 -0
  88. package/fesm2022/frame-kit-ui-ng-ui-list-editor.mjs.map +1 -0
  89. package/fesm2022/frame-kit-ui-ng-ui-loader.mjs +81 -0
  90. package/fesm2022/frame-kit-ui-ng-ui-loader.mjs.map +1 -0
  91. package/fesm2022/frame-kit-ui-ng-ui-menu-item.mjs +79 -0
  92. package/fesm2022/frame-kit-ui-ng-ui-menu-item.mjs.map +1 -0
  93. package/fesm2022/frame-kit-ui-ng-ui-nav-brand.mjs +40 -0
  94. package/fesm2022/frame-kit-ui-ng-ui-nav-brand.mjs.map +1 -0
  95. package/fesm2022/frame-kit-ui-ng-ui-nav-group.mjs +110 -0
  96. package/fesm2022/frame-kit-ui-ng-ui-nav-group.mjs.map +1 -0
  97. package/fesm2022/frame-kit-ui-ng-ui-nav-separator.mjs +91 -0
  98. package/fesm2022/frame-kit-ui-ng-ui-nav-separator.mjs.map +1 -0
  99. package/fesm2022/frame-kit-ui-ng-ui-node-tree-breadcrumb.mjs +86 -0
  100. package/fesm2022/frame-kit-ui-ng-ui-node-tree-breadcrumb.mjs.map +1 -0
  101. package/fesm2022/frame-kit-ui-ng-ui-node-tree.mjs +443 -0
  102. package/fesm2022/frame-kit-ui-ng-ui-node-tree.mjs.map +1 -0
  103. package/fesm2022/frame-kit-ui-ng-ui-note.mjs +56 -0
  104. package/fesm2022/frame-kit-ui-ng-ui-note.mjs.map +1 -0
  105. package/fesm2022/frame-kit-ui-ng-ui-numbered-list.mjs +105 -0
  106. package/fesm2022/frame-kit-ui-ng-ui-numbered-list.mjs.map +1 -0
  107. package/fesm2022/frame-kit-ui-ng-ui-pagination.mjs +110 -0
  108. package/fesm2022/frame-kit-ui-ng-ui-pagination.mjs.map +1 -0
  109. package/fesm2022/frame-kit-ui-ng-ui-progress-bar.mjs +129 -0
  110. package/fesm2022/frame-kit-ui-ng-ui-progress-bar.mjs.map +1 -0
  111. package/fesm2022/frame-kit-ui-ng-ui-sidenav-link.mjs +42 -0
  112. package/fesm2022/frame-kit-ui-ng-ui-sidenav-link.mjs.map +1 -0
  113. package/fesm2022/frame-kit-ui-ng-ui-tabs.mjs +894 -0
  114. package/fesm2022/frame-kit-ui-ng-ui-tabs.mjs.map +1 -0
  115. package/fesm2022/frame-kit-ui-ng-ui-timeline.mjs +81 -0
  116. package/fesm2022/frame-kit-ui-ng-ui-timeline.mjs.map +1 -0
  117. package/fesm2022/frame-kit-ui-ng-ui-toast.mjs +179 -0
  118. package/fesm2022/frame-kit-ui-ng-ui-toast.mjs.map +1 -0
  119. package/fesm2022/frame-kit-ui-ng-ui-user-menu.mjs +143 -0
  120. package/fesm2022/frame-kit-ui-ng-ui-user-menu.mjs.map +1 -0
  121. package/fesm2022/frame-kit-ui-ng-ui-wizard-dialog.mjs +191 -0
  122. package/fesm2022/frame-kit-ui-ng-ui-wizard-dialog.mjs.map +1 -0
  123. package/fesm2022/frame-kit-ui-ng.mjs +58 -0
  124. package/fesm2022/frame-kit-ui-ng.mjs.map +1 -0
  125. package/layouts/app-shell/README.md +357 -0
  126. package/layouts/content-split/README.md +180 -0
  127. package/package.json +253 -0
  128. package/services/overlay-orchestrator/README.md +184 -0
  129. package/services/spotlight/README.md +61 -0
  130. package/services/toast/README.md +118 -0
  131. package/types/frame-kit-ui-ng-core-headline.d.ts +38 -0
  132. package/types/frame-kit-ui-ng-core-icon.d.ts +74 -0
  133. package/types/frame-kit-ui-ng-core-image.d.ts +93 -0
  134. package/types/frame-kit-ui-ng-core-link.d.ts +251 -0
  135. package/types/frame-kit-ui-ng-core-separator.d.ts +28 -0
  136. package/types/frame-kit-ui-ng-core-text.d.ts +186 -0
  137. package/types/frame-kit-ui-ng-directives-infinite-scroll.d.ts +42 -0
  138. package/types/frame-kit-ui-ng-directives-spotlight.d.ts +51 -0
  139. package/types/frame-kit-ui-ng-directives-tooltip.d.ts +70 -0
  140. package/types/frame-kit-ui-ng-docs-endpoint-link.d.ts +43 -0
  141. package/types/frame-kit-ui-ng-docs-method-badge.d.ts +30 -0
  142. package/types/frame-kit-ui-ng-forms.d.ts +1674 -0
  143. package/types/frame-kit-ui-ng-layouts-app-shell.d.ts +75 -0
  144. package/types/frame-kit-ui-ng-layouts-content-split.d.ts +43 -0
  145. package/types/frame-kit-ui-ng-services-overlay-orchestrator.d.ts +96 -0
  146. package/types/frame-kit-ui-ng-services-spotlight.d.ts +32 -0
  147. package/types/frame-kit-ui-ng-services-toast.d.ts +100 -0
  148. package/types/frame-kit-ui-ng-ui-accordion.d.ts +86 -0
  149. package/types/frame-kit-ui-ng-ui-alert.d.ts +34 -0
  150. package/types/frame-kit-ui-ng-ui-avatar-stack.d.ts +38 -0
  151. package/types/frame-kit-ui-ng-ui-avatar.d.ts +36 -0
  152. package/types/frame-kit-ui-ng-ui-badge.d.ts +33 -0
  153. package/types/frame-kit-ui-ng-ui-breadcrumb.d.ts +45 -0
  154. package/types/frame-kit-ui-ng-ui-button.d.ts +48 -0
  155. package/types/frame-kit-ui-ng-ui-callout.d.ts +26 -0
  156. package/types/frame-kit-ui-ng-ui-card.d.ts +30 -0
  157. package/types/frame-kit-ui-ng-ui-copyable-field.d.ts +62 -0
  158. package/types/frame-kit-ui-ng-ui-data-table.d.ts +482 -0
  159. package/types/frame-kit-ui-ng-ui-dialog.d.ts +166 -0
  160. package/types/frame-kit-ui-ng-ui-drawer.d.ts +130 -0
  161. package/types/frame-kit-ui-ng-ui-dropdown-menu.d.ts +77 -0
  162. package/types/frame-kit-ui-ng-ui-editable-field.d.ts +65 -0
  163. package/types/frame-kit-ui-ng-ui-icon-badge.d.ts +45 -0
  164. package/types/frame-kit-ui-ng-ui-icon-list.d.ts +67 -0
  165. package/types/frame-kit-ui-ng-ui-inline-edit.d.ts +44 -0
  166. package/types/frame-kit-ui-ng-ui-list-editor.d.ts +56 -0
  167. package/types/frame-kit-ui-ng-ui-loader.d.ts +32 -0
  168. package/types/frame-kit-ui-ng-ui-menu-item.d.ts +27 -0
  169. package/types/frame-kit-ui-ng-ui-nav-brand.d.ts +25 -0
  170. package/types/frame-kit-ui-ng-ui-nav-group.d.ts +60 -0
  171. package/types/frame-kit-ui-ng-ui-nav-separator.d.ts +33 -0
  172. package/types/frame-kit-ui-ng-ui-node-tree-breadcrumb.d.ts +35 -0
  173. package/types/frame-kit-ui-ng-ui-node-tree.d.ts +135 -0
  174. package/types/frame-kit-ui-ng-ui-note.d.ts +22 -0
  175. package/types/frame-kit-ui-ng-ui-numbered-list.d.ts +52 -0
  176. package/types/frame-kit-ui-ng-ui-pagination.d.ts +49 -0
  177. package/types/frame-kit-ui-ng-ui-progress-bar.d.ts +50 -0
  178. package/types/frame-kit-ui-ng-ui-sidenav-link.d.ts +24 -0
  179. package/types/frame-kit-ui-ng-ui-tabs.d.ts +266 -0
  180. package/types/frame-kit-ui-ng-ui-timeline.d.ts +42 -0
  181. package/types/frame-kit-ui-ng-ui-toast.d.ts +56 -0
  182. package/types/frame-kit-ui-ng-ui-user-menu.d.ts +87 -0
  183. package/types/frame-kit-ui-ng-ui-wizard-dialog.d.ts +116 -0
  184. package/types/frame-kit-ui-ng.d.ts +53 -0
  185. package/ui/accordion/README.md +261 -0
  186. package/ui/alert/README.md +211 -0
  187. package/ui/avatar/README.md +167 -0
  188. package/ui/avatar-stack/README.md +164 -0
  189. package/ui/badge/README.md +162 -0
  190. package/ui/breadcrumb/README.md +240 -0
  191. package/ui/button/README.md +184 -0
  192. package/ui/callout/README.md +159 -0
  193. package/ui/card/README.md +174 -0
  194. package/ui/copyable-field/README.md +235 -0
  195. package/ui/data-table/README.md +408 -0
  196. package/ui/dialog/README.md +222 -0
  197. package/ui/drawer/README.md +274 -0
  198. package/ui/dropdown-menu/README.md +336 -0
  199. package/ui/editable-field/README.md +171 -0
  200. package/ui/icon-badge/README.md +131 -0
  201. package/ui/icon-list/README.md +205 -0
  202. package/ui/inline-edit/README.md +135 -0
  203. package/ui/list-editor/README.md +162 -0
  204. package/ui/loader/README.md +160 -0
  205. package/ui/menu-item/README.md +204 -0
  206. package/ui/nav-brand/README.md +111 -0
  207. package/ui/nav-group/README.md +145 -0
  208. package/ui/nav-separator/README.md +44 -0
  209. package/ui/node-tree/README.md +278 -0
  210. package/ui/node-tree-breadcrumb/README.md +164 -0
  211. package/ui/note/README.md +146 -0
  212. package/ui/numbered-list/README.md +187 -0
  213. package/ui/pagination/README.md +174 -0
  214. package/ui/progress-bar/README.md +223 -0
  215. package/ui/sidenav-link/README.md +214 -0
  216. package/ui/tabs/README.md +204 -0
  217. package/ui/timeline/README.md +285 -0
  218. package/ui/toast/README.md +243 -0
  219. package/ui/user-menu/README.md +260 -0
  220. package/ui/wizard-dialog/README.md +283 -0
@@ -0,0 +1,283 @@
1
+ # fk-wizard-dialog
2
+
3
+ A service-driven wizard dialog for multi-step workflows. Opens its own dialog via `DialogService`, placing the stepper and scrollable content in the body and action buttons in the pinned footer.
4
+
5
+ ## API
6
+
7
+ ### WizardDialogService
8
+
9
+ | Method | Returns | Description |
10
+ | --------------------------------------- | --------------------------------- | ------------------------------------------------------ |
11
+ | `open<TResult, TData>(content, config)` | `WizardDialogRef<TResult, TData>` | Opens a wizard dialog with the given content component |
12
+
13
+ ### WizardDialogConfig
14
+
15
+ | Option | Type | Default | Description |
16
+ | ------------------ | -------------------- | -------------- | -------------------------------------- |
17
+ | `steps` | `WizardDialogStep[]` | required | Step definitions (title + contentKey) |
18
+ | `linear` | `boolean` | `true` | Enforce sequential navigation |
19
+ | `submitLabel` | `string` | `"Submit"` | Label for the final step action button |
20
+ | `cancelLabel` | `string` | `"Cancel"` | Label for cancel button (first step) |
21
+ | `nextLabel` | `string` | `"Next"` | Label for next step button |
22
+ | `backLabel` | `string` | `"Back"` | Label for back button |
23
+ | `header` | `string` | — | Dialog header title |
24
+ | `size` | `DialogSize` | `"lg"` | Dialog size |
25
+ | `data` | `TData` | — | Data passed to the content component |
26
+ | `closable` | `boolean` | `true` | Show close button |
27
+ | `closeOnEscape` | `boolean` | `true` | Close on Escape key |
28
+ | `closeOnBackdrop` | `boolean` | `false` | Close on backdrop click |
29
+ | `animation` | `DialogAnimation` | `"scale-fade"` | Open/close animation |
30
+ | `fullscreenMobile` | `boolean` | `false` | Fullscreen on mobile viewports |
31
+ | `className` | `string` | — | Additional CSS class on dialog |
32
+ | `ariaLabel` | `string` | — | Accessible label for the dialog |
33
+ | `ariaDescribedBy` | `string` | — | ID of describing element |
34
+
35
+ ### WizardDialogRef
36
+
37
+ | Property / Method | Type | Description |
38
+ | ----------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
39
+ | `currentIndex` | `Signal<number>` | Current step index |
40
+ | `isFirstStep` | `Signal<boolean>` | Whether on the first step |
41
+ | `isLastStep` | `Signal<boolean>` | Whether on the last step |
42
+ | `totalSteps` | `Signal<number>` | Total number of steps |
43
+ | `currentStep` | `Signal<WizardDialogStep>` | Current step definition |
44
+ | `submitDisabled` | `WritableSignal<boolean>` | Disable submit button |
45
+ | `nextDisabled` | `WritableSignal<boolean>` | Disable next button |
46
+ | `chromeVisible` | `WritableSignal<boolean>` | Show or hide the stepper + footer (both flip together) |
47
+ | `extraAction` | `WritableSignal<WizardExtraAction\|null>` | Optional third footer button rendered between Back and Submit (see [Extra Footer Action](#extra-footer-action)) |
48
+ | `submitted` | `Observable<void>` | Emitted when submit is clicked |
49
+ | `stepChanged` | `Observable<number>` | Emitted when step changes |
50
+ | `data` | `TData` | Config data |
51
+ | `next()` | `boolean` | Advance to next step |
52
+ | `previous()` | `boolean` | Go back one step |
53
+ | `goTo(index)` | `boolean` | Jump to step (respects linear mode) |
54
+ | `close(result?)` | `void` | Close the dialog |
55
+ | `afterClosed()` | `Observable<TResult>` | Emitted after dialog closes |
56
+
57
+ ### WizardExtraAction
58
+
59
+ Metadata describing the optional third footer button. Set `wizardRef.extraAction` to this shape (or `null` to remove it).
60
+
61
+ | Field | Type | Default | Description |
62
+ | --------- | --------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------- |
63
+ | `label` | `string` | required | Button text |
64
+ | `variant` | `"primary" \| "outline" \| "secondary" \| "danger"` | `"outline"` | Visual variant. Defaults to outline so the extra action doesn't compete with the primary Submit button. |
65
+ | `onClick` | `() => void` | required | Click handler — typically calls `wizardRef.close(...)` with a sentinel that tells the host page how to react. |
66
+
67
+ ### Content
68
+
69
+ The content component is dynamically created inside the wizard body. It receives a `WIZARD_DIALOG_REF` injection token to access navigation state and lifecycle events. Step content is rendered via `@switch` on `wizardRef.currentIndex()`.
70
+
71
+ ## Features
72
+
73
+ - Service-driven: opens its own dialog with proper footer pinning
74
+ - Built-in stepper, scrollable body, and fixed action footer
75
+ - Linear and non-linear navigation modes
76
+ - Consumer controls submit/next disabled state via writable signals
77
+ - Token-driven theming with two-tier fallbacks
78
+ - Focus ring on stepper buttons for keyboard navigation
79
+
80
+ ## Quick Start
81
+
82
+ ```ts
83
+ // 1. Create a content component that injects WIZARD_DIALOG_REF
84
+ @Component({
85
+ template: `
86
+ @switch (wizardRef.currentIndex()) {
87
+ @case (0) {
88
+ <p>Step 1 content</p>
89
+ }
90
+ @case (1) {
91
+ <p>Step 2 content</p>
92
+ }
93
+ }
94
+ `,
95
+ })
96
+ class MyWizardContentComponent {
97
+ readonly wizardRef = inject(WIZARD_DIALOG_REF) as WizardDialogRef;
98
+
99
+ constructor() {
100
+ this.wizardRef.submitted.subscribe(() => {
101
+ // handle submit, then close
102
+ this.wizardRef.close('done');
103
+ });
104
+ }
105
+ }
106
+
107
+ // 2. Open the wizard dialog from a parent component
108
+ const ref = this.wizardDialogService.open(MyWizardContentComponent, {
109
+ header: 'Create Item',
110
+ steps: [
111
+ { title: 'Details', contentKey: 'details' },
112
+ { title: 'Review', contentKey: 'review' },
113
+ ],
114
+ submitLabel: 'Create',
115
+ });
116
+
117
+ ref.afterClosed().subscribe((result) => {
118
+ if (result) {
119
+ /* success */
120
+ }
121
+ });
122
+ ```
123
+
124
+ ## Import
125
+
126
+ ```ts
127
+ import { WizardDialogService, WizardDialogRef, WIZARD_DIALOG_REF } from '@frame-kit/ui-ng';
128
+ ```
129
+
130
+ ```ts
131
+ @Component({
132
+ selector: 'app-my-page',
133
+ templateUrl: './my-page.component.html',
134
+ })
135
+ export class MyPageComponent {
136
+ private readonly wizardDialogService = inject(WizardDialogService);
137
+ }
138
+ ```
139
+
140
+ ## Selector
141
+
142
+ This component is service-driven. There is no consumer-facing selector. Use `WizardDialogService.open()` to open the wizard dialog imperatively.
143
+
144
+ Internally, the container renders as `<fk-wizard-dialog-container>`, but this is not part of the public API.
145
+
146
+ ## Examples
147
+
148
+ ### Three-Step API Key Creation
149
+
150
+ ```ts
151
+ const ref = this.wizardDialogService.open(CreateApiKeyComponent, {
152
+ header: 'Create API Key',
153
+ steps: [
154
+ { title: 'Details', contentKey: 'details' },
155
+ { title: 'Permissions', contentKey: 'permissions' },
156
+ { title: 'Review', contentKey: 'review' },
157
+ ],
158
+ submitLabel: 'Create API Key',
159
+ size: 'lg',
160
+ });
161
+
162
+ ref.afterClosed().subscribe((created) => {
163
+ if (created) {
164
+ this.refresh();
165
+ }
166
+ });
167
+ ```
168
+
169
+ ### Non-Linear Navigation
170
+
171
+ ```ts
172
+ const ref = this.wizardDialogService.open(SettingsComponent, {
173
+ header: 'Settings',
174
+ steps: [
175
+ { title: 'General', contentKey: 'general' },
176
+ { title: 'Advanced', contentKey: 'advanced' },
177
+ { title: 'Review', contentKey: 'review' },
178
+ ],
179
+ linear: false,
180
+ submitLabel: 'Save',
181
+ });
182
+ ```
183
+
184
+ ### Controlling Button State from Content
185
+
186
+ ```ts
187
+ @Component({ ... })
188
+ class MyContentComponent {
189
+ readonly wizardRef = inject(WIZARD_DIALOG_REF) as WizardDialogRef;
190
+ readonly form = new FormGroup({ name: new FormControl("", Validators.required) });
191
+
192
+ constructor() {
193
+ // Disable Next when form is invalid
194
+ effect(() => {
195
+ this.wizardRef.nextDisabled.set(this.form.invalid);
196
+ });
197
+ }
198
+ }
199
+ ```
200
+
201
+ ### Extra Footer Action
202
+
203
+ A single extra `<fk-button>` can be slotted between Back and Submit on any step via `wizardRef.extraAction`. Typical use: a "View X" jump-off on the results/last step so the host page can branch on a sentinel value when the wizard closes.
204
+
205
+ The button only renders while `extraAction` is non-null, so consumers usually drive it from an `effect` keyed on `currentIndex`:
206
+
207
+ ```ts
208
+ @Component({ ... })
209
+ class MyContentComponent {
210
+ readonly wizardRef = inject(WIZARD_DIALOG_REF) as WizardDialogRef<"done" | "view">;
211
+
212
+ constructor() {
213
+ effect(() => {
214
+ const idx = this.wizardRef.currentIndex();
215
+
216
+ if (this.wizardRef.isLastStep()) {
217
+ this.wizardRef.extraAction.set({
218
+ label: "View Identities",
219
+ // omit `variant` to default to "outline"
220
+ onClick: () => this.wizardRef.close("view"),
221
+ });
222
+ } else {
223
+ this.wizardRef.extraAction.set(null);
224
+ }
225
+ });
226
+ }
227
+ }
228
+ ```
229
+
230
+ Then on the consumer side:
231
+
232
+ ```ts
233
+ ref.afterClosed().subscribe((action) => {
234
+ if (action === 'view') {
235
+ this.router.navigate(['./directory'], { relativeTo: this.route });
236
+ }
237
+ });
238
+ ```
239
+
240
+ The footer's existing flex layout (`flex: 1 1 0` on each child) stretches all three buttons evenly when the extra action is present. If a future use case needs more than one extra button or a fully custom footer row, extend this API rather than adding parallel signals — there's no other footer-projection mechanism on the wizard container.
241
+
242
+ ## Accessibility
243
+
244
+ - Stepper uses `role="tablist"` with `role="tab"` buttons
245
+ - Active tab indicated via `aria-selected`
246
+ - Disabled future steps in linear mode prevent keyboard activation
247
+ - Focus ring on step buttons via `--fk-focus-ring` token
248
+ - Footer buttons are standard `fk-button` components with full keyboard support
249
+ - Dialog provides focus trapping via `cdkTrapFocus` and restores focus on close
250
+ - `ariaLabel` and `ariaDescribedBy` pass through to the underlying dialog
251
+
252
+ ## Design Tokens
253
+
254
+ ```scss
255
+ --fk-wizard-dialog-stepper-gap
256
+ --fk-wizard-dialog-stepper-padding
257
+ --fk-wizard-dialog-step-color
258
+ --fk-wizard-dialog-step-active-color
259
+ --fk-wizard-dialog-step-completed-color
260
+ --fk-wizard-dialog-step-number-active-color
261
+ --fk-wizard-dialog-body-padding
262
+ --fk-wizard-dialog-footer-gap
263
+ --fk-wizard-dialog-footer-padding
264
+ --fk-wizard-dialog-footer-border
265
+ ```
266
+
267
+ Override in your app stylesheet:
268
+
269
+ ```scss
270
+ :root {
271
+ --fk-wizard-dialog-step-active-color: #0070f3;
272
+ --fk-wizard-dialog-footer-border: none;
273
+ }
274
+ ```
275
+
276
+ ## Behavior Notes
277
+
278
+ - The wizard opens as a full dialog overlay, not as inline content
279
+ - The body section scrolls independently — the stepper and footer remain fixed
280
+ - `--fk-form-field-gap` is set to `0` inside the body to match FormRenderer spacing
281
+ - In linear mode, only previously visited steps can be clicked in the stepper
282
+ - The content component is dynamically created inside the wizard body via `ViewContainerRef`
283
+ - Cancel button closes the dialog with `undefined`; submit emits on the `submitted` observable for the consumer to handle