@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,278 @@
|
|
|
1
|
+
# fk-node-tree
|
|
2
|
+
|
|
3
|
+
A token-driven, hierarchical tree component for Angular with expand/collapse, selection, drag-and-drop reparenting, position-aware sibling insertion, consumer drop validation, and custom row templates.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## API
|
|
8
|
+
|
|
9
|
+
### Inputs
|
|
10
|
+
|
|
11
|
+
| Input | Type | Default | Description |
|
|
12
|
+
| ----------------- | ------------------------ | ----------- | ------------------------------------------------------------------- |
|
|
13
|
+
| `nodes` | `TreeNode[]` | _required_ | Flat array of tree nodes; parent-child relationships via `parentId` |
|
|
14
|
+
| `selectedNodeId` | `string \| undefined` | `undefined` | Currently selected node ID |
|
|
15
|
+
| `expandedNodeIds` | `string[] \| undefined` | `undefined` | Controlled expanded state; `undefined` uses internal state |
|
|
16
|
+
| `draggable` | `boolean` | `false` | Enables drag-and-drop with drag handles |
|
|
17
|
+
| `canDrop` | `CanDropFn \| undefined` | `undefined` | Consumer callback to validate drop targets |
|
|
18
|
+
| `className` | `string` | `''` | Additional CSS classes for the host |
|
|
19
|
+
|
|
20
|
+
### Outputs
|
|
21
|
+
|
|
22
|
+
| Output | Type | Description |
|
|
23
|
+
| ------------ | ----------------- | ----------------------------------------------- |
|
|
24
|
+
| `nodeSelect` | `TreeNode` | Emitted when a row is clicked |
|
|
25
|
+
| `nodeExpand` | `NodeExpandEvent` | Emitted when a node is expanded or collapsed |
|
|
26
|
+
| `nodeDrop` | `NodeDropEvent` | Emitted when a valid drag-and-drop is completed |
|
|
27
|
+
|
|
28
|
+
### Types
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
interface TreeNode<T = unknown> {
|
|
32
|
+
id: string;
|
|
33
|
+
label: string;
|
|
34
|
+
icon?: string;
|
|
35
|
+
parentId?: string | null;
|
|
36
|
+
draggable?: boolean;
|
|
37
|
+
data?: T;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface NodeExpandEvent {
|
|
41
|
+
nodeId: string;
|
|
42
|
+
expanded: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type DropPosition = 'before' | 'inside' | 'after';
|
|
46
|
+
|
|
47
|
+
interface NodeDropEvent {
|
|
48
|
+
nodeId: string;
|
|
49
|
+
newParentId: string | null;
|
|
50
|
+
previousParentId: string | null;
|
|
51
|
+
position: DropPosition;
|
|
52
|
+
referenceNodeId: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
type CanDropFn = (draggedNode: FlatNode, targetNode: FlatNode, position: DropPosition) => boolean;
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Content Projection
|
|
59
|
+
|
|
60
|
+
Custom row templates use the `fkNodeTreeRow` structural directive:
|
|
61
|
+
|
|
62
|
+
```html
|
|
63
|
+
<fk-node-tree [nodes]="nodes">
|
|
64
|
+
<ng-template fkNodeTreeRow let-node>
|
|
65
|
+
<fk-icon [name]="node.icon" size="sm" />
|
|
66
|
+
<span>{{ node.label }}</span>
|
|
67
|
+
</ng-template>
|
|
68
|
+
</fk-node-tree>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Features
|
|
74
|
+
|
|
75
|
+
- Hierarchical tree rendering from flat node array
|
|
76
|
+
- Expand/collapse (uncontrolled and controlled)
|
|
77
|
+
- Row selection
|
|
78
|
+
- Drag-and-drop reparenting via drag handle
|
|
79
|
+
- Position-aware drops (before, inside, after)
|
|
80
|
+
- Consumer drop validation via `canDrop` callback
|
|
81
|
+
- Auto-expand on hover during drag
|
|
82
|
+
- Custom row templates
|
|
83
|
+
- Token-driven styling with dark mode support
|
|
84
|
+
- Accessible (role=tree, treeitem, aria-level, aria-expanded, aria-selected)
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Quick Start
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<fk-node-tree [nodes]="nodes" [selectedNodeId]="selectedId" (nodeSelect)="onSelect($event)" (nodeExpand)="onExpand($event)" />
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Import
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import { FkNodeTreeComponent } from '@frame-kit/ui-ng';
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
@Component({
|
|
104
|
+
selector: 'app-org-tree',
|
|
105
|
+
imports: [FkNodeTreeComponent],
|
|
106
|
+
templateUrl: './org-tree.component.html',
|
|
107
|
+
})
|
|
108
|
+
export class OrgTreeComponent {
|
|
109
|
+
nodes: TreeNode[] = [
|
|
110
|
+
{ id: 'root', label: 'Acme Realty', parentId: null },
|
|
111
|
+
{ id: 'west', label: 'West Region', parentId: 'root' },
|
|
112
|
+
{ id: 'east', label: 'East Region', parentId: 'root' },
|
|
113
|
+
];
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Selector
|
|
120
|
+
|
|
121
|
+
```html
|
|
122
|
+
<fk-node-tree></fk-node-tree>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Examples
|
|
128
|
+
|
|
129
|
+
### Basic tree
|
|
130
|
+
|
|
131
|
+
```html
|
|
132
|
+
<fk-node-tree [nodes]="nodes" [selectedNodeId]="selectedId" (nodeSelect)="onSelect($event)" (nodeExpand)="onExpand($event)" />
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Controlled expand
|
|
136
|
+
|
|
137
|
+
```html
|
|
138
|
+
<fk-node-tree [nodes]="nodes" [expandedNodeIds]="expandedIds" (nodeExpand)="onExpand($event)" />
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
When `expandedNodeIds` is provided, the tree delegates expand/collapse state to the consumer.
|
|
142
|
+
|
|
143
|
+
### Drag and drop
|
|
144
|
+
|
|
145
|
+
```html
|
|
146
|
+
<fk-node-tree [nodes]="nodes" [draggable]="true" (nodeDrop)="onDrop($event)" />
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
When `draggable` is true, each row with `draggable !== false` shows a grip handle. Dragging to the top 25% of a row triggers a `'before'` drop, the middle 50% triggers `'inside'`, and the bottom 25% triggers `'after'`.
|
|
150
|
+
|
|
151
|
+
### Drop validation
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
canDrop: CanDropFn = (dragged, target, position) => {
|
|
155
|
+
// Block agents from being dropped into regions
|
|
156
|
+
if (dragged.id.startsWith('agent-') && target.id.startsWith('region-')) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
};
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
```html
|
|
164
|
+
<fk-node-tree [nodes]="nodes" [draggable]="true" [canDrop]="canDrop" (nodeDrop)="onDrop($event)" />
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
When `canDrop` returns `false`, the drop target is not highlighted and the drop is blocked.
|
|
168
|
+
|
|
169
|
+
### Custom row template
|
|
170
|
+
|
|
171
|
+
```html
|
|
172
|
+
<fk-node-tree [nodes]="nodes">
|
|
173
|
+
<ng-template fkNodeTreeRow let-node>
|
|
174
|
+
@if (node.icon) {
|
|
175
|
+
<fk-icon [name]="node.icon" size="sm" />
|
|
176
|
+
}
|
|
177
|
+
<span style="font-weight: 500;">{{ node.label }}</span>
|
|
178
|
+
<span style="margin-left: auto; font-size: 0.75rem;">Level {{ node.level }}</span>
|
|
179
|
+
</ng-template>
|
|
180
|
+
</fk-node-tree>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Locked nodes
|
|
184
|
+
|
|
185
|
+
Set `draggable: false` on individual `TreeNode` entries to prevent them from being dragged while keeping the rest of the tree draggable.
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
nodes = [
|
|
189
|
+
{ id: 'root', label: 'Root', parentId: null, draggable: false },
|
|
190
|
+
{ id: 'child', label: 'Child', parentId: 'root' },
|
|
191
|
+
];
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Accessibility
|
|
197
|
+
|
|
198
|
+
- Host element has `role="tree"`
|
|
199
|
+
- Each row has `role="treeitem"` with `aria-level` (1-based), `aria-expanded`, and `aria-selected`
|
|
200
|
+
- All rows are keyboard-focusable (`tabindex="0"`)
|
|
201
|
+
- Expand/collapse toggle has `aria-label` ("Expand" / "Collapse")
|
|
202
|
+
- Drag handle SVG is `aria-hidden="true"`
|
|
203
|
+
- Focus ring uses the `--fk-focus-ring` token
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Design Tokens
|
|
208
|
+
|
|
209
|
+
`fk-node-tree` uses the following design tokens:
|
|
210
|
+
|
|
211
|
+
```scss
|
|
212
|
+
// Row layout
|
|
213
|
+
--fk-node-tree-row-gap
|
|
214
|
+
--fk-node-tree-row-padding
|
|
215
|
+
--fk-node-tree-row-radius
|
|
216
|
+
--fk-node-tree-row-color
|
|
217
|
+
--fk-node-tree-row-font-size
|
|
218
|
+
|
|
219
|
+
// Hover & selection
|
|
220
|
+
--fk-node-tree-row-bg-hover
|
|
221
|
+
--fk-node-tree-row-bg-selected
|
|
222
|
+
--fk-node-tree-row-color-selected
|
|
223
|
+
--fk-node-tree-row-font-weight-selected
|
|
224
|
+
|
|
225
|
+
// Toggle chevron
|
|
226
|
+
--fk-node-tree-row-toggle-color
|
|
227
|
+
--fk-node-tree-row-toggle-color-hover
|
|
228
|
+
--fk-node-tree-row-toggle-bg-hover
|
|
229
|
+
|
|
230
|
+
// Drag handle
|
|
231
|
+
--fk-node-tree-row-handle-color
|
|
232
|
+
--fk-node-tree-row-handle-color-hover
|
|
233
|
+
|
|
234
|
+
// Drop target
|
|
235
|
+
--fk-node-tree-row-bg-drop-target
|
|
236
|
+
--fk-node-tree-row-border-drop-target
|
|
237
|
+
--fk-node-tree-row-drag-source-opacity
|
|
238
|
+
|
|
239
|
+
// Drag preview & placeholder
|
|
240
|
+
--fk-node-tree-drag-preview-bg
|
|
241
|
+
--fk-node-tree-drag-preview-shadow
|
|
242
|
+
--fk-node-tree-drag-placeholder-bg
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Customizing Tokens
|
|
246
|
+
|
|
247
|
+
Override tokens in your application's global stylesheet or a scoped selector:
|
|
248
|
+
|
|
249
|
+
```css
|
|
250
|
+
:root {
|
|
251
|
+
--fk-node-tree-row-bg-selected: #ede9fe;
|
|
252
|
+
--fk-node-tree-row-color-selected: #7c3aed;
|
|
253
|
+
--fk-node-tree-row-border-drop-target: #7c3aed;
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Or scope overrides to a specific context:
|
|
258
|
+
|
|
259
|
+
```css
|
|
260
|
+
.dark-theme fk-node-tree {
|
|
261
|
+
--fk-node-tree-row-color: #e2e8f0;
|
|
262
|
+
--fk-node-tree-row-bg-hover: #1e293b;
|
|
263
|
+
--fk-node-tree-row-bg-selected: rgba(99, 102, 241, 0.15);
|
|
264
|
+
--fk-node-tree-row-handle-color: #64748b;
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Behavior Notes
|
|
271
|
+
|
|
272
|
+
- Nodes are provided as a flat array. Parent-child relationships are derived from `parentId`.
|
|
273
|
+
- Nodes with `parentId: null` or `parentId: undefined` are treated as root nodes.
|
|
274
|
+
- When `expandedNodeIds` is provided, the tree operates in controlled mode and will not manage expand state internally.
|
|
275
|
+
- Self-drops and drops onto descendants are blocked automatically.
|
|
276
|
+
- The `canDrop` callback is invoked during drag movement, not at drop time, so invalid targets never highlight.
|
|
277
|
+
- Auto-expand during drag (800ms hover delay) only triggers for the `'inside'` drop position.
|
|
278
|
+
- The drag handle (`cdkDragHandle`) restricts drag initiation to the grip icon, allowing normal click interactions on the rest of the row.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# fk-node-tree-breadcrumb
|
|
2
|
+
|
|
3
|
+
A token-driven breadcrumb that displays the ancestry path from root to a
|
|
4
|
+
selected node in a tree hierarchy. Paired with `fk-node-tree` — consume a
|
|
5
|
+
flat `TreeNode[]` array plus a selected node id and render the path as
|
|
6
|
+
clickable ancestor buttons terminating in the current node.
|
|
7
|
+
|
|
8
|
+
Use this when the breadcrumb reflects a tree/hierarchy selection. For
|
|
9
|
+
route-driven crumbs (e.g. URL segments), use a route-based breadcrumb
|
|
10
|
+
instead — this component does not consume routes.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## API
|
|
15
|
+
|
|
16
|
+
### Inputs
|
|
17
|
+
|
|
18
|
+
| Input | Type | Default | Description |
|
|
19
|
+
| ---------------- | --------------------- | ----------- | --------------------------------------------------- |
|
|
20
|
+
| `nodes` | `TreeNode[]` | _required_ | Flat array of tree nodes with `parentId` references |
|
|
21
|
+
| `selectedNodeId` | `string \| undefined` | `undefined` | ID of the currently selected node |
|
|
22
|
+
| `className` | `string` | `''` | Additional CSS classes merged onto the host element |
|
|
23
|
+
|
|
24
|
+
### Outputs
|
|
25
|
+
|
|
26
|
+
| Output | Type | Description |
|
|
27
|
+
| ------------ | ------------------------ | -------------------------------------------- |
|
|
28
|
+
| `nodeSelect` | `NodeTreeBreadcrumbItem` | Emits when an ancestor breadcrumb is clicked |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- Computes full ancestry path from root to selected node
|
|
35
|
+
- Ancestor crumbs are clickable buttons; current node is a non-interactive span
|
|
36
|
+
- Inline SVG chevron separators
|
|
37
|
+
- Token-driven styling with two-tier fallbacks
|
|
38
|
+
- Self-sufficient rendering without any theme file loaded
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Quick Start
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<fk-node-tree-breadcrumb [nodes]="nodes()" [selectedNodeId]="selectedNodeId()" (nodeSelect)="onNodeSelect($event)" />
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Import
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { NodeTreeBreadcrumbComponent } from '@frame-kit/ui-ng';
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
@Component({
|
|
58
|
+
selector: 'app-example',
|
|
59
|
+
imports: [NodeTreeBreadcrumbComponent],
|
|
60
|
+
templateUrl: './example.component.html',
|
|
61
|
+
})
|
|
62
|
+
export class ExampleComponent {}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Selector
|
|
68
|
+
|
|
69
|
+
```html
|
|
70
|
+
<fk-node-tree-breadcrumb></fk-node-tree-breadcrumb>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Examples
|
|
76
|
+
|
|
77
|
+
### Root node selected
|
|
78
|
+
|
|
79
|
+
```html
|
|
80
|
+
<fk-node-tree-breadcrumb [nodes]="nodes" selectedNodeId="org-1" />
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Renders: **Acme Realty**
|
|
84
|
+
|
|
85
|
+
### Deep node selected
|
|
86
|
+
|
|
87
|
+
```html
|
|
88
|
+
<fk-node-tree-breadcrumb [nodes]="nodes" selectedNodeId="office-1" />
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Renders: Acme Realty > West Region > **Downtown Office**
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Accessibility
|
|
96
|
+
|
|
97
|
+
`fk-node-tree-breadcrumb` renders a `<nav>` element with proper ARIA attributes.
|
|
98
|
+
|
|
99
|
+
Accessibility behavior:
|
|
100
|
+
|
|
101
|
+
- Host has `role="navigation"` and `aria-label="Breadcrumb"`
|
|
102
|
+
- Rendered as an ordered list (`<ol>`) for semantic structure
|
|
103
|
+
- Ancestor crumbs are `<button>` elements for keyboard interaction
|
|
104
|
+
- Current (last) crumb has `aria-current="location"`
|
|
105
|
+
- Chevron separators are marked `aria-hidden="true"`
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Design Tokens
|
|
110
|
+
|
|
111
|
+
`fk-node-tree-breadcrumb` is styled entirely through design tokens.
|
|
112
|
+
|
|
113
|
+
### Component-specific tokens
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
--fk-node-tree-breadcrumb-gap
|
|
117
|
+
--fk-node-tree-breadcrumb-font-size
|
|
118
|
+
--fk-node-tree-breadcrumb-link-color
|
|
119
|
+
--fk-node-tree-breadcrumb-link-color-hover
|
|
120
|
+
--fk-node-tree-breadcrumb-current-color
|
|
121
|
+
--fk-node-tree-breadcrumb-current-font-weight
|
|
122
|
+
--fk-node-tree-breadcrumb-separator-color
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Shared tokens
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
--fk-rhythm-1
|
|
129
|
+
--fk-typography-caption-font-size
|
|
130
|
+
--fk-font-weight-medium
|
|
131
|
+
--fk-color-muted
|
|
132
|
+
--fk-color-text
|
|
133
|
+
--fk-focus-ring
|
|
134
|
+
--fk-radius-sm
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Customizing Tokens
|
|
138
|
+
|
|
139
|
+
Override tokens in your application's stylesheet:
|
|
140
|
+
|
|
141
|
+
```scss
|
|
142
|
+
:root {
|
|
143
|
+
--fk-node-tree-breadcrumb-font-size: 0.875rem;
|
|
144
|
+
--fk-node-tree-breadcrumb-link-color: #475569;
|
|
145
|
+
--fk-node-tree-breadcrumb-current-font-weight: 600;
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Or scope overrides to a specific context:
|
|
150
|
+
|
|
151
|
+
```scss
|
|
152
|
+
.dark-theme fk-node-tree-breadcrumb {
|
|
153
|
+
--fk-node-tree-breadcrumb-link-color: #94a3b8;
|
|
154
|
+
--fk-node-tree-breadcrumb-current-color: #e2e8f0;
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Behavior Notes
|
|
161
|
+
|
|
162
|
+
- Returns an empty list when `selectedNodeId` is `undefined` or does not match any node
|
|
163
|
+
- The `NodeTreeBreadcrumbItem` type includes `id`, `label`, and optional `icon` fields (icon is not rendered by the breadcrumb but is available for consumers)
|
|
164
|
+
- `text-transform` is not applied by the component; consumers can apply it externally via CSS
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# fk-note
|
|
2
|
+
|
|
3
|
+
A lightweight, token-driven inline callout that draws attention to a line of prose with a colored left rail — no box chrome, no background, no border radius.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## API
|
|
8
|
+
|
|
9
|
+
### Inputs
|
|
10
|
+
|
|
11
|
+
| Input | Type | Default | Description |
|
|
12
|
+
| ----------- | ---------------- | -------- | --------------------------------------------------------------------- |
|
|
13
|
+
| `variant` | `NoteVariant` | `"info"` | Accent tone: `"info"`, `"success"`, `"warning"`, or `"danger"` |
|
|
14
|
+
| `italic` | `boolean` | `false` | Render the note's text in italic style |
|
|
15
|
+
| `className` | `string` | `''` | Additional CSS classes merged onto the host element |
|
|
16
|
+
| `id` | `string \| null` | `null` | Optional ID applied to the host element |
|
|
17
|
+
| `ariaLabel` | `string \| null` | `null` | Accessible label when the note's visual content alone is insufficient |
|
|
18
|
+
|
|
19
|
+
### Outputs
|
|
20
|
+
|
|
21
|
+
None.
|
|
22
|
+
|
|
23
|
+
### Content
|
|
24
|
+
|
|
25
|
+
`fk-note` projects its content:
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<fk-note>Permissions inherit through the hierarchy.</fk-note>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- Left-rail accent in info / success / warning / danger tones
|
|
36
|
+
- No box chrome — sits inline with surrounding prose
|
|
37
|
+
- Fully token-driven accent colors, border width, and padding
|
|
38
|
+
- Works with any inline or block content (text, links, code)
|
|
39
|
+
- Renders correctly without any theme file via two-tier fallbacks
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
```html
|
|
46
|
+
<fk-note>Your first request is ready to send.</fk-note>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```html
|
|
50
|
+
<fk-note variant="warning"> API keys are shown only once. Copy yours before leaving this screen. </fk-note>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Import
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { NoteComponent } from '@frame-kit/ui-ng';
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
@Component({
|
|
63
|
+
selector: 'app-example',
|
|
64
|
+
imports: [NoteComponent],
|
|
65
|
+
templateUrl: './example.component.html',
|
|
66
|
+
})
|
|
67
|
+
export class ExampleComponent {}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Selector
|
|
73
|
+
|
|
74
|
+
```html
|
|
75
|
+
<fk-note></fk-note>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Examples
|
|
81
|
+
|
|
82
|
+
### Tone variants
|
|
83
|
+
|
|
84
|
+
```html
|
|
85
|
+
<fk-note variant="info">Neutral attention marker.</fk-note>
|
|
86
|
+
<fk-note variant="success">Positive confirmation.</fk-note>
|
|
87
|
+
<fk-note variant="warning">Caveat or caution.</fk-note>
|
|
88
|
+
<fk-note variant="danger">Destructive or irreversible action.</fk-note>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### With rich inline content
|
|
92
|
+
|
|
93
|
+
```html
|
|
94
|
+
<fk-note variant="info"> Use the <code>X-API-Key</code> header for server-to-server requests. <a href="/docs/api-reference">Learn more</a>. </fk-note>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Custom accessible label
|
|
98
|
+
|
|
99
|
+
```html
|
|
100
|
+
<fk-note variant="warning" ariaLabel="Deprecation notice"> This endpoint will be removed in v2. </fk-note>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Accessibility
|
|
106
|
+
|
|
107
|
+
- Renders as a plain block container; content inside is read in source order
|
|
108
|
+
- Use `ariaLabel` when the note conveys meaning beyond its visible text (e.g. "Deprecation notice", "Security warning")
|
|
109
|
+
- For a note that announces dynamic updates, wrap it in a parent `role="status"` or `role="alert"` element — `fk-note` itself stays presentation-only
|
|
110
|
+
- Color alone is never the sole signal; pair the variant with clear wording so screen-reader users get the same cue
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Design Tokens
|
|
115
|
+
|
|
116
|
+
```scss
|
|
117
|
+
--fk-note-border-width;
|
|
118
|
+
--fk-note-padding-block;
|
|
119
|
+
--fk-note-padding-inline-start;
|
|
120
|
+
--fk-note-color;
|
|
121
|
+
--fk-note-font-size;
|
|
122
|
+
--fk-note-line-height;
|
|
123
|
+
|
|
124
|
+
--fk-note-info-accent;
|
|
125
|
+
--fk-note-success-accent;
|
|
126
|
+
--fk-note-warning-accent;
|
|
127
|
+
--fk-note-danger-accent;
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Override in your app stylesheet:
|
|
131
|
+
|
|
132
|
+
```scss
|
|
133
|
+
:root {
|
|
134
|
+
--fk-note-border-width: 4px;
|
|
135
|
+
--fk-note-padding-inline-start: 1.25rem;
|
|
136
|
+
--fk-note-info-accent: var(--fk-color-primary-hover);
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Behavior Notes
|
|
143
|
+
|
|
144
|
+
- The left rail uses `border-inline-start` so it automatically flips for RTL languages
|
|
145
|
+
- Vertical rhythm above and below is the caller's responsibility — `fk-note` does not carry its own margin. Use utility classes (`.fk-mt-4`, etc.) or parent `gap` for spacing
|
|
146
|
+
- Accent tokens resolve to `--fk-color-primary / success / warning / danger` by default, so dark mode is picked up from the semantic color layer without per-note overrides
|