@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.
- package/COMPONENTS.md +683 -0
- package/DEVELOPMENT_GUIDE.md +1102 -0
- package/LICENSE +21 -0
- package/README.md +69 -0
- package/THEMING.md +130 -0
- package/core/headline/README.md +121 -0
- package/core/icon/README.md +173 -0
- package/core/image/README.md +210 -0
- package/core/link/README.md +297 -0
- package/core/separator/README.md +145 -0
- package/core/text/README.md +240 -0
- package/directives/infinite-scroll/README.md +102 -0
- package/directives/spotlight/README.md +154 -0
- package/directives/tooltip/README.md +147 -0
- package/docs/endpoint-link/README.md +142 -0
- package/docs/method-badge/README.md +154 -0
- package/fesm2022/frame-kit-ui-ng-core-headline.mjs +122 -0
- package/fesm2022/frame-kit-ui-ng-core-headline.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-core-icon.mjs +189 -0
- package/fesm2022/frame-kit-ui-ng-core-icon.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-core-image.mjs +123 -0
- package/fesm2022/frame-kit-ui-ng-core-image.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-core-link.mjs +369 -0
- package/fesm2022/frame-kit-ui-ng-core-link.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-core-separator.mjs +59 -0
- package/fesm2022/frame-kit-ui-ng-core-separator.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-core-text.mjs +204 -0
- package/fesm2022/frame-kit-ui-ng-core-text.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-directives-infinite-scroll.mjs +74 -0
- package/fesm2022/frame-kit-ui-ng-directives-infinite-scroll.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-directives-spotlight.mjs +76 -0
- package/fesm2022/frame-kit-ui-ng-directives-spotlight.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-directives-tooltip.mjs +425 -0
- package/fesm2022/frame-kit-ui-ng-directives-tooltip.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-docs-endpoint-link.mjs +63 -0
- package/fesm2022/frame-kit-ui-ng-docs-endpoint-link.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-docs-method-badge.mjs +43 -0
- package/fesm2022/frame-kit-ui-ng-docs-method-badge.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-forms.mjs +3632 -0
- package/fesm2022/frame-kit-ui-ng-forms.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-layouts-app-shell.mjs +239 -0
- package/fesm2022/frame-kit-ui-ng-layouts-app-shell.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-layouts-content-split.mjs +132 -0
- package/fesm2022/frame-kit-ui-ng-layouts-content-split.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-services-overlay-orchestrator.mjs +133 -0
- package/fesm2022/frame-kit-ui-ng-services-overlay-orchestrator.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-services-spotlight.mjs +60 -0
- package/fesm2022/frame-kit-ui-ng-services-spotlight.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-services-toast.mjs +166 -0
- package/fesm2022/frame-kit-ui-ng-services-toast.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-accordion.mjs +214 -0
- package/fesm2022/frame-kit-ui-ng-ui-accordion.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-alert.mjs +82 -0
- package/fesm2022/frame-kit-ui-ng-ui-alert.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-avatar-stack.mjs +76 -0
- package/fesm2022/frame-kit-ui-ng-ui-avatar-stack.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-avatar.mjs +81 -0
- package/fesm2022/frame-kit-ui-ng-ui-avatar.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-badge.mjs +81 -0
- package/fesm2022/frame-kit-ui-ng-ui-badge.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-breadcrumb.mjs +68 -0
- package/fesm2022/frame-kit-ui-ng-ui-breadcrumb.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-button.mjs +108 -0
- package/fesm2022/frame-kit-ui-ng-ui-button.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-callout.mjs +58 -0
- package/fesm2022/frame-kit-ui-ng-ui-callout.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-card.mjs +70 -0
- package/fesm2022/frame-kit-ui-ng-ui-card.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-copyable-field.mjs +113 -0
- package/fesm2022/frame-kit-ui-ng-ui-copyable-field.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-data-table.mjs +1288 -0
- package/fesm2022/frame-kit-ui-ng-ui-data-table.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-dialog.mjs +456 -0
- package/fesm2022/frame-kit-ui-ng-ui-dialog.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-drawer.mjs +398 -0
- package/fesm2022/frame-kit-ui-ng-ui-drawer.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-dropdown-menu.mjs +398 -0
- package/fesm2022/frame-kit-ui-ng-ui-dropdown-menu.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-editable-field.mjs +125 -0
- package/fesm2022/frame-kit-ui-ng-ui-editable-field.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-icon-badge.mjs +113 -0
- package/fesm2022/frame-kit-ui-ng-ui-icon-badge.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-icon-list.mjs +111 -0
- package/fesm2022/frame-kit-ui-ng-ui-icon-list.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-inline-edit.mjs +103 -0
- package/fesm2022/frame-kit-ui-ng-ui-inline-edit.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-list-editor.mjs +135 -0
- package/fesm2022/frame-kit-ui-ng-ui-list-editor.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-loader.mjs +81 -0
- package/fesm2022/frame-kit-ui-ng-ui-loader.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-menu-item.mjs +79 -0
- package/fesm2022/frame-kit-ui-ng-ui-menu-item.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-nav-brand.mjs +40 -0
- package/fesm2022/frame-kit-ui-ng-ui-nav-brand.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-nav-group.mjs +110 -0
- package/fesm2022/frame-kit-ui-ng-ui-nav-group.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-nav-separator.mjs +91 -0
- package/fesm2022/frame-kit-ui-ng-ui-nav-separator.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-node-tree-breadcrumb.mjs +86 -0
- package/fesm2022/frame-kit-ui-ng-ui-node-tree-breadcrumb.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-node-tree.mjs +443 -0
- package/fesm2022/frame-kit-ui-ng-ui-node-tree.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-note.mjs +56 -0
- package/fesm2022/frame-kit-ui-ng-ui-note.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-numbered-list.mjs +105 -0
- package/fesm2022/frame-kit-ui-ng-ui-numbered-list.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-pagination.mjs +110 -0
- package/fesm2022/frame-kit-ui-ng-ui-pagination.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-progress-bar.mjs +129 -0
- package/fesm2022/frame-kit-ui-ng-ui-progress-bar.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-sidenav-link.mjs +42 -0
- package/fesm2022/frame-kit-ui-ng-ui-sidenav-link.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-tabs.mjs +894 -0
- package/fesm2022/frame-kit-ui-ng-ui-tabs.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-timeline.mjs +81 -0
- package/fesm2022/frame-kit-ui-ng-ui-timeline.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-toast.mjs +179 -0
- package/fesm2022/frame-kit-ui-ng-ui-toast.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-user-menu.mjs +143 -0
- package/fesm2022/frame-kit-ui-ng-ui-user-menu.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng-ui-wizard-dialog.mjs +191 -0
- package/fesm2022/frame-kit-ui-ng-ui-wizard-dialog.mjs.map +1 -0
- package/fesm2022/frame-kit-ui-ng.mjs +58 -0
- package/fesm2022/frame-kit-ui-ng.mjs.map +1 -0
- package/layouts/app-shell/README.md +357 -0
- package/layouts/content-split/README.md +180 -0
- package/package.json +253 -0
- package/services/overlay-orchestrator/README.md +184 -0
- package/services/spotlight/README.md +61 -0
- package/services/toast/README.md +118 -0
- package/types/frame-kit-ui-ng-core-headline.d.ts +38 -0
- package/types/frame-kit-ui-ng-core-icon.d.ts +74 -0
- package/types/frame-kit-ui-ng-core-image.d.ts +93 -0
- package/types/frame-kit-ui-ng-core-link.d.ts +251 -0
- package/types/frame-kit-ui-ng-core-separator.d.ts +28 -0
- package/types/frame-kit-ui-ng-core-text.d.ts +186 -0
- package/types/frame-kit-ui-ng-directives-infinite-scroll.d.ts +42 -0
- package/types/frame-kit-ui-ng-directives-spotlight.d.ts +51 -0
- package/types/frame-kit-ui-ng-directives-tooltip.d.ts +70 -0
- package/types/frame-kit-ui-ng-docs-endpoint-link.d.ts +43 -0
- package/types/frame-kit-ui-ng-docs-method-badge.d.ts +30 -0
- package/types/frame-kit-ui-ng-forms.d.ts +1674 -0
- package/types/frame-kit-ui-ng-layouts-app-shell.d.ts +75 -0
- package/types/frame-kit-ui-ng-layouts-content-split.d.ts +43 -0
- package/types/frame-kit-ui-ng-services-overlay-orchestrator.d.ts +96 -0
- package/types/frame-kit-ui-ng-services-spotlight.d.ts +32 -0
- package/types/frame-kit-ui-ng-services-toast.d.ts +100 -0
- package/types/frame-kit-ui-ng-ui-accordion.d.ts +86 -0
- package/types/frame-kit-ui-ng-ui-alert.d.ts +34 -0
- package/types/frame-kit-ui-ng-ui-avatar-stack.d.ts +38 -0
- package/types/frame-kit-ui-ng-ui-avatar.d.ts +36 -0
- package/types/frame-kit-ui-ng-ui-badge.d.ts +33 -0
- package/types/frame-kit-ui-ng-ui-breadcrumb.d.ts +45 -0
- package/types/frame-kit-ui-ng-ui-button.d.ts +48 -0
- package/types/frame-kit-ui-ng-ui-callout.d.ts +26 -0
- package/types/frame-kit-ui-ng-ui-card.d.ts +30 -0
- package/types/frame-kit-ui-ng-ui-copyable-field.d.ts +62 -0
- package/types/frame-kit-ui-ng-ui-data-table.d.ts +482 -0
- package/types/frame-kit-ui-ng-ui-dialog.d.ts +166 -0
- package/types/frame-kit-ui-ng-ui-drawer.d.ts +130 -0
- package/types/frame-kit-ui-ng-ui-dropdown-menu.d.ts +77 -0
- package/types/frame-kit-ui-ng-ui-editable-field.d.ts +65 -0
- package/types/frame-kit-ui-ng-ui-icon-badge.d.ts +45 -0
- package/types/frame-kit-ui-ng-ui-icon-list.d.ts +67 -0
- package/types/frame-kit-ui-ng-ui-inline-edit.d.ts +44 -0
- package/types/frame-kit-ui-ng-ui-list-editor.d.ts +56 -0
- package/types/frame-kit-ui-ng-ui-loader.d.ts +32 -0
- package/types/frame-kit-ui-ng-ui-menu-item.d.ts +27 -0
- package/types/frame-kit-ui-ng-ui-nav-brand.d.ts +25 -0
- package/types/frame-kit-ui-ng-ui-nav-group.d.ts +60 -0
- package/types/frame-kit-ui-ng-ui-nav-separator.d.ts +33 -0
- package/types/frame-kit-ui-ng-ui-node-tree-breadcrumb.d.ts +35 -0
- package/types/frame-kit-ui-ng-ui-node-tree.d.ts +135 -0
- package/types/frame-kit-ui-ng-ui-note.d.ts +22 -0
- package/types/frame-kit-ui-ng-ui-numbered-list.d.ts +52 -0
- package/types/frame-kit-ui-ng-ui-pagination.d.ts +49 -0
- package/types/frame-kit-ui-ng-ui-progress-bar.d.ts +50 -0
- package/types/frame-kit-ui-ng-ui-sidenav-link.d.ts +24 -0
- package/types/frame-kit-ui-ng-ui-tabs.d.ts +266 -0
- package/types/frame-kit-ui-ng-ui-timeline.d.ts +42 -0
- package/types/frame-kit-ui-ng-ui-toast.d.ts +56 -0
- package/types/frame-kit-ui-ng-ui-user-menu.d.ts +87 -0
- package/types/frame-kit-ui-ng-ui-wizard-dialog.d.ts +116 -0
- package/types/frame-kit-ui-ng.d.ts +53 -0
- package/ui/accordion/README.md +261 -0
- package/ui/alert/README.md +211 -0
- package/ui/avatar/README.md +167 -0
- package/ui/avatar-stack/README.md +164 -0
- package/ui/badge/README.md +162 -0
- package/ui/breadcrumb/README.md +240 -0
- package/ui/button/README.md +184 -0
- package/ui/callout/README.md +159 -0
- package/ui/card/README.md +174 -0
- package/ui/copyable-field/README.md +235 -0
- package/ui/data-table/README.md +408 -0
- package/ui/dialog/README.md +222 -0
- package/ui/drawer/README.md +274 -0
- package/ui/dropdown-menu/README.md +336 -0
- package/ui/editable-field/README.md +171 -0
- package/ui/icon-badge/README.md +131 -0
- package/ui/icon-list/README.md +205 -0
- package/ui/inline-edit/README.md +135 -0
- package/ui/list-editor/README.md +162 -0
- package/ui/loader/README.md +160 -0
- package/ui/menu-item/README.md +204 -0
- package/ui/nav-brand/README.md +111 -0
- package/ui/nav-group/README.md +145 -0
- package/ui/nav-separator/README.md +44 -0
- package/ui/node-tree/README.md +278 -0
- package/ui/node-tree-breadcrumb/README.md +164 -0
- package/ui/note/README.md +146 -0
- package/ui/numbered-list/README.md +187 -0
- package/ui/pagination/README.md +174 -0
- package/ui/progress-bar/README.md +223 -0
- package/ui/sidenav-link/README.md +214 -0
- package/ui/tabs/README.md +204 -0
- package/ui/timeline/README.md +285 -0
- package/ui/toast/README.md +243 -0
- package/ui/user-menu/README.md +260 -0
- 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
|