@flyos/design-system 3.13.0 → 3.14.0
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/fesm2022/flyos-design-system.mjs +3593 -2441
- package/fesm2022/flyos-design-system.mjs.map +1 -1
- package/package.json +1 -1
- package/types/flyos-design-system.d.ts +1944 -1439
- package/types/flyos-design-system.d.ts.map +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { Type, InjectionToken, Signal, WritableSignal, OnInit, EventEmitter, OnChanges, OnDestroy, SimpleChanges, EnvironmentProviders, PipeTransform, signal, AfterViewInit, ElementRef, AfterViewChecked,
|
|
2
|
+
import { Type, InjectionToken, Signal, WritableSignal, OnInit, EventEmitter, OnChanges, OnDestroy, SimpleChanges, EnvironmentProviders, PipeTransform, signal, AfterViewInit, ElementRef, AfterViewChecked, Provider, ErrorHandler, TemplateRef } from '@angular/core';
|
|
3
3
|
import * as rxjs from 'rxjs';
|
|
4
4
|
import { Observable, MonoTypeOperatorFunction } from 'rxjs';
|
|
5
5
|
import { ControlValueAccessor, Validator, AbstractControl, ValidationErrors } from '@angular/forms';
|
|
@@ -6569,6 +6569,43 @@ interface GanttDependencyCreate {
|
|
|
6569
6569
|
toId: string;
|
|
6570
6570
|
type: GanttDependencyType;
|
|
6571
6571
|
}
|
|
6572
|
+
/**
|
|
6573
|
+
* Payload of {@link FlyGanttComponent.rowReorder} — a label row dragged to a new place in the tree.
|
|
6574
|
+
*
|
|
6575
|
+
* Carries the FULL new sibling order rather than a `before`/`after` hint, because that is the shape
|
|
6576
|
+
* every ordering endpoint actually takes (an ordered, complete id set) and because re-deriving it
|
|
6577
|
+
* consumer-side is where the chart's order and the consumer's start to disagree. `parentId` is the
|
|
6578
|
+
* parent AFTER the move — `null` for a root row — so a drop that also re-homes the row (dragging a
|
|
6579
|
+
* task from one summary group into another) is one event, not two.
|
|
6580
|
+
*
|
|
6581
|
+
* The chart does NOT judge whether a level change is legal: only the consumer knows whether its
|
|
6582
|
+
* two outline levels are the same kind of thing. Reject the move by simply not persisting it; the
|
|
6583
|
+
* rows are re-rendered from the consumer's own input either way, so nothing is left inconsistent.
|
|
6584
|
+
*/
|
|
6585
|
+
interface GanttRowReorder {
|
|
6586
|
+
/** The row that moved. */
|
|
6587
|
+
readonly id: string;
|
|
6588
|
+
/** Its parent after the move; `null` = a root row. */
|
|
6589
|
+
readonly parentId: string | null;
|
|
6590
|
+
/** Zero-based slot among `parentId`'s children after the move. */
|
|
6591
|
+
readonly index: number;
|
|
6592
|
+
/** Every child of `parentId` after the move, in their new order (includes {@link id}). */
|
|
6593
|
+
readonly siblingIds: readonly string[];
|
|
6594
|
+
}
|
|
6595
|
+
/**
|
|
6596
|
+
* Payload of {@link FlyGanttComponent.rowIndentChange} — the outline-level nudge behind an
|
|
6597
|
+
* indent / outdent action.
|
|
6598
|
+
*
|
|
6599
|
+
* `delta` is `+1` (indent — become a child of the row above) or `-1` (outdent — become a sibling of
|
|
6600
|
+
* the current parent). `parentId` is the resulting parent, resolved by the chart from the row's
|
|
6601
|
+
* neighbours so every consumer does not re-implement "which row would adopt it": `null` means the
|
|
6602
|
+
* row lands at the root.
|
|
6603
|
+
*/
|
|
6604
|
+
interface GanttRowIndentChange {
|
|
6605
|
+
readonly id: string;
|
|
6606
|
+
readonly delta: 1 | -1;
|
|
6607
|
+
readonly parentId: string | null;
|
|
6608
|
+
}
|
|
6572
6609
|
/** Payload of {@link FlyGanttComponent.dependencyDelete} — the edge the user removed. */
|
|
6573
6610
|
interface GanttDependencyDelete {
|
|
6574
6611
|
fromId: string;
|
|
@@ -6605,6 +6642,10 @@ interface GanttFlatRow {
|
|
|
6605
6642
|
hasChildren: boolean;
|
|
6606
6643
|
collapsed: boolean;
|
|
6607
6644
|
}
|
|
6645
|
+
interface ResolvedDates {
|
|
6646
|
+
start: Date | null;
|
|
6647
|
+
end: Date | null;
|
|
6648
|
+
}
|
|
6608
6649
|
/** Render shape a row resolves to — decides which geometry fields on its VM are meaningful. */
|
|
6609
6650
|
type RowShape = 'bar' | 'milestone' | 'group' | 'empty';
|
|
6610
6651
|
/** Which end of a bar a link gesture grabbed / was dropped on. */
|
|
@@ -6718,6 +6759,90 @@ interface GanttRowVm {
|
|
|
6718
6759
|
/** Baseline overlay geometry, or `null` when the row has none (or baselines are hidden). */
|
|
6719
6760
|
baseline: GanttBaselineVm | null;
|
|
6720
6761
|
}
|
|
6762
|
+
/**
|
|
6763
|
+
* What the geometry needs from its host, as signals rather than a component reference — the same
|
|
6764
|
+
* one-way shape {@link GanttLabelPane} and {@link GanttLinkGestures} take.
|
|
6765
|
+
*/
|
|
6766
|
+
interface GanttRowGeometryDeps {
|
|
6767
|
+
readonly rowHeight: Signal<number>;
|
|
6768
|
+
readonly rtl: Signal<boolean>;
|
|
6769
|
+
readonly domain: Signal<GanttDomain>;
|
|
6770
|
+
readonly pxPerDay: Signal<number>;
|
|
6771
|
+
readonly innerWidth: Signal<number>;
|
|
6772
|
+
readonly showBaselines: Signal<boolean>;
|
|
6773
|
+
readonly readonly: Signal<boolean>;
|
|
6774
|
+
/** Every row's effective `{start,end}` (`resolveRowDates`), including derived group spans. */
|
|
6775
|
+
readonly resolvedDates: Signal<ReadonlyMap<string, ResolvedDates>>;
|
|
6776
|
+
/** The in-flight bar drag, folded into the geometry so the bar follows the pointer. */
|
|
6777
|
+
readonly dragPreview: Signal<{
|
|
6778
|
+
id: string;
|
|
6779
|
+
start: Date;
|
|
6780
|
+
end: Date;
|
|
6781
|
+
} | null>;
|
|
6782
|
+
/** The row-band tint, already faded to its low alpha (or `null`). */
|
|
6783
|
+
readonly tintFor: (row: GanttRow) => string | null;
|
|
6784
|
+
/** The localized accessible label for a row. */
|
|
6785
|
+
readonly ariaFor: (row: GanttRow, start: Date | null, end: Date | null, shape: RowShape) => string;
|
|
6786
|
+
}
|
|
6787
|
+
/**
|
|
6788
|
+
* Render-space geometry for a Gantt row: the view-model one flattened row resolves to, and every
|
|
6789
|
+
* shape derived from it.
|
|
6790
|
+
*
|
|
6791
|
+
* ## Why this is not in the component
|
|
6792
|
+
* `fly-gantt` composes its gestures out of one-concern classes already ({@link GanttLabelPane},
|
|
6793
|
+
* {@link GanttLinkGestures}, {@link GanttViewport}, {@link GanttPan}) and this is the matching
|
|
6794
|
+
* carve on the RENDER side: everything here is "given a row and the current scale, where is it and
|
|
6795
|
+
* what shape is it", with no knowledge of selection, collapse, windowing, events or i18n beyond the
|
|
6796
|
+
* one label callback. Keeping it here means the component's remaining bulk is state and wiring, and
|
|
6797
|
+
* the geometry — the part that is actually hard to read — sits beside the scale math it calls.
|
|
6798
|
+
*
|
|
6799
|
+
* ## RTL
|
|
6800
|
+
* Nothing here branches on direction except through `mapX`/`projectBar` and the two `sign` terms
|
|
6801
|
+
* below, because the whole coordinate space is pre-mirrored (see `gantt-scale.ts`). The
|
|
6802
|
+
* consequence worth remembering: under RTL a row's `startX` is GREATER than its `endX`.
|
|
6803
|
+
*/
|
|
6804
|
+
declare class GanttRowGeometry {
|
|
6805
|
+
private readonly deps;
|
|
6806
|
+
constructor(deps: GanttRowGeometryDeps);
|
|
6807
|
+
/** Bar height for the current row height — the band minus its vertical padding. */
|
|
6808
|
+
readonly barHeight: Signal<number>;
|
|
6809
|
+
/** Full geometry for one row — used for rendered rows AND for link endpoints outside the window. */
|
|
6810
|
+
forFlat(flat: GanttFlatRow, index: number): GanttRowVm;
|
|
6811
|
+
barTop(vm: GanttRowVm): number;
|
|
6812
|
+
/** Baseline underbar's top edge — a thin strip directly beneath the main bar. */
|
|
6813
|
+
baselineBarTop(vm: GanttRowVm): number;
|
|
6814
|
+
private milestoneR;
|
|
6815
|
+
/** Diamond polygon points for a milestone marker. */
|
|
6816
|
+
diamondPoints(vm: GanttRowVm): string;
|
|
6817
|
+
/** Hollow outline diamond for a milestone row's baseline date (its own x, same row's y). */
|
|
6818
|
+
baselineDiamondPoints(vm: GanttRowVm): string;
|
|
6819
|
+
/**
|
|
6820
|
+
* Link connector x for a milestone. A diamond has no width, so the connector is nudged clear
|
|
6821
|
+
* of the marker in the forward-in-time direction (which flips under RTL).
|
|
6822
|
+
*/
|
|
6823
|
+
milestoneConnectorX(vm: GanttRowVm): number;
|
|
6824
|
+
/**
|
|
6825
|
+
* Connector x for one END of a bar, pushed into the gutter BESIDE the bar rather than sitting on
|
|
6826
|
+
* its edge (see {@link CONNECTOR_GAP}). Forward-in-time is `+x` LTR and `-x` RTL, so the start
|
|
6827
|
+
* connector always lands before the bar and the finish connector after it, in reading order.
|
|
6828
|
+
*/
|
|
6829
|
+
connectorX(vm: GanttRowVm, anchor: 'start' | 'finish'): number;
|
|
6830
|
+
/** Summary-bracket path (thin bar + down-turned end caps) for a group row. */
|
|
6831
|
+
groupPath(vm: GanttRowVm): string;
|
|
6832
|
+
/** Inline-start label indent for a tree depth. */
|
|
6833
|
+
indentFor(depth: number): number;
|
|
6834
|
+
}
|
|
6835
|
+
|
|
6836
|
+
/** Which part of a bar the press grabbed. */
|
|
6837
|
+
type GanttBarDragMode = 'move' | 'resize-start' | 'resize-end';
|
|
6838
|
+
/** The follow-the-cursor date readout shown while a drag runs. */
|
|
6839
|
+
interface GanttDragTooltip {
|
|
6840
|
+
readonly x: number;
|
|
6841
|
+
readonly y: number;
|
|
6842
|
+
readonly text: string;
|
|
6843
|
+
}
|
|
6844
|
+
|
|
6845
|
+
/** One dependency arrow, routed and ready for the template. */
|
|
6721
6846
|
interface LinkVm {
|
|
6722
6847
|
key: string;
|
|
6723
6848
|
fromId: string;
|
|
@@ -6762,9 +6887,21 @@ interface LinkVm {
|
|
|
6762
6887
|
declare class FlyGanttComponent {
|
|
6763
6888
|
readonly i18n: I18nService;
|
|
6764
6889
|
private readonly destroyRef;
|
|
6890
|
+
/**
|
|
6891
|
+
* App-level presentation defaults, when the consuming app provided any. Optional by
|
|
6892
|
+
* construction: a chart with no provider behaves exactly as it did before the token existed.
|
|
6893
|
+
*/
|
|
6894
|
+
private readonly appDefaults;
|
|
6765
6895
|
readonly rows: _angular_core.InputSignal<readonly GanttRow[]>;
|
|
6766
6896
|
readonly dependencies: _angular_core.InputSignal<readonly GanttDependency[]>;
|
|
6767
|
-
|
|
6897
|
+
/**
|
|
6898
|
+
* Time-grid resolution. `null` defers to {@link FlyGanttDefaults.zoom}, then to `'week'`.
|
|
6899
|
+
*
|
|
6900
|
+
* Widened from `GanttZoom` to `GanttZoom | null` so the same three-step precedence
|
|
6901
|
+
* (input → app default → built-in) applies to every presentation input. Passing a concrete zoom
|
|
6902
|
+
* is unchanged.
|
|
6903
|
+
*/
|
|
6904
|
+
readonly zoom: _angular_core.InputSignal<GanttZoom | null>;
|
|
6768
6905
|
/** Draw the vertical "today" marker when today falls inside the domain. */
|
|
6769
6906
|
readonly showToday: _angular_core.InputSignal<boolean>;
|
|
6770
6907
|
/** Globally disable drag/resize/link (individual rows can also be `readonly`). */
|
|
@@ -6774,11 +6911,11 @@ declare class FlyGanttComponent {
|
|
|
6774
6911
|
* divider from there; once they have, this input only re-seeds the pane if
|
|
6775
6912
|
* {@link resetLabelWidth} is called (double-clicking the divider does exactly that).
|
|
6776
6913
|
*/
|
|
6777
|
-
readonly labelWidth: _angular_core.InputSignal<number>;
|
|
6914
|
+
readonly labelWidth: _angular_core.InputSignal<number | null>;
|
|
6778
6915
|
/** Let the user drag the divider between the label pane and the time grid. */
|
|
6779
6916
|
readonly resizableLabels: _angular_core.InputSignal<boolean>;
|
|
6780
|
-
/** Row band height in px. */
|
|
6781
|
-
readonly rowHeight: _angular_core.InputSignal<number>;
|
|
6917
|
+
/** Row band height in px. `null` defers to {@link FlyGanttDefaults.rowHeight}, then to `34`. */
|
|
6918
|
+
readonly rowHeight: _angular_core.InputSignal<number | null>;
|
|
6782
6919
|
/** Hard cap on the flattened row list; beyond it the list is truncated (see class doc).
|
|
6783
6920
|
* `0` (the default) is uncapped — windowing (below) is what keeps an uncapped chart cheap. */
|
|
6784
6921
|
readonly maxRows: _angular_core.InputSignal<number>;
|
|
@@ -6793,6 +6930,31 @@ declare class FlyGanttComponent {
|
|
|
6793
6930
|
readonly virtualized: _angular_core.InputSignal<boolean>;
|
|
6794
6931
|
/** Render the baseline underbar/diamond for rows carrying `baselineStart`/`baselineEnd`. */
|
|
6795
6932
|
readonly showBaselines: _angular_core.InputSignal<boolean>;
|
|
6933
|
+
/**
|
|
6934
|
+
* Render a search field in the pinned corner that filters the label tree.
|
|
6935
|
+
*
|
|
6936
|
+
* Filtering preserves tree CONTEXT rather than flattening to a hit list — see
|
|
6937
|
+
* `gantt-search.ts` for why a plain `rows.filter()` silently re-parents matching children and
|
|
6938
|
+
* de-groups matching parents. A live query also expands every group (a match hidden inside a
|
|
6939
|
+
* collapsed summary is indistinguishable from no match at all) and suspends drag-reorder, since
|
|
6940
|
+
* a filtered sibling list is not a complete one to reorder against.
|
|
6941
|
+
*
|
|
6942
|
+
* `null` defers to {@link FlyGanttDefaults.searchable}, then to `false`.
|
|
6943
|
+
*/
|
|
6944
|
+
readonly searchable: _angular_core.InputSignal<boolean | null>;
|
|
6945
|
+
/**
|
|
6946
|
+
* Let the user drag label rows to reorder / re-home them, emitting {@link rowReorder}.
|
|
6947
|
+
*
|
|
6948
|
+
* `null` defers to {@link FlyGanttDefaults.reorderable}, then to `false` — the chart never
|
|
6949
|
+
* offers a gesture whose result nobody is persisting.
|
|
6950
|
+
*/
|
|
6951
|
+
readonly reorderable: _angular_core.InputSignal<boolean | null>;
|
|
6952
|
+
/**
|
|
6953
|
+
* The label-tree filter text. Two-way bindable, so a consumer can seed it from a deep link or
|
|
6954
|
+
* clear it on navigation; the built-in field writes it as the user types (debounced by
|
|
6955
|
+
* `fly-search-input`). Ignored unless {@link searchable}.
|
|
6956
|
+
*/
|
|
6957
|
+
readonly searchQuery: _angular_core.ModelSignal<string>;
|
|
6796
6958
|
/** Fires on a committed bar move / resize with the new ISO `start`/`end`. */
|
|
6797
6959
|
readonly rowDatesChange: _angular_core.OutputEmitterRef<GanttRowDatesChange>;
|
|
6798
6960
|
/**
|
|
@@ -6812,32 +6974,72 @@ declare class FlyGanttComponent {
|
|
|
6812
6974
|
readonly rowExpand: _angular_core.OutputEmitterRef<string>;
|
|
6813
6975
|
/** The component coarsened the requested zoom to stay under `maxCanvasPx`. */
|
|
6814
6976
|
readonly effectiveZoomChange: _angular_core.OutputEmitterRef<GanttZoom>;
|
|
6977
|
+
/**
|
|
6978
|
+
* A label row was dragged to a new place. Carries the complete new sibling order, so a consumer
|
|
6979
|
+
* persists it with one ordered-set write. See {@link GanttRowReorder}.
|
|
6980
|
+
*/
|
|
6981
|
+
readonly rowReorder: _angular_core.OutputEmitterRef<GanttRowReorder>;
|
|
6982
|
+
/**
|
|
6983
|
+
* A row's outline level was nudged by {@link indentRow} / {@link outdentRow}, with the resulting
|
|
6984
|
+
* parent already resolved from the row's neighbours. The chart does not re-render on its own —
|
|
6985
|
+
* like every other gesture here, the consumer persists and feeds new `rows` back in.
|
|
6986
|
+
*/
|
|
6987
|
+
readonly rowIndentChange: _angular_core.OutputEmitterRef<GanttRowIndentChange>;
|
|
6815
6988
|
private readonly _uid;
|
|
6816
6989
|
readonly markerId: string;
|
|
6817
6990
|
readonly HEADER_H: number;
|
|
6818
6991
|
readonly HEADER_UPPER_H = 22;
|
|
6819
6992
|
readonly HEADER_LOWER_H = 22;
|
|
6820
6993
|
readonly HANDLE_W = 8;
|
|
6994
|
+
/** Connector radius — small, and parked outside the bar, so it never steals the resize
|
|
6995
|
+
* handle's press (`gantt-row-vm.ts`'s CONNECTOR_R note). */
|
|
6996
|
+
readonly CONNECTOR_R = 3;
|
|
6821
6997
|
readonly MIN_LABEL_W = 140;
|
|
6822
6998
|
readonly MAX_LABEL_W = 720;
|
|
6823
6999
|
readonly BASELINE_BAR_H: number;
|
|
6824
7000
|
readonly selectedId: _angular_core.WritableSignal<string | null>;
|
|
6825
7001
|
/** Uncontrolled collapse state — the source of truth whenever the `collapsedIds` input is `null`. */
|
|
6826
7002
|
private readonly _uncontrolledCollapsed;
|
|
6827
|
-
/** Live drag preview `{id,start,end}` folded into geometry while a gesture runs
|
|
7003
|
+
/** Live drag preview `{id,start,end}` folded into geometry while a bar gesture runs, and the
|
|
7004
|
+
* cursor-following date readout beside it — both owned by {@link GanttBarDrag}, re-exposed here
|
|
7005
|
+
* because the row geometry reads the first and the template renders the second. */
|
|
6828
7006
|
private readonly _dragPreview;
|
|
6829
|
-
readonly dragTooltip: _angular_core.
|
|
6830
|
-
x: number;
|
|
6831
|
-
y: number;
|
|
6832
|
-
text: string;
|
|
6833
|
-
} | null>;
|
|
7007
|
+
readonly dragTooltip: _angular_core.Signal<GanttDragTooltip | null>;
|
|
6834
7008
|
private readonly bodyRef;
|
|
6835
7009
|
private readonly scrollElRef;
|
|
6836
7010
|
private readonly canvasElRef;
|
|
6837
7011
|
private readonly labelsElRef;
|
|
6838
7012
|
readonly rtl: _angular_core.Signal<boolean>;
|
|
7013
|
+
/** The zoom the consumer asked for, before `maxCanvasPx` coarsening ({@link effectiveZoom}). */
|
|
7014
|
+
readonly requestedZoom: _angular_core.Signal<GanttZoom>;
|
|
7015
|
+
/** Row band height actually rendered. */
|
|
7016
|
+
readonly effectiveRowHeight: _angular_core.Signal<number>;
|
|
7017
|
+
/** The width the label pane falls back to until the user drags the divider. */
|
|
7018
|
+
private readonly _labelWidthInput;
|
|
7019
|
+
/** Whether the corner search field is rendered at all. */
|
|
7020
|
+
readonly searchEnabled: _angular_core.Signal<boolean>;
|
|
7021
|
+
/** The live filter text, or `''` when searching is off — the one signal every filter path reads. */
|
|
7022
|
+
readonly activeQuery: _angular_core.Signal<string>;
|
|
7023
|
+
/**
|
|
7024
|
+
* Whether a label row can be dragged right now.
|
|
7025
|
+
*
|
|
7026
|
+
* Suspended while a search is live, deliberately: {@link rowReorder} emits the COMPLETE sibling
|
|
7027
|
+
* order, and a filtered tree only holds the siblings that matched. Persisting that list would
|
|
7028
|
+
* quietly drop every row the filter is hiding — the sort of data loss whose cause is invisible
|
|
7029
|
+
* afterwards. A read-only chart never reorders either.
|
|
7030
|
+
*/
|
|
7031
|
+
readonly reorderEnabled: _angular_core.Signal<boolean>;
|
|
6839
7032
|
/** Effective collapse set: the controlled input when the consumer supplied one, else internal state. */
|
|
6840
7033
|
private readonly _collapsed;
|
|
7034
|
+
/**
|
|
7035
|
+
* The consumer's rows narrowed by the live search filter (identity-stable when not searching).
|
|
7036
|
+
*
|
|
7037
|
+
* NOTE the domain and the resolved dates below deliberately stay on the UNFILTERED `rows()`: a
|
|
7038
|
+
* timeline whose axis and whose summary spans jumped on every keystroke would make the filter
|
|
7039
|
+
* feel like it was editing the plan. Filtering decides which rows are LISTED, not what the dates
|
|
7040
|
+
* are.
|
|
7041
|
+
*/
|
|
7042
|
+
readonly filteredRows: _angular_core.Signal<readonly GanttRow[]>;
|
|
6841
7043
|
/** Full visible list after tree flatten/collapse (no `maxRows` cap applied yet). */
|
|
6842
7044
|
private readonly _flat;
|
|
6843
7045
|
/** `_flat`, capped at `maxRows` when it is positive — unchanged from the pre-A9 contract. */
|
|
@@ -6882,26 +7084,15 @@ declare class FlyGanttComponent {
|
|
|
6882
7084
|
* window with one endpoint outside it — the memo §4.3 rule-2 fix for the pre-A9 "both
|
|
6883
7085
|
* endpoints rendered" predicate, which would erase exactly those crossing arrows. */
|
|
6884
7086
|
readonly linkVms: _angular_core.Signal<LinkVm[]>;
|
|
6885
|
-
/** Full geometry for one row — shared by `rowVms` and `linkVms` (endpoints outside the window). */
|
|
6886
|
-
private _vmForFlat;
|
|
6887
|
-
readonly barHeight: _angular_core.Signal<number>;
|
|
6888
|
-
barTop(vm: GanttRowVm): number;
|
|
6889
|
-
/** Baseline underbar's top edge — a thin strip directly beneath the main bar. */
|
|
6890
|
-
baselineBarTop(vm: GanttRowVm): number;
|
|
6891
|
-
private milestoneR;
|
|
6892
|
-
/** Diamond polygon points for a milestone marker. */
|
|
6893
|
-
diamondPoints(vm: GanttRowVm): string;
|
|
6894
|
-
/** Hollow outline diamond for a milestone row's baseline date (its own x, same row's y). */
|
|
6895
|
-
baselineDiamondPoints(vm: GanttRowVm): string;
|
|
6896
7087
|
/**
|
|
6897
|
-
*
|
|
6898
|
-
*
|
|
7088
|
+
* Render-space geometry, in {@link GanttRowGeometry} — the row view-model plus every shape
|
|
7089
|
+
* derived from it. Composed for the same reason as the gestures below it: given a row and the
|
|
7090
|
+
* current scale it answers "where is this and what shape is it", and knows nothing about
|
|
7091
|
+
* selection, collapse, windowing or events. `geo` is public because the TEMPLATE calls it.
|
|
6899
7092
|
*/
|
|
6900
|
-
|
|
6901
|
-
/**
|
|
6902
|
-
|
|
6903
|
-
/** Inline-start label indent for a tree depth. */
|
|
6904
|
-
indentFor(depth: number): number;
|
|
7093
|
+
readonly geo: GanttRowGeometry;
|
|
7094
|
+
/** Bar height for the current row height — bound directly by the template. */
|
|
7095
|
+
readonly barHeight: _angular_core.Signal<number>;
|
|
6905
7096
|
/**
|
|
6906
7097
|
* The divider's own state machine, in {@link GanttLabelPane}. It is composed rather than
|
|
6907
7098
|
* inlined because it is the one region of this component with no coupling to the chart: give it
|
|
@@ -6936,12 +7127,29 @@ declare class FlyGanttComponent {
|
|
|
6936
7127
|
onLabelRowKeydown(ev: Event, id: string): void;
|
|
6937
7128
|
onRowClick(id: string): void;
|
|
6938
7129
|
onRowDblClick(id: string): void;
|
|
7130
|
+
/**
|
|
7131
|
+
* Press on a row's own SHAPE — the group bracket today; bars and milestones reach the same place
|
|
7132
|
+
* through {@link onBarPointerDown}, which additionally starts a drag.
|
|
7133
|
+
*
|
|
7134
|
+
* `stopPropagation` is what keeps this apart from the background pan: the full-width lane rect
|
|
7135
|
+
* behind every row is deliberately NOT a selection target any more (clicking the empty part of a
|
|
7136
|
+
* row is a pan, not a pick), so only a press that lands on a painted shape may select.
|
|
7137
|
+
*/
|
|
7138
|
+
onShapePointerDown(ev: PointerEvent, id: string): void;
|
|
7139
|
+
/** Settled (debounced) text from the corner search field. */
|
|
7140
|
+
onSearchQueryChange(query: string): void;
|
|
6939
7141
|
onLinkClick(ev: Event, vm: LinkVm): void;
|
|
6940
7142
|
deleteLink(ev: Event, vm: LinkVm): void;
|
|
6941
7143
|
onGridKeydown(ev: KeyboardEvent): void;
|
|
6942
7144
|
/** Shift both dates of the selected bar by `deltaDays` and emit (respecting read-only). */
|
|
6943
7145
|
private _nudgeSelected;
|
|
6944
|
-
|
|
7146
|
+
/**
|
|
7147
|
+
* Moving and resizing a bar, in {@link GanttBarDrag} — the last of the three pointer gestures
|
|
7148
|
+
* to be composed rather than inlined, for the same reason as the other two: it needs a scale, a
|
|
7149
|
+
* direction and somewhere to report a committed pair of dates, and nothing else about the chart.
|
|
7150
|
+
*/
|
|
7151
|
+
private readonly _barDrag;
|
|
7152
|
+
onBarPointerDown(ev: PointerEvent, vm: GanttRowVm, mode: GanttBarDragMode): void;
|
|
6945
7153
|
/**
|
|
6946
7154
|
* The dependency-drawing gesture, in {@link GanttLinkGestures}. Composed rather than inlined
|
|
6947
7155
|
* because it is a self-contained second gesture whose interesting part is a RULE — the end you
|
|
@@ -6957,1582 +7165,1829 @@ declare class FlyGanttComponent {
|
|
|
6957
7165
|
readonly linkGesturePath: _angular_core.Signal<string | null>;
|
|
6958
7166
|
onLinkPointerDown(ev: PointerEvent, vm: GanttRowVm, anchor: GanttLinkAnchor): void;
|
|
6959
7167
|
/**
|
|
6960
|
-
*
|
|
6961
|
-
*
|
|
6962
|
-
*
|
|
6963
|
-
|
|
6964
|
-
|
|
7168
|
+
* Ctrl+wheel scrolls horizontally and a press-drag on empty chart space pans, both in
|
|
7169
|
+
* {@link GanttPan}. Composed for the same reason as the other two gestures: it needs a scrolling
|
|
7170
|
+
* element and nothing else about the chart, and its two subtleties (a non-passive wheel listener
|
|
7171
|
+
* is the only kind that can out-vote browser zoom; a pan must swallow its own trailing click)
|
|
7172
|
+
* read better beside each other than scattered through this class.
|
|
7173
|
+
*/
|
|
7174
|
+
private readonly _pan;
|
|
7175
|
+
/** True mid drag-pan — drives the host's grabbing cursor. */
|
|
7176
|
+
readonly panning: _angular_core.WritableSignal<boolean>;
|
|
7177
|
+
/**
|
|
7178
|
+
* Press on the chart background. Every interactive shape stops propagation on its own
|
|
7179
|
+
* `pointerdown`, so only genuinely empty space (the lane rects, the weekend bands, the
|
|
7180
|
+
* gridlines, the canvas itself) ever reaches this.
|
|
7181
|
+
*/
|
|
7182
|
+
onPanPointerDown(ev: PointerEvent): void;
|
|
7183
|
+
/**
|
|
7184
|
+
* The flattened rows in the narrow shape the reorder resolver needs.
|
|
7185
|
+
*
|
|
7186
|
+
* `parentId` is recomputed from the rendered DEPTHS rather than copied off `GanttRow.parentId`,
|
|
7187
|
+
* and the difference is load-bearing: `flattenRows` treats an unknown, self- or cyclic parent as
|
|
7188
|
+
* a root, so a row can render at depth 0 while still carrying a `parentId` string. Trusting the
|
|
7189
|
+
* field would have the resolver build a sibling list for a parent that is not on screen.
|
|
7190
|
+
*/
|
|
7191
|
+
private readonly _reorderRows;
|
|
7192
|
+
private readonly _reorder;
|
|
7193
|
+
/** Id of the row being dragged, or `null`. */
|
|
7194
|
+
readonly reorderDraggingId: _angular_core.WritableSignal<string | null>;
|
|
7195
|
+
/** Absolute row-space `y` of the drop indicator, or `null` when no drag is live. */
|
|
7196
|
+
readonly reorderIndicatorTop: _angular_core.Signal<number | null>;
|
|
7197
|
+
onLabelRowPointerDown(ev: PointerEvent, id: string): void;
|
|
7198
|
+
/** Whether `id` can become a child of the row above it (see `canIndentGanttRow`). */
|
|
7199
|
+
canIndentRow(id: string): boolean;
|
|
7200
|
+
/** Whether `id` can be lifted out of its parent — i.e. whether it has one. */
|
|
7201
|
+
canOutdentRow(id: string): boolean;
|
|
7202
|
+
/** Reactive twins for the currently selected row — what a magic-bar publisher binds to. */
|
|
7203
|
+
readonly canIndentSelected: _angular_core.Signal<boolean>;
|
|
7204
|
+
readonly canOutdentSelected: _angular_core.Signal<boolean>;
|
|
7205
|
+
/** Make `id` a child of the row directly above it, if it has an eligible sibling there. */
|
|
7206
|
+
indentRow(id: string): void;
|
|
7207
|
+
/** Lift `id` out to its grandparent's level (`null` = the root). */
|
|
7208
|
+
outdentRow(id: string): void;
|
|
6965
7209
|
private _mapTicks;
|
|
7210
|
+
/** Bridges the pure a11y label builder to this component's localizer + Date-typed geometry. */
|
|
6966
7211
|
private _ariaFor;
|
|
6967
7212
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlyGanttComponent, never>;
|
|
6968
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyGanttComponent, "fly-gantt", never, { "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "dependencies": { "alias": "dependencies"; "required": false; "isSignal": true; }; "zoom": { "alias": "zoom"; "required": false; "isSignal": true; }; "showToday": { "alias": "showToday"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "labelWidth": { "alias": "labelWidth"; "required": false; "isSignal": true; }; "resizableLabels": { "alias": "resizableLabels"; "required": false; "isSignal": true; }; "rowHeight": { "alias": "rowHeight"; "required": false; "isSignal": true; }; "maxRows": { "alias": "maxRows"; "required": false; "isSignal": true; }; "collapsedIds": { "alias": "collapsedIds"; "required": false; "isSignal": true; }; "overscanRows": { "alias": "overscanRows"; "required": false; "isSignal": true; }; "maxCanvasPx": { "alias": "maxCanvasPx"; "required": false; "isSignal": true; }; "virtualized": { "alias": "virtualized"; "required": false; "isSignal": true; }; "showBaselines": { "alias": "showBaselines"; "required": false; "isSignal": true; }; }, { "rowDatesChange": "rowDatesChange"; "dependencyCreate": "dependencyCreate"; "dependencyDelete": "dependencyDelete"; "rowClick": "rowClick"; "rowDblClick": "rowDblClick"; "labelWidthChange": "labelWidthChange"; "collapsedIdsChange": "collapsedIdsChange"; "rowExpand": "rowExpand"; "effectiveZoomChange": "effectiveZoomChange"; }, never, never, true, never>;
|
|
7213
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyGanttComponent, "fly-gantt", never, { "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "dependencies": { "alias": "dependencies"; "required": false; "isSignal": true; }; "zoom": { "alias": "zoom"; "required": false; "isSignal": true; }; "showToday": { "alias": "showToday"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "labelWidth": { "alias": "labelWidth"; "required": false; "isSignal": true; }; "resizableLabels": { "alias": "resizableLabels"; "required": false; "isSignal": true; }; "rowHeight": { "alias": "rowHeight"; "required": false; "isSignal": true; }; "maxRows": { "alias": "maxRows"; "required": false; "isSignal": true; }; "collapsedIds": { "alias": "collapsedIds"; "required": false; "isSignal": true; }; "overscanRows": { "alias": "overscanRows"; "required": false; "isSignal": true; }; "maxCanvasPx": { "alias": "maxCanvasPx"; "required": false; "isSignal": true; }; "virtualized": { "alias": "virtualized"; "required": false; "isSignal": true; }; "showBaselines": { "alias": "showBaselines"; "required": false; "isSignal": true; }; "searchable": { "alias": "searchable"; "required": false; "isSignal": true; }; "reorderable": { "alias": "reorderable"; "required": false; "isSignal": true; }; "searchQuery": { "alias": "searchQuery"; "required": false; "isSignal": true; }; }, { "searchQuery": "searchQueryChange"; "rowDatesChange": "rowDatesChange"; "dependencyCreate": "dependencyCreate"; "dependencyDelete": "dependencyDelete"; "rowClick": "rowClick"; "rowDblClick": "rowDblClick"; "labelWidthChange": "labelWidthChange"; "collapsedIdsChange": "collapsedIdsChange"; "rowExpand": "rowExpand"; "effectiveZoomChange": "effectiveZoomChange"; "rowReorder": "rowReorder"; "rowIndentChange": "rowIndentChange"; }, never, never, true, never>;
|
|
6969
7214
|
}
|
|
6970
7215
|
|
|
6971
|
-
/** The 14 rendered field kinds. Drives the control the renderer picks. */
|
|
6972
|
-
type FlyFormQuestionType = 'Text' | 'MultilineText' | 'Number' | 'Email' | 'Date' | 'DateTime' | 'Boolean' | 'SingleSelect' | 'MultipleSelect' | 'RadioButton' | 'Country' | 'File' | 'MultiFile' | 'Image';
|
|
6973
|
-
/**
|
|
6974
|
-
* A selectable option on a choice field (SingleSelect / MultipleSelect /
|
|
6975
|
-
* RadioButton). `linkedQuestionIds` drive conditional branching: selecting this
|
|
6976
|
-
* option reveals those (branch-target) fields. `score` is author-only and is only
|
|
6977
|
-
* surfaced to the viewer when the host opts in via `[showScore]` (a scorecard);
|
|
6978
|
-
* a respondent-facing form leaves `showScore` false and never renders it.
|
|
6979
|
-
*/
|
|
6980
|
-
interface FlyFormOption {
|
|
6981
|
-
id: string;
|
|
6982
|
-
label: string;
|
|
6983
|
-
score?: number;
|
|
6984
|
-
linkedQuestionIds?: string[];
|
|
6985
|
-
}
|
|
6986
|
-
/** Per-type constraints/affordances an author can attach to a field. */
|
|
6987
|
-
interface FlyFormFieldOptions {
|
|
6988
|
-
minLength?: number;
|
|
6989
|
-
maxLength?: number;
|
|
6990
|
-
numericMin?: number;
|
|
6991
|
-
numericMax?: number;
|
|
6992
|
-
rows?: number;
|
|
6993
|
-
maxFileSizeMb?: number;
|
|
6994
|
-
maxFileCount?: number;
|
|
6995
|
-
allowedExtensions?: string[];
|
|
6996
|
-
hasSearch?: boolean;
|
|
6997
|
-
}
|
|
6998
7216
|
/**
|
|
6999
|
-
*
|
|
7000
|
-
*
|
|
7001
|
-
*
|
|
7217
|
+
* App-level defaults for every {@link FlyGanttComponent} under a given injector.
|
|
7218
|
+
*
|
|
7219
|
+
* ## Why a token and not "just use the input"
|
|
7220
|
+
* Every field here is already a per-instance `input()`, and for a one-off chart that is the right
|
|
7221
|
+
* knob. But a planning app draws the SAME chart on four or five screens (a project plan, a
|
|
7222
|
+
* schedule, a portfolio roadmap, a programme rollup), and the presentation decisions — how wide the
|
|
7223
|
+
* label pane starts, how tall a row band is, whether the label pane is searchable — are properties
|
|
7224
|
+
* of the APP, not of any one screen. Repeating them at every call site is how the fifth screen ends
|
|
7225
|
+
* up with a 240px pane while the other four use 360, with no single place that says which is right.
|
|
7226
|
+
*
|
|
7227
|
+
* So: provide once at the app (or a feature-area) injector, override per instance where a screen
|
|
7228
|
+
* genuinely differs. An explicit input ALWAYS wins over the token, and the token over the built-in
|
|
7229
|
+
* default — the plain three-step precedence, stated once in `FlyGanttComponent`'s resolvers.
|
|
7230
|
+
*
|
|
7231
|
+
* ```ts
|
|
7232
|
+
* // app.config.ts
|
|
7233
|
+
* providers: [provideFlyGanttDefaults({ labelWidth: 360, searchable: true })]
|
|
7234
|
+
* ```
|
|
7235
|
+
*
|
|
7236
|
+
* Every field is optional: a partial object overrides only what it names, so an app can move the
|
|
7237
|
+
* label width without also inheriting an opinion about row height.
|
|
7002
7238
|
*/
|
|
7003
|
-
interface
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
/**
|
|
7016
|
-
|
|
7017
|
-
/** Additive: labels the weighted-criteria group a scored field belongs to. Ignored by surveys. */
|
|
7018
|
-
criteriaGroup?: string;
|
|
7019
|
-
}
|
|
7020
|
-
/** A full form definition — the top-level `[definition]` binding. */
|
|
7021
|
-
interface FlyFormDefinition {
|
|
7022
|
-
title: string;
|
|
7023
|
-
description?: string;
|
|
7024
|
-
declaration?: string;
|
|
7025
|
-
questions: FlyFormQuestion[];
|
|
7239
|
+
interface FlyGanttDefaults {
|
|
7240
|
+
/**
|
|
7241
|
+
* Initial inline-start label-pane width in px, before the user drags the divider. Clamped into
|
|
7242
|
+
* `[GANTT_LABEL_W_MIN, GANTT_LABEL_W_MAX]` like every other width source.
|
|
7243
|
+
*/
|
|
7244
|
+
readonly labelWidth?: number;
|
|
7245
|
+
/** Row band height in px. */
|
|
7246
|
+
readonly rowHeight?: number;
|
|
7247
|
+
/** Time-grid resolution a chart opens at. */
|
|
7248
|
+
readonly zoom?: GanttZoom;
|
|
7249
|
+
/** Render the label-pane search field (see `FlyGanttComponent.searchable`). */
|
|
7250
|
+
readonly searchable?: boolean;
|
|
7251
|
+
/** Allow dragging label rows to reorder them (see `FlyGanttComponent.reorderable`). */
|
|
7252
|
+
readonly reorderable?: boolean;
|
|
7026
7253
|
}
|
|
7027
|
-
/** How an opted-in `[showScore]` host renders a choice option's points. */
|
|
7028
|
-
type FlyFormScoreDisplay = 'inline' | 'badge';
|
|
7029
7254
|
/**
|
|
7030
|
-
*
|
|
7031
|
-
*
|
|
7032
|
-
* - text: Text / MultilineText / Email
|
|
7033
|
-
* - number: Number
|
|
7034
|
-
* - dateValue: Date / DateTime (raw `<input>` value string)
|
|
7035
|
-
* - boolValue: Boolean
|
|
7036
|
-
* - selectedOptionIds: SingleSelect / MultipleSelect / RadioButton / Country
|
|
7037
|
-
* - fileIds: File / MultiFile / Image (filled by the host after upload; this
|
|
7038
|
-
* component emits it empty and surfaces the raw selection via `fileSelected`)
|
|
7255
|
+
* DI token carrying {@link FlyGanttDefaults}. Optional everywhere — a chart with no provider falls
|
|
7256
|
+
* back to the component's own built-in defaults, which is what every pre-existing consumer gets.
|
|
7039
7257
|
*/
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
}
|
|
7048
|
-
/** One field's answer — the unit emitted by `answersChange` / `submit`. */
|
|
7049
|
-
interface FlyFormAnswer {
|
|
7050
|
-
questionId: string;
|
|
7051
|
-
value: FlyFormAnswerValue;
|
|
7052
|
-
}
|
|
7258
|
+
declare const FLY_GANTT_DEFAULTS: InjectionToken<FlyGanttDefaults>;
|
|
7259
|
+
/** Provider helper — `providers: [provideFlyGanttDefaults({ labelWidth: 360 })]`. */
|
|
7260
|
+
declare function provideFlyGanttDefaults(defaults: FlyGanttDefaults): Provider;
|
|
7261
|
+
|
|
7262
|
+
/** Label-pane width bounds (px) the splitter clamps to. */
|
|
7263
|
+
declare const GANTT_LABEL_W_MIN = 140;
|
|
7264
|
+
declare const GANTT_LABEL_W_MAX = 720;
|
|
7053
7265
|
/**
|
|
7054
|
-
*
|
|
7055
|
-
*
|
|
7056
|
-
*
|
|
7266
|
+
* Width (px) a label pane opens at when neither the consumer's `labelWidth` input nor an app-level
|
|
7267
|
+
* `FlyGanttDefaults` says otherwise.
|
|
7268
|
+
*
|
|
7269
|
+
* Raised from the original 240. A Gantt label is a full work-breakdown title, routinely carrying a
|
|
7270
|
+
* prefix the consumer composed in (PPM puts the assignee's initials on every task row and a weight
|
|
7271
|
+
* suffix on every milestone), and at 240px the ellipsis landed inside the NAME for a majority of
|
|
7272
|
+
* real rows — which turns the pane into a list of indistinguishable truncations rather than a
|
|
7273
|
+
* readable outline. It remains an INITIAL value only: the divider drag, the keyboard resize and
|
|
7274
|
+
* `resetLabelWidth()` all behave exactly as before.
|
|
7057
7275
|
*/
|
|
7058
|
-
|
|
7059
|
-
questionId: string;
|
|
7060
|
-
files: File[];
|
|
7061
|
-
}
|
|
7276
|
+
declare const GANTT_LABEL_W_DEFAULT = 320;
|
|
7062
7277
|
|
|
7063
|
-
/** A render segment: either an ungrouped field (`group === null`) or a titled `criteriaGroup` section.
|
|
7064
|
-
* `index` is the field's running position across the whole form (drives unique element ids). */
|
|
7065
|
-
interface FlyFormFieldGroup {
|
|
7066
|
-
group: string | null;
|
|
7067
|
-
items: {
|
|
7068
|
-
q: FlyFormQuestion;
|
|
7069
|
-
index: number;
|
|
7070
|
-
}[];
|
|
7071
|
-
}
|
|
7072
7278
|
/**
|
|
7073
|
-
*
|
|
7279
|
+
* Magic-bar contribution contract (UX v2 "Nova", D5 §4).
|
|
7074
7280
|
*
|
|
7075
|
-
*
|
|
7076
|
-
*
|
|
7077
|
-
* **
|
|
7078
|
-
*
|
|
7079
|
-
*
|
|
7080
|
-
*
|
|
7081
|
-
* surface the raw selection via {@link fileSelected} and emit `fileIds` empty; the
|
|
7082
|
-
* host wires the upload and feeds ids back through the `[answers]` prefill.
|
|
7281
|
+
* The magic bar is the shell's top-bar toolbar pill. Unlike the fixed right
|
|
7282
|
+
* cluster (Help / Tasks / Notifications / assistant orb — shell-owned, an app can
|
|
7283
|
+
* never remove it), the pill's contents belong to **whatever view the user is
|
|
7284
|
+
* looking at**, and the design's reference implementation re-publishes the whole
|
|
7285
|
+
* set on every selection, tab and save (`pubTabActions`). Two consequences shape
|
|
7286
|
+
* every type below:
|
|
7083
7287
|
*
|
|
7084
|
-
*
|
|
7085
|
-
*
|
|
7086
|
-
*
|
|
7087
|
-
*
|
|
7088
|
-
*
|
|
7288
|
+
* 1. **A contribution is a full replace, never a patch.** There is no "add one
|
|
7289
|
+
* action" call, because the publisher never knows what the previous view left
|
|
7290
|
+
* behind. That also collapses D5's `search: null` ("suppress") vs `search`
|
|
7291
|
+
* absent distinction — under full replace both simply mean "this view offers
|
|
7292
|
+
* no search".
|
|
7293
|
+
* 2. **Render data and behaviour are separated in the type system.** Each family
|
|
7294
|
+
* has a `*Spec` base carrying ONLY the fields that affect what is painted;
|
|
7295
|
+
* the publisher-facing type extends it with callbacks, and the shell-facing
|
|
7296
|
+
* `*View` type extends it with bound invokers. The base IS the equality
|
|
7297
|
+
* surface {@link MagicBarRegistry} dedupes on — a re-publish whose specs are
|
|
7298
|
+
* unchanged must not disturb the shell, even though its closures are brand
|
|
7299
|
+
* new objects every time (an arrow function in a component method never
|
|
7300
|
+
* compares equal to its predecessor). See `magic-bar-projection.ts`.
|
|
7089
7301
|
*
|
|
7090
|
-
* i18n
|
|
7091
|
-
*
|
|
7092
|
-
*
|
|
7093
|
-
*
|
|
7094
|
-
*
|
|
7302
|
+
* **Strings are i18n keys, never resolved text** — same rule as
|
|
7303
|
+
* {@link AgentCommandRegistration} (`labelKey` / `descriptionKey` / `hintKey`),
|
|
7304
|
+
* for the same two reasons: a contribution outlives a locale switch (a resolved
|
|
7305
|
+
* label would silently go stale until the publisher happened to re-publish), and
|
|
7306
|
+
* keys are locale-invariant so the dedupe fingerprint doesn't churn when the user
|
|
7307
|
+
* changes language. Keys resolve in the OWNING app's bundle.
|
|
7095
7308
|
*
|
|
7096
|
-
* @
|
|
7097
|
-
*
|
|
7098
|
-
*
|
|
7099
|
-
*
|
|
7100
|
-
*
|
|
7101
|
-
*
|
|
7102
|
-
*
|
|
7103
|
-
*
|
|
7104
|
-
*
|
|
7105
|
-
*
|
|
7106
|
-
*
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7309
|
+
* **Every `*Key` has an optional `*Params` sibling** ({@link MagicBarTextParams}),
|
|
7310
|
+
* fed straight to `I18nService.t(key, params)`. Without it a count-carrying string
|
|
7311
|
+
* ("Search 1,204 tasks…") forces the publisher to pass pre-formatted TEXT as the
|
|
7312
|
+
* key: it renders correctly in `en`, renders identically untranslated in ar/fr/ur,
|
|
7313
|
+
* and no locale tool can see it. Params participate in the dedupe fingerprint, so
|
|
7314
|
+
* a changing count re-paints.
|
|
7315
|
+
*
|
|
7316
|
+
* Which of D5 §4's "dynamics the shell must honor" live where:
|
|
7317
|
+
*
|
|
7318
|
+
* | # | Dynamic | Owner |
|
|
7319
|
+
* |---|---|---|
|
|
7320
|
+
* | 1 | Live re-publication, idempotent replace | {@link MagicBarRegistry} (here) |
|
|
7321
|
+
* | 2 | Disabled ≠ hidden, auto disabled-tooltip | contract keeps `disabled` rows; `fly-magic-actions` renders + suffixes |
|
|
7322
|
+
* | 3 | `toolbarPopIn` 40 ms stagger | renderer — it tracks on {@link MagicBarActionSpec.id}, which is why ids are unique across the WHOLE contribution |
|
|
7323
|
+
* | 4 | i18n on every label/tip | contract (keys + params, above) |
|
|
7324
|
+
* | 5 | Fixed right cluster is not contributable | contract — no slot exists for it |
|
|
7325
|
+
* | 6 | Mobile renders the same contribution | contract carries no form-factor branch; `openWidth` is a desktop hint mobile ignores |
|
|
7326
|
+
* | 7 | `shortcut` reserved (design has no shortcut affordance yet) | contract — carried, unrendered |
|
|
7327
|
+
*
|
|
7328
|
+
* On dynamic 3 specifically: the registry's dedupe does NOT stop the stagger
|
|
7329
|
+
* replaying, and believing it does would produce a renderer that re-animates on
|
|
7330
|
+
* every click. Dedupe fires only when *nothing painted* changed, and the dominant
|
|
7331
|
+
* case — `disabled: !hasSelection` — changes the fingerprint on every selection.
|
|
7332
|
+
* What holds the DOM still is the renderer's `@for (…; track item.id)`.
|
|
7333
|
+
*/
|
|
7334
|
+
/**
|
|
7335
|
+
* How an action paints. `'text'` is the labelled-pill form (calendar's "Today").
|
|
7336
|
+
*
|
|
7337
|
+
* `kind` and {@link MagicBarActionSpec.iconPath} are INDEPENDENT, and the three useful
|
|
7338
|
+
* combinations are all reachable:
|
|
7339
|
+
*
|
|
7340
|
+
* | `kind` | `iconPath` | Paints |
|
|
7341
|
+
* |---|---|---|
|
|
7342
|
+
* | absent / `'icon'` | set | icon only — the default, for a verb with a universally-read glyph |
|
|
7343
|
+
* | `'text'` | absent | label only — for a value with no honest glyph ("Shortlisted", "Deferred") |
|
|
7344
|
+
* | `'text'` | set | **icon + label** — for a verb whose glyph needs naming ("Promote to schedule") |
|
|
7345
|
+
*
|
|
7346
|
+
* Prefer icon-only for the small set of verbs a user reads without help — add, edit, delete, close,
|
|
7347
|
+
* save. Anything else earns its label: an unlabelled glyph the reader has to hover to identify is a
|
|
7348
|
+
* quiz, and the tooltip is not an answer on touch.
|
|
7349
|
+
*/
|
|
7350
|
+
type MagicBarActionKind = 'icon' | 'text' | 'toggle';
|
|
7351
|
+
/**
|
|
7352
|
+
* Semantic colour of an action. `'danger'` is the red Delete treatment (red glyph
|
|
7353
|
+
* + red 18 % hover tint, D7); `'success'` is the green "Mark as complete" pressed
|
|
7354
|
+
* state (D5 §1.4 + §4 prop table: "pressed bg tint-sel / green for complete").
|
|
7355
|
+
*
|
|
7356
|
+
* A union rather than the boolean `danger` this started as: the design already
|
|
7357
|
+
* demands a second colour, and widening a shipped `danger?: boolean` into a union
|
|
7358
|
+
* later would mean REMOVING an interface member — MAJOR under `tools/ds-compat`
|
|
7359
|
+
* (rule 7), which forks the federation singleton for every remote.
|
|
7360
|
+
*/
|
|
7361
|
+
type MagicBarTone = 'default' | 'danger' | 'success';
|
|
7362
|
+
/**
|
|
7363
|
+
* Interpolation params for one i18n key — the `params` argument of
|
|
7364
|
+
* `I18nService.t(key, params)`, substituting `{{name}}` placeholders.
|
|
7365
|
+
*
|
|
7366
|
+
* Values are `string | number` only: the fingerprint has to encode them, and the
|
|
7367
|
+
* renderer resolves them through `t()`, which stringifies. A `Date` or a nested
|
|
7368
|
+
* object would fingerprint as `{}` and paint as `[object Object]`.
|
|
7369
|
+
*/
|
|
7370
|
+
type MagicBarTextParams = Readonly<Record<string, string | number>>;
|
|
7371
|
+
/**
|
|
7372
|
+
* Identity of a contribution's publisher, and the arbitration key the shell uses
|
|
7373
|
+
* to pick which contribution the bar renders.
|
|
7374
|
+
*
|
|
7375
|
+
* `windowId` is optional but strongly preferred: two windows of the same app can
|
|
7376
|
+
* be open on different selections, and keying on `appId` alone would let the
|
|
7377
|
+
* background one paint the focused one's toolbar. It is optional only because a
|
|
7378
|
+
* federated remote that predates per-window plumbing can still contribute —
|
|
7379
|
+
* {@link MagicBarRegistry} resolves an `appId`-keyed slot as a fallback.
|
|
7380
|
+
*
|
|
7381
|
+
* It only has to be unique **within the publishing app** (the shell passes its own
|
|
7382
|
+
* `win-<appId>-<timestamp>` window id; a tab index or a route-derived id is equally
|
|
7383
|
+
* valid) — {@link magicBarOwnerKey} scopes it by `appId`, so a value another app
|
|
7384
|
+
* also uses can never cross over.
|
|
7385
|
+
*/
|
|
7386
|
+
interface MagicBarOwnerRef {
|
|
7387
|
+
readonly appId: string;
|
|
7388
|
+
readonly windowId?: string;
|
|
7389
|
+
}
|
|
7390
|
+
/**
|
|
7391
|
+
* Storage/arbitration key for an owner. Exported because the shell computes it
|
|
7392
|
+
* on the janitor path (`clear` after a window closes) without holding the
|
|
7393
|
+
* publisher.
|
|
7394
|
+
*
|
|
7395
|
+
* **Both fields key the slot**, even though the shell's own ids
|
|
7396
|
+
* (`win-<appId>-<timestamp>`) are already unique. `windowId` is publisher-supplied
|
|
7397
|
+
* DATA that crosses the federation boundary, and the field is documented only as
|
|
7398
|
+
* "two windows of the same app" — nothing stops a remote passing a tab index or a
|
|
7399
|
+
* route-derived id. Keyed on `windowId` alone, two apps that both call their first
|
|
7400
|
+
* window `"1"` would share a slot: one silently paints the other's chrome, and the
|
|
7401
|
+
* shell's janitor `clear()` wipes the wrong one.
|
|
7402
|
+
*/
|
|
7403
|
+
declare function magicBarOwnerKey(owner: MagicBarOwnerRef): string;
|
|
7404
|
+
/** One `menuitemradio` row. `value` is the publisher's own vocabulary. */
|
|
7405
|
+
interface MagicBarRadioOption {
|
|
7406
|
+
readonly value: string;
|
|
7156
7407
|
/**
|
|
7157
|
-
*
|
|
7158
|
-
* (
|
|
7159
|
-
*
|
|
7160
|
-
*
|
|
7408
|
+
* i18n key for this row. Required, and it stays required — the overwhelming case is a fixed
|
|
7409
|
+
* vocabulary (statuses, sort orders) that MUST translate. When {@link label} is supplied this
|
|
7410
|
+
* is the accessible fallback used if the row's data-derived text is ever empty, so give it a
|
|
7411
|
+
* generic key ("Untitled") rather than inventing a per-value one.
|
|
7161
7412
|
*/
|
|
7162
|
-
readonly
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
readonly isValid: _angular_core.Signal<boolean>;
|
|
7166
|
-
/** Whether `(submit)` may fire: valid required set AND declaration accepted (if any). */
|
|
7167
|
-
readonly canSubmit: _angular_core.Signal<boolean>;
|
|
7168
|
-
readonly declarationAccepted: _angular_core.Signal<boolean>;
|
|
7169
|
-
fieldId(index: number): string;
|
|
7170
|
-
descId(index: number): string;
|
|
7171
|
-
errId(index: number): string;
|
|
7172
|
-
describedBy(q: FlyFormQuestion, index: number): string | null;
|
|
7173
|
-
isChoice(type: FlyFormQuestionType): boolean;
|
|
7174
|
-
isFile(type: FlyFormQuestionType): boolean;
|
|
7175
|
-
/** Types rendered as a native input group inside `<fieldset><legend>`. */
|
|
7176
|
-
isFieldset(type: FlyFormQuestionType): boolean;
|
|
7177
|
-
isCountry(type: FlyFormQuestionType): boolean;
|
|
7413
|
+
readonly labelKey: string;
|
|
7414
|
+
/** Params for {@link labelKey} — the count-badged option ("All statuses ({{count}})"). */
|
|
7415
|
+
readonly labelParams?: MagicBarTextParams;
|
|
7178
7416
|
/**
|
|
7179
|
-
*
|
|
7417
|
+
* ALREADY-RESOLVED display text, for a row whose label is TENANT DATA rather than a caption —
|
|
7418
|
+
* a campaign name, an area of focus, an owner. When present it wins over {@link labelKey}.
|
|
7180
7419
|
*
|
|
7181
|
-
*
|
|
7182
|
-
*
|
|
7183
|
-
*
|
|
7184
|
-
*
|
|
7185
|
-
*
|
|
7420
|
+
* ## Why this had to exist
|
|
7421
|
+
* Everything else in this contract is an i18n key, deliberately (see the module header). But a
|
|
7422
|
+
* key can only name a string the APP ships in its locale bundles, and a tenant's campaign names
|
|
7423
|
+
* are rows in their database. Without this field a publisher had exactly two bad options: put
|
|
7424
|
+
* the name in `labelKey`, which renders correctly in `en`, renders identically untranslated in
|
|
7425
|
+
* ar/fr/ur, and is invisible to every locale tool; or leave the filter out of the bar entirely.
|
|
7426
|
+
* Thoughts' `top-trending` chose the second and kept its campaign/area filters in-page — that
|
|
7427
|
+
* is the gap this closes.
|
|
7428
|
+
*
|
|
7429
|
+
* ## What it does NOT license
|
|
7430
|
+
* Do not use it for captions. If the string is something your app authored — "All statuses",
|
|
7431
|
+
* "Newest first", an action name — it belongs in a locale bundle and `labelKey` is the field.
|
|
7432
|
+
* The test is where the string comes from: shipped with the app ⇒ `labelKey`; read from the
|
|
7433
|
+
* tenant's data ⇒ `label`. A resolved caption here is untranslatable text smuggled past the
|
|
7434
|
+
* locale tooling, which is precisely what the key-only rule exists to prevent.
|
|
7435
|
+
*
|
|
7436
|
+
* It participates in the dedupe fingerprint, so a renamed campaign repaints.
|
|
7186
7437
|
*/
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
|
|
7438
|
+
readonly label?: string;
|
|
7439
|
+
}
|
|
7440
|
+
/** Render surface of a radio menu — the dedupe key for {@link MagicBarRadioMenu}. */
|
|
7441
|
+
interface MagicBarRadioMenuSpec {
|
|
7442
|
+
/** Eyebrow above the options ("Filter by status" / "Sort by"). */
|
|
7443
|
+
readonly titleKey: string;
|
|
7444
|
+
/** Params for {@link titleKey}. */
|
|
7445
|
+
readonly titleParams?: MagicBarTextParams;
|
|
7446
|
+
readonly options: readonly MagicBarRadioOption[];
|
|
7447
|
+
/** Current selection — check glyph + 600 weight on the matching row. */
|
|
7448
|
+
readonly value: string;
|
|
7449
|
+
/** The unfiltered/unsorted baseline; the trigger shows its accent dot iff `value !== defaultValue`. */
|
|
7450
|
+
readonly defaultValue: string;
|
|
7451
|
+
}
|
|
7452
|
+
/** What a publisher supplies for a radio menu. */
|
|
7453
|
+
interface MagicBarRadioMenu extends MagicBarRadioMenuSpec {
|
|
7454
|
+
readonly onSelect?: (value: string) => void;
|
|
7455
|
+
}
|
|
7456
|
+
/** What the shell renders. `select` always exists; it no-ops when the publisher supplied no handler. */
|
|
7457
|
+
interface MagicBarRadioMenuView extends MagicBarRadioMenuSpec {
|
|
7458
|
+
select(value: string): void;
|
|
7459
|
+
}
|
|
7460
|
+
/**
|
|
7461
|
+
* Render surface of an action — the dedupe key for {@link MagicBarAction}.
|
|
7462
|
+
*
|
|
7463
|
+
* `id` must be unique across the WHOLE contribution (every group, plus `primary`
|
|
7464
|
+
* and `overflow`), not merely within its group: it is the address the shell's
|
|
7465
|
+
* invoker resolves against the publisher's latest handlers.
|
|
7466
|
+
*/
|
|
7467
|
+
interface MagicBarActionSpec {
|
|
7468
|
+
readonly id: string;
|
|
7469
|
+
/** i18n key — the `aria-label` and the default tooltip. */
|
|
7470
|
+
readonly labelKey: string;
|
|
7471
|
+
/** Params for {@link labelKey}, e.g. `{ count: 3 }` for "Delete {{count}} items". */
|
|
7472
|
+
readonly labelParams?: MagicBarTextParams;
|
|
7190
7473
|
/**
|
|
7191
|
-
*
|
|
7192
|
-
*
|
|
7193
|
-
*
|
|
7474
|
+
* Inner-SVG geometry for a 24×24 glyph (`stroke-width: 1.8`, round caps) —
|
|
7475
|
+
* the design's icon transport. Reference {@link FLY_MAGIC_BAR_ICONS} by name
|
|
7476
|
+
* rather than hand-authoring; a publisher MAY author its own, subject to the
|
|
7477
|
+
* contract below.
|
|
7478
|
+
*
|
|
7479
|
+
* **This value is not trusted.** The renderer parses it against a closed
|
|
7480
|
+
* allowlist — self-closing `path`/`circle`/`rect`/`ellipse`/`line`/`polyline`/
|
|
7481
|
+
* `polygon` elements carrying geometry attributes only (`d`, `cx`, `points`,
|
|
7482
|
+
* …) — and binds the result as real attributes. It is never assigned as HTML.
|
|
7483
|
+
* Anything else (a container element, an `on*` handler, `style`, `href`,
|
|
7484
|
+
* `fill="url(…)"`, a stray text node) rejects the WHOLE fragment: the button
|
|
7485
|
+
* renders with no glyph and logs. See `magic-actions-icon.ts`.
|
|
7486
|
+
*
|
|
7487
|
+
* The type stays `string` deliberately. Narrowing it to a branded/opaque type
|
|
7488
|
+
* would be a ds-compat MAJOR, and it would not buy anything the renderer's own
|
|
7489
|
+
* validation does not already guarantee — a nominal type describes where a
|
|
7490
|
+
* value came from, not what it contains.
|
|
7194
7491
|
*/
|
|
7195
|
-
|
|
7196
|
-
/**
|
|
7197
|
-
|
|
7198
|
-
|
|
7199
|
-
|
|
7200
|
-
numberValue(q: FlyFormQuestion): number | null;
|
|
7201
|
-
dateValue(q: FlyFormQuestion): string;
|
|
7202
|
-
boolValue(q: FlyFormQuestion): boolean | null;
|
|
7203
|
-
singleValue(q: FlyFormQuestion): string | null;
|
|
7204
|
-
isSelected(q: FlyFormQuestion, optionId: string): boolean;
|
|
7205
|
-
countryOptions(q: FlyFormQuestion): readonly FlySelectOption[];
|
|
7206
|
-
selectOptions(q: FlyFormQuestion): readonly FlySelectOption[];
|
|
7207
|
-
fileNames(q: FlyFormQuestion): string[];
|
|
7208
|
-
acceptFor(q: FlyFormQuestion): string;
|
|
7209
|
-
onText(q: FlyFormQuestion, value: string): void;
|
|
7210
|
-
onNumber(q: FlyFormQuestion, value: string): void;
|
|
7211
|
-
onDate(q: FlyFormQuestion, value: string): void;
|
|
7212
|
-
onBoolean(q: FlyFormQuestion, value: boolean): void;
|
|
7213
|
-
onSingleSelect(q: FlyFormQuestion, value: string | readonly string[] | null): void;
|
|
7214
|
-
onRadio(q: FlyFormQuestion, optionId: string): void;
|
|
7215
|
-
onMultiToggle(q: FlyFormQuestion, optionId: string, checked: boolean): void;
|
|
7216
|
-
onFiles(q: FlyFormQuestion, input: HTMLInputElement): void;
|
|
7217
|
-
onDeclarationToggle(checked: boolean): void;
|
|
7218
|
-
onSubmit(): void;
|
|
7219
|
-
private _touch;
|
|
7220
|
-
private _setFileError;
|
|
7221
|
-
private _mutate;
|
|
7222
|
-
private _emit;
|
|
7223
|
-
private _collectAnswers;
|
|
7224
|
-
private _isAnswered;
|
|
7225
|
-
private _isEmptyValue;
|
|
7226
|
-
private _selectedIds;
|
|
7492
|
+
readonly iconPath?: string;
|
|
7493
|
+
/** Default `'icon'`. */
|
|
7494
|
+
readonly kind?: MagicBarActionKind;
|
|
7495
|
+
/** Dimmed (`opacity .38`), NEVER hidden — a vanishing action teaches the user nothing. */
|
|
7496
|
+
readonly disabled?: boolean;
|
|
7227
7497
|
/**
|
|
7228
|
-
*
|
|
7229
|
-
*
|
|
7230
|
-
*
|
|
7231
|
-
*
|
|
7232
|
-
|
|
7498
|
+
* Tooltip override while disabled. Absent is the normal case: the renderer
|
|
7499
|
+
* auto-suffixes the resolved label ("… — select an item first"). Resolution
|
|
7500
|
+
* and the connector phrasing are the renderer's job precisely because they are
|
|
7501
|
+
* locale work, and this store holds keys rather than text.
|
|
7502
|
+
*/
|
|
7503
|
+
readonly disabledTipKey?: string;
|
|
7504
|
+
/** Params for {@link disabledTipKey}. */
|
|
7505
|
+
readonly disabledTipParams?: MagicBarTextParams;
|
|
7506
|
+
/**
|
|
7507
|
+
* Mirror the glyph horizontally under `dir="rtl"`.
|
|
7233
7508
|
*
|
|
7234
|
-
*
|
|
7235
|
-
*
|
|
7236
|
-
*
|
|
7509
|
+
* Most marks in {@link FLY_MAGIC_BAR_ICONS} are direction-neutral — a trash can, a gear, a
|
|
7510
|
+
* calendar grid read the same in every locale, and mirroring them would be wrong. A minority
|
|
7511
|
+
* encode a DIRECTION as their meaning: indent/outdent, promote (an up-and-right arrow), a
|
|
7512
|
+
* next/previous chevron, an export tray. Those are mirrored by every RTL desktop application
|
|
7513
|
+
* there is, and left unmirrored they point at the wrong edge of the screen in `ar` and `ur` —
|
|
7514
|
+
* three of this platform's four locales.
|
|
7515
|
+
*
|
|
7516
|
+
* Opt-in rather than automatic because no property of the geometry distinguishes the two
|
|
7517
|
+
* groups: only the publisher knows whether its arrow means "forward" (mirror) or "north-east"
|
|
7518
|
+
* (do not). Defaults to `false`, so every glyph shipped before this field existed paints exactly
|
|
7519
|
+
* as it did.
|
|
7520
|
+
*
|
|
7521
|
+
* It flips only the ICON. The button, its label and the bar's own item order already mirror
|
|
7522
|
+
* through logical CSS properties — see `magic-actions.component.scss`'s header.
|
|
7237
7523
|
*/
|
|
7238
|
-
|
|
7239
|
-
/**
|
|
7240
|
-
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
|
|
7248
|
-
/**
|
|
7249
|
-
|
|
7524
|
+
readonly mirrorInRtl?: boolean;
|
|
7525
|
+
/** Tooltip override while enabled. Absent → the renderer uses `labelKey`. */
|
|
7526
|
+
readonly tipKey?: string;
|
|
7527
|
+
/** Params for {@link tipKey}. */
|
|
7528
|
+
readonly tipParams?: MagicBarTextParams;
|
|
7529
|
+
/**
|
|
7530
|
+
* Semantic colour. Default `'default'`; `'danger'` is the ONLY thing that makes
|
|
7531
|
+
* an icon red (D7), `'success'` the green completed-toggle treatment.
|
|
7532
|
+
*/
|
|
7533
|
+
readonly tone?: MagicBarTone;
|
|
7534
|
+
/** `aria-pressed` for `kind: 'toggle'`. */
|
|
7535
|
+
readonly pressed?: boolean;
|
|
7536
|
+
/** Small accent dot — a non-default filter/sort is active. */
|
|
7537
|
+
readonly badgeDot?: boolean;
|
|
7538
|
+
/**
|
|
7539
|
+
* Reserved (D5 §4 item 7). The designs carry no keyboard-shortcut affordance
|
|
7540
|
+
* anywhere; the field exists so adding one later is a renderer change rather
|
|
7541
|
+
* than a contract break. Nothing renders it today.
|
|
7542
|
+
*/
|
|
7543
|
+
readonly shortcut?: string;
|
|
7250
7544
|
}
|
|
7251
|
-
/**
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
/**
|
|
7255
|
-
|
|
7256
|
-
|
|
7257
|
-
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
* navigable; the component never assumes `body` is present when `isDeleted`).
|
|
7262
|
-
* `canEdit` / `canDelete` / `canModerate` are pre-resolved by the host (Cerbos
|
|
7263
|
-
* decision or equivalent) — the component never evaluates authorization itself.
|
|
7264
|
-
*/
|
|
7265
|
-
interface FlyComment {
|
|
7266
|
-
id: string;
|
|
7267
|
-
authorUserId: string;
|
|
7268
|
-
authorDisplayName?: string;
|
|
7269
|
-
authorAvatarUrl?: string;
|
|
7270
|
-
parentCommentId?: string;
|
|
7271
|
-
depth: number;
|
|
7272
|
-
body: string;
|
|
7273
|
-
replyCount: number;
|
|
7274
|
-
isEdited: boolean;
|
|
7275
|
-
isDeleted: boolean;
|
|
7276
|
-
createdAt: string;
|
|
7277
|
-
updatedAt?: string;
|
|
7278
|
-
canEdit: boolean;
|
|
7279
|
-
canDelete: boolean;
|
|
7280
|
-
canModerate: boolean;
|
|
7545
|
+
/** What a publisher supplies for one action. */
|
|
7546
|
+
interface MagicBarAction extends MagicBarActionSpec {
|
|
7547
|
+
readonly menu?: MagicBarRadioMenu;
|
|
7548
|
+
/**
|
|
7549
|
+
* Invoked on activation. The argument is the DOM element the renderer painted
|
|
7550
|
+
* for this action — see {@link MagicBarActionView.run} for why it is passed and
|
|
7551
|
+
* what a publisher may do with it. Ignore it and this is the zero-argument
|
|
7552
|
+
* handler it has always been.
|
|
7553
|
+
*/
|
|
7554
|
+
readonly onSelect?: (trigger?: HTMLElement) => void;
|
|
7281
7555
|
}
|
|
7282
7556
|
/**
|
|
7283
|
-
*
|
|
7284
|
-
*
|
|
7285
|
-
*
|
|
7286
|
-
* separate {@link FlyCommentPage} instances tracked by the host.
|
|
7557
|
+
* What the shell renders. `run()` always exists and always dispatches to the
|
|
7558
|
+
* publisher's LATEST handler for this id — including after a re-publish the
|
|
7559
|
+
* registry deliberately did not propagate (see `magic-bar-projection.ts`).
|
|
7287
7560
|
*/
|
|
7288
|
-
interface
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7561
|
+
interface MagicBarActionView extends MagicBarActionSpec {
|
|
7562
|
+
readonly menu: MagicBarRadioMenuView | null;
|
|
7563
|
+
/**
|
|
7564
|
+
* Fire the publisher's newest handler for this id.
|
|
7565
|
+
*
|
|
7566
|
+
* ## Why it carries the trigger element
|
|
7567
|
+
* An action that opens a POPOVER the publisher owns — the canonical case is a
|
|
7568
|
+
* listing screen's advanced-filter panel — has to position that popover under
|
|
7569
|
+
* the button the user just pressed. The publisher cannot find that button:
|
|
7570
|
+
* embedded, it is painted by `fly-magic-actions` inside the shell's top-bar
|
|
7571
|
+
* pill, in the shell's DOM, several stacking contexts and one federation
|
|
7572
|
+
* boundary away from the remote that published the action. Before this argument
|
|
7573
|
+
* existed, PPM's projects register had to anchor its panel to its own page
|
|
7574
|
+
* header instead, which put the panel in the middle of the window while the
|
|
7575
|
+
* button that opened it sat in the chrome above — an affordance with no visible
|
|
7576
|
+
* relationship to its own trigger.
|
|
7577
|
+
*
|
|
7578
|
+
* Passing the element rather than modelling the popover is deliberate. The
|
|
7579
|
+
* panel's CONTENT is app schema (see {@link MagicBarSearch.onOpenFilters} for
|
|
7580
|
+
* the same ruling), so it must stay in the publisher's own DOM and injection
|
|
7581
|
+
* context; only its POSITION is chrome-relative. An element reference crosses
|
|
7582
|
+
* the federation boundary without any of the coupling a descriptor would need —
|
|
7583
|
+
* a DOM node is a DOM node in every bundle. `fly-filter-panel`'s `[anchorEl]`
|
|
7584
|
+
* is the intended consumer.
|
|
7585
|
+
*
|
|
7586
|
+
* ## What a publisher must not assume
|
|
7587
|
+
* The element is the trigger AS PAINTED RIGHT NOW. It is valid for the duration
|
|
7588
|
+
* of the popover, not beyond: a re-publish that drops this action id destroys it
|
|
7589
|
+
* (`@for (…; track action.id)`), and a mode switch repaints it in a different
|
|
7590
|
+
* chrome entirely. Hold it in a signal the popover's open-state clears, never in
|
|
7591
|
+
* long-lived state, and never mutate it.
|
|
7592
|
+
*
|
|
7593
|
+
* It is OPTIONAL because not every renderer has one to give — a keyboard-driven
|
|
7594
|
+
* invocation, a synthetic call in a test, an inline composer that paints no
|
|
7595
|
+
* button. A publisher that receives `undefined` must still work: for a popover
|
|
7596
|
+
* that means falling back to its own in-page anchoring, which is exactly what
|
|
7597
|
+
* `fly-filter-panel` does when `[anchorEl]` is null.
|
|
7598
|
+
*/
|
|
7599
|
+
run(trigger?: HTMLElement): void;
|
|
7314
7600
|
}
|
|
7315
|
-
/**
|
|
7316
|
-
interface
|
|
7317
|
-
|
|
7601
|
+
/** Render surface of a group — the dedupe key for {@link MagicBarGroup}. */
|
|
7602
|
+
interface MagicBarGroupSpec {
|
|
7603
|
+
readonly id: string;
|
|
7604
|
+
/** i18n key for the `role="group"` aria-label ("Signal actions"). */
|
|
7605
|
+
readonly labelKey: string;
|
|
7606
|
+
/** Framed variant: 2 px gaps + a trailing separator. Plain (default) uses 8 px gaps. */
|
|
7607
|
+
readonly framed?: boolean;
|
|
7318
7608
|
}
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
commentId: string;
|
|
7322
|
-
reason: FlyCommentReportReason;
|
|
7323
|
-
detail?: string;
|
|
7609
|
+
interface MagicBarGroup extends MagicBarGroupSpec {
|
|
7610
|
+
readonly items: readonly MagicBarAction[];
|
|
7324
7611
|
}
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
locked: boolean;
|
|
7612
|
+
interface MagicBarGroupView extends MagicBarGroupSpec {
|
|
7613
|
+
readonly items: readonly MagicBarActionView[];
|
|
7328
7614
|
}
|
|
7329
|
-
|
|
7330
7615
|
/**
|
|
7331
|
-
*
|
|
7332
|
-
*
|
|
7333
|
-
* Renders a {@link FlyCommentPage} (root comments) plus lazily-fetched nested
|
|
7334
|
-
* reply pages into an accessible, theme-aware thread: reply composer, inline
|
|
7335
|
-
* edit, soft-delete (tombstone render), typed report-with-reason dialog, and
|
|
7336
|
-
* moderator affordances (lock/unlock, delete-any). It is a platform surface —
|
|
7337
|
-
* transport-agnostic like `fly-survey-form` / `fly-dynamic-form`: this component
|
|
7338
|
-
* never calls an API. It only renders the pages the host hands it via
|
|
7339
|
-
* `[rootPage]` / `[repliesByParent]` and emits typed requests
|
|
7340
|
-
* (`loadReplies`/`loadMore`/`submit`/`edit`/`delete`/`report`/`lockToggle`) —
|
|
7341
|
-
* the host owns HTTP, optimistic-insert reconciliation, and any live-update
|
|
7342
|
-
* channel (SignalR, polling, …).
|
|
7343
|
-
*
|
|
7344
|
-
* Nested replies are fetched **lazily on expand** (`loadReplies`, never an
|
|
7345
|
-
* eager load-all) — the explicit fix for the legacy unpaged-children scale bug
|
|
7346
|
-
* — and each level pages independently via `loadMore`.
|
|
7347
|
-
*
|
|
7348
|
-
* The `comments` core app owns no user profile data, so `FlyComment` carries
|
|
7349
|
-
* `authorUserId` and an OPTIONAL `authorDisplayName`. Rather than make every host
|
|
7350
|
-
* map names in itself (and render GUIDs when it forgets), bind
|
|
7351
|
-
* `[resolveDisplayName]` to `FlyUserDirectoryService.label` — see
|
|
7352
|
-
* {@link FlyCommentThreadComponent.resolveDisplayName}. Still transport-agnostic:
|
|
7353
|
-
* the resolver is a function the host hands over, not a call this component makes.
|
|
7354
|
-
*
|
|
7355
|
-
* i18n is self-sufficient through the `comment.*` keys in `DS_BASELINE_LOCALES`
|
|
7356
|
-
* (en/ar/fr/ur), overridable by any consumer key of the same name. RTL works via
|
|
7357
|
-
* logical CSS. Styling uses DS theme tokens (`--surface-*`, `--label-*`,
|
|
7358
|
-
* `--separator`, `--fill-*`, `--accent`, `--system-*`) with light-neutral
|
|
7359
|
-
* fallbacks so it stays readable even in a consumer that hasn't mapped them.
|
|
7616
|
+
* Render surface of the expanding search field — the dedupe key for
|
|
7617
|
+
* {@link MagicBarSearch}.
|
|
7360
7618
|
*
|
|
7361
|
-
*
|
|
7362
|
-
*
|
|
7363
|
-
* <fly-comment-thread
|
|
7364
|
-
* [rootPage]="rootPage()"
|
|
7365
|
-
* [repliesByParent]="repliesByParent()"
|
|
7366
|
-
* [currentUserId]="me.id"
|
|
7367
|
-
* [resolveDisplayName]="directory.label"
|
|
7368
|
-
* [canModerateThread]="canModerate()"
|
|
7369
|
-
* [isLocked]="thread().isLocked"
|
|
7370
|
-
* (loadReplies)="onLoadReplies($event)"
|
|
7371
|
-
* (loadMore)="onLoadMore($event)"
|
|
7372
|
-
* (submit)="onSubmit($event)"
|
|
7373
|
-
* (edit)="onEdit($event)"
|
|
7374
|
-
* (delete)="onDelete($event)"
|
|
7375
|
-
* (report)="onReport($event)"
|
|
7376
|
-
* (lockToggle)="onLockToggle($event)" />
|
|
7377
|
-
* ```
|
|
7619
|
+
* This is a per-page typeahead, NOT a command palette: neither design package
|
|
7620
|
+
* has a global ⌘K surface, and the only "command" affordance is the Ask-AI menu.
|
|
7378
7621
|
*/
|
|
7379
|
-
|
|
7380
|
-
/**
|
|
7381
|
-
readonly
|
|
7382
|
-
/**
|
|
7383
|
-
|
|
7384
|
-
* accumulated across `loadMore` calls by the host. Additive to the frozen
|
|
7385
|
-
* contract's `rootPage` input — required because a lazily-nested tree has no
|
|
7386
|
-
* other channel to carry fetched reply data back into the component.
|
|
7387
|
-
*/
|
|
7388
|
-
readonly repliesByParent: _angular_core.InputSignal<Readonly<Record<string, FlyCommentPage>>>;
|
|
7389
|
-
/** Current sort order label (host owns re-fetch on {@link sortChange}; purely descriptive here otherwise). */
|
|
7390
|
-
readonly sort: _angular_core.InputSignal<"newest" | "oldest">;
|
|
7391
|
-
/** Locked threads disable the composer (root + reply) entirely, for every user. */
|
|
7392
|
-
readonly isLocked: _angular_core.InputSignal<boolean>;
|
|
7393
|
-
/** The signed-in user's id — gates the "report" affordance (can't report your own comment). */
|
|
7394
|
-
readonly currentUserId: _angular_core.InputSignal<string | null>;
|
|
7395
|
-
/** Replay / read-only mode — hides composer, reply, edit, delete, report, and lock affordances.
|
|
7396
|
-
* Aliased to `[readonly]` (the public binding); the class member avoids shadowing the
|
|
7397
|
-
* TypeScript `readonly` keyword. */
|
|
7398
|
-
readonly isReadonly: _angular_core.InputSignal<boolean>;
|
|
7399
|
-
/** Thread-scoped moderator permission (lock/unlock). Additive — distinct from the
|
|
7400
|
-
* per-comment `canModerate` flag, which gates delete-any on that specific comment. */
|
|
7401
|
-
readonly canModerateThread: _angular_core.InputSignal<boolean>;
|
|
7622
|
+
interface MagicBarSearchSpec {
|
|
7623
|
+
/** Context-aware placeholder key ("Search tasks…", "Search events…"). */
|
|
7624
|
+
readonly placeholderKey: string;
|
|
7625
|
+
/** Params for {@link placeholderKey}, e.g. `{ count: 1204 }` for "Search {{count}} tasks…". */
|
|
7626
|
+
readonly placeholderParams?: MagicBarTextParams;
|
|
7402
7627
|
/**
|
|
7403
|
-
*
|
|
7404
|
-
*
|
|
7405
|
-
* this every host had to map display names into `authorDisplayName` itself — and
|
|
7406
|
-
* a host that forgot rendered raw GUIDs at the reader.
|
|
7628
|
+
* The text the search field should SHOW — literal text, not an i18n key, because
|
|
7629
|
+
* it is the user's own query rather than a caption.
|
|
7407
7630
|
*
|
|
7408
|
-
*
|
|
7409
|
-
*
|
|
7410
|
-
*
|
|
7411
|
-
*
|
|
7631
|
+
* Exists because a view can arrive **already filtered**: a deep link carrying
|
|
7632
|
+
* `?q=…`, a restored session, a filter applied from a detail pane. Without it the
|
|
7633
|
+
* box renders empty over a visibly filtered list, and the user is looking at a
|
|
7634
|
+
* contradiction the chrome cannot explain.
|
|
7412
7635
|
*
|
|
7413
|
-
*
|
|
7414
|
-
*
|
|
7415
|
-
*
|
|
7416
|
-
*
|
|
7417
|
-
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
readonly
|
|
7455
|
-
private readonly _base;
|
|
7456
|
-
readonly reportReasons: readonly FlyCommentReportReason[];
|
|
7457
|
-
/** commentIds whose reply subtree is currently expanded/visible. */
|
|
7458
|
-
private readonly _expanded;
|
|
7459
|
-
/** Composer draft text, keyed by parentCommentId (root uses {@link ROOT_DRAFT_KEY}). */
|
|
7460
|
-
private readonly _drafts;
|
|
7461
|
-
/** commentIds whose reply composer box is currently open (distinct from `_expanded`, which toggles the read view). */
|
|
7462
|
-
private readonly _replyBoxOpen;
|
|
7463
|
-
private readonly _editingId;
|
|
7464
|
-
private readonly _editDraft;
|
|
7465
|
-
private readonly _confirmingDeleteId;
|
|
7466
|
-
private readonly _reportingId;
|
|
7467
|
-
private readonly _reportReason;
|
|
7468
|
-
private readonly _reportDetail;
|
|
7469
|
-
readonly rootDraft: _angular_core.Signal<string>;
|
|
7470
|
-
readonly editingId: _angular_core.Signal<string | null>;
|
|
7471
|
-
readonly confirmingDeleteId: _angular_core.Signal<string | null>;
|
|
7472
|
-
readonly reportingId: _angular_core.Signal<string | null>;
|
|
7473
|
-
readonly reportReason: _angular_core.Signal<FlyCommentReportReason | null>;
|
|
7474
|
-
readonly reportDetail: _angular_core.Signal<string>;
|
|
7475
|
-
fieldId(suffix: string): string;
|
|
7476
|
-
isExpanded(commentId: string): boolean;
|
|
7477
|
-
isReplyBoxOpen(commentId: string): boolean;
|
|
7478
|
-
repliesFor(commentId: string): FlyCommentPage | undefined;
|
|
7479
|
-
replyDraft(commentId: string): string;
|
|
7480
|
-
isOwn(comment: FlyComment): boolean;
|
|
7636
|
+
* ## Why it is not called `query`
|
|
7637
|
+
* {@link MagicBarSearchView} — which extends this interface — already declares
|
|
7638
|
+
* `query(text: string): void`, the late-bound invoker. A `query?: string` here
|
|
7639
|
+
* would make that view an illegal extension (TS2430: `(text: string) => void` is
|
|
7640
|
+
* not assignable to `string | undefined`), and the only other way out — renaming
|
|
7641
|
+
* the invoker — removes a member of a shipped exported interface, which is a
|
|
7642
|
+
* ds-compat MAJOR (rule 7) and forks the federation singleton for every remote.
|
|
7643
|
+
* So the field takes the name that pairs with the invoker instead of colliding
|
|
7644
|
+
* with it: `queryText` is the text, `query()` submits it.
|
|
7645
|
+
*
|
|
7646
|
+
* ## Precedence — this is a SEED, not a controlled value
|
|
7647
|
+
* The field's live text is owned by the **shell**, because the user types into
|
|
7648
|
+
* it. This field is the publisher's chance to move it, and the shell adopts the
|
|
7649
|
+
* published value exactly three times:
|
|
7650
|
+
*
|
|
7651
|
+
* 1. the first time it binds this view,
|
|
7652
|
+
* 2. when {@link MagicBarContribution.viewKey} changes (reset-on-navigate — the
|
|
7653
|
+
* previous view's query must not survive into the next one), and
|
|
7654
|
+
* 3. when the published value **itself changes** from the one previously
|
|
7655
|
+
* published.
|
|
7656
|
+
*
|
|
7657
|
+
* A re-publish carrying an UNCHANGED `queryText` never touches what the user has
|
|
7658
|
+
* typed. That third clause is the whole rule: the dominant re-publish is
|
|
7659
|
+
* `disabled: !hasSelection` flipping on a selection change, and a shell that
|
|
7660
|
+
* re-read `queryText` on every emitted view would revert a keystroke every time
|
|
7661
|
+
* the user selected a row mid-search — the classic controlled-input bug. The rule
|
|
7662
|
+
* is authored once, as {@link magicBarSearchText}, so no renderer re-derives it.
|
|
7663
|
+
*
|
|
7664
|
+
* `undefined` and `''` are **different** and the difference is load-bearing:
|
|
7665
|
+
* absent means "this view does not manage the field" (nothing is ever forced),
|
|
7666
|
+
* `''` means "clear it". Both the fingerprint and the seed comparison distinguish
|
|
7667
|
+
* them.
|
|
7668
|
+
*
|
|
7669
|
+
* ## Do not echo the user's keystrokes back through this field
|
|
7670
|
+
* A publisher that mirrors its `onQuery` argument straight back into `queryText`
|
|
7671
|
+
* is harmless (the seed changes to text the field already shows). A publisher
|
|
7672
|
+
* that mirrors it back **debounced** is not: typing "abc" then publishing
|
|
7673
|
+
* `queryText: 'a'` 300 ms later is, by rule 3, a genuine publisher-initiated
|
|
7674
|
+
* change, and the field snaps back to "a". Publish here only for state the view
|
|
7675
|
+
* owns independently of the field.
|
|
7676
|
+
*/
|
|
7677
|
+
readonly queryText?: string;
|
|
7481
7678
|
/**
|
|
7482
|
-
*
|
|
7483
|
-
* explicit `authorDisplayName` (a host that already knows the name, or a
|
|
7484
|
-
* backend that returns one, always wins) → {@link resolveDisplayName} →
|
|
7485
|
-
* the raw `authorUserId`.
|
|
7679
|
+
* Expanded width in px — a **desktop layout hint**, carried verbatim.
|
|
7486
7680
|
*
|
|
7487
|
-
* The
|
|
7488
|
-
*
|
|
7489
|
-
*
|
|
7681
|
+
* The design's range is 140–420 (default 230), but this store deliberately does
|
|
7682
|
+
* NOT validate or clamp it: enforcing a paint range here would reject a whole
|
|
7683
|
+
* contribution over a cosmetic hint (leaving the previous view's actions in the
|
|
7684
|
+
* chrome), and mobile ignores the field entirely, so there is no single range to
|
|
7685
|
+
* enforce. `fly-magic-actions` clamps to the design range at paint time and is
|
|
7686
|
+
* the only place that decides what an out-of-range or non-finite value means.
|
|
7490
7687
|
*/
|
|
7491
|
-
|
|
7492
|
-
/**
|
|
7493
|
-
|
|
7494
|
-
canReport(comment: FlyComment): boolean;
|
|
7495
|
-
canReply(): boolean;
|
|
7496
|
-
canDeleteComment(comment: FlyComment): boolean;
|
|
7497
|
-
canEditComment(comment: FlyComment): boolean;
|
|
7498
|
-
formatDate(iso: string): string;
|
|
7499
|
-
onRootDraftChange(value: string): void;
|
|
7500
|
-
submitRoot(): void;
|
|
7501
|
-
toggleReplies(comment: FlyComment): void;
|
|
7502
|
-
private _expand;
|
|
7503
|
-
loadMoreRoot(): void;
|
|
7504
|
-
loadMoreReplies(parentId: string): void;
|
|
7505
|
-
openReplyBox(commentId: string): void;
|
|
7506
|
-
closeReplyBox(commentId: string): void;
|
|
7507
|
-
onReplyDraftChange(commentId: string, value: string): void;
|
|
7508
|
-
submitReply(commentId: string): void;
|
|
7509
|
-
startEdit(comment: FlyComment): void;
|
|
7510
|
-
onEditDraftChange(value: string): void;
|
|
7511
|
-
saveEdit(comment: FlyComment): void;
|
|
7512
|
-
cancelEdit(): void;
|
|
7513
|
-
requestDelete(comment: FlyComment): void;
|
|
7514
|
-
confirmDelete(comment: FlyComment): void;
|
|
7515
|
-
cancelDelete(): void;
|
|
7516
|
-
openReport(comment: FlyComment): void;
|
|
7517
|
-
onReportReasonChange(reason: FlyCommentReportReason): void;
|
|
7518
|
-
onReportDetailChange(value: string): void;
|
|
7519
|
-
submitReport(): void;
|
|
7520
|
-
closeReport(): void;
|
|
7521
|
-
/** Space would otherwise scroll the page while the backdrop (role="button") is focused. */
|
|
7522
|
-
onOverlayBackdropSpace(event: Event): void;
|
|
7523
|
-
toggleLock(): void;
|
|
7524
|
-
onSortPick(next: 'newest' | 'oldest'): void;
|
|
7525
|
-
private _setDraft;
|
|
7526
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlyCommentThreadComponent, never>;
|
|
7527
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyCommentThreadComponent, "fly-comment-thread", never, { "rootPage": { "alias": "rootPage"; "required": true; "isSignal": true; }; "repliesByParent": { "alias": "repliesByParent"; "required": false; "isSignal": true; }; "sort": { "alias": "sort"; "required": false; "isSignal": true; }; "isLocked": { "alias": "isLocked"; "required": false; "isSignal": true; }; "currentUserId": { "alias": "currentUserId"; "required": false; "isSignal": true; }; "isReadonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "canModerateThread": { "alias": "canModerateThread"; "required": false; "isSignal": true; }; "resolveDisplayName": { "alias": "resolveDisplayName"; "required": false; "isSignal": true; }; }, { "loadReplies": "loadReplies"; "loadMore": "loadMore"; "submit": "submit"; "edit": "edit"; "delete": "delete"; "report": "report"; "lockToggle": "lockToggle"; "sortChange": "sortChange"; }, never, never, true, never>;
|
|
7688
|
+
readonly openWidth?: number;
|
|
7689
|
+
/** Accent dot on the Filters button — a non-default filter is applied. */
|
|
7690
|
+
readonly filtersActive?: boolean;
|
|
7528
7691
|
}
|
|
7529
|
-
|
|
7530
|
-
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
challenge: string;
|
|
7540
|
-
/** Base64 random salt, unique per challenge. */
|
|
7541
|
-
salt: string;
|
|
7542
|
-
/** HMAC signature binding challenge + maxNumber + expiresAt (server-verified). */
|
|
7543
|
-
signature: string;
|
|
7544
|
-
/** Exclusive upper bound of the search space (difficulty). */
|
|
7545
|
-
maxNumber: number;
|
|
7546
|
-
/** ISO-8601 instant after which the solution is rejected. Echoed back verbatim. */
|
|
7547
|
-
expiresAt: string;
|
|
7692
|
+
interface MagicBarSearch extends MagicBarSearchSpec {
|
|
7693
|
+
readonly onQuery?: (query: string) => void;
|
|
7694
|
+
/**
|
|
7695
|
+
* Opens the view's own Advanced-search overlay. Presence of this handler is
|
|
7696
|
+
* what makes the Filters button exist — the DS deliberately does not model the
|
|
7697
|
+
* dialog itself. Its fields are app schema (Circles' PESTLE/horizon grid), and
|
|
7698
|
+
* a descriptor for them would be business logic the design system cannot
|
|
7699
|
+
* validate or render honestly.
|
|
7700
|
+
*/
|
|
7701
|
+
readonly onOpenFilters?: (trigger?: HTMLElement) => void;
|
|
7548
7702
|
}
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
|
|
7703
|
+
interface MagicBarSearchView extends MagicBarSearchSpec {
|
|
7704
|
+
/** True iff the publisher can open an advanced-search overlay. */
|
|
7705
|
+
readonly hasFilters: boolean;
|
|
7706
|
+
/**
|
|
7707
|
+
* Submit the field's current text to the publisher's newest `onQuery`. The
|
|
7708
|
+
* inbound half — what the field should SHOW — is
|
|
7709
|
+
* {@link MagicBarSearchSpec.queryText}, and that asymmetry in naming is forced:
|
|
7710
|
+
* this member shipped first, and renaming it would be a ds-compat MAJOR.
|
|
7711
|
+
*/
|
|
7712
|
+
query(text: string): void;
|
|
7713
|
+
/**
|
|
7714
|
+
* Open the publisher's advanced-search overlay. Carries the Filters button the
|
|
7715
|
+
* shell painted, for the same reason and under the same caveats as
|
|
7716
|
+
* {@link MagicBarActionView.run} — a publisher whose overlay is a popover
|
|
7717
|
+
* anchors it there instead of guessing at a position inside its own page.
|
|
7718
|
+
*/
|
|
7719
|
+
openFilters(trigger?: HTMLElement): void;
|
|
7564
7720
|
}
|
|
7565
|
-
/** The solver lifecycle surfaced by the component's `state()` signal. */
|
|
7566
|
-
type FlyCaptchaState = 'idle' | 'verifying' | 'verified' | 'expired' | 'error';
|
|
7567
|
-
|
|
7568
|
-
/** Lowercase-hex SHA-256 of `input` via Web Crypto — matches `Convert.ToHexStringLower(SHA256…)`. */
|
|
7569
|
-
declare function flyCaptchaSha256Hex(input: string): Promise<string>;
|
|
7570
|
-
/** Standard base64 of the UTF-8 bytes of `s` — matches .NET `Convert.ToBase64String`. */
|
|
7571
|
-
declare function flyCaptchaBase64Utf8(s: string): string;
|
|
7572
7721
|
/**
|
|
7573
|
-
*
|
|
7574
|
-
*
|
|
7575
|
-
*
|
|
7722
|
+
* One view's complete claim on the magic bar.
|
|
7723
|
+
*
|
|
7724
|
+
* Identity (`appId` / `windowId`) is deliberately absent: it belongs to the
|
|
7725
|
+
* {@link MagicBarPublisher} that was minted for this owner, so a later publish
|
|
7726
|
+
* cannot re-target another app's slot.
|
|
7576
7727
|
*/
|
|
7577
|
-
|
|
7728
|
+
interface MagicBarContribution {
|
|
7729
|
+
/**
|
|
7730
|
+
* What the publisher is showing, e.g. `'tasks:detail'`. A change here is
|
|
7731
|
+
* reset-on-navigate: the registry replaces the slot wholesale rather than
|
|
7732
|
+
* reconciling, so nothing from the previous view can survive.
|
|
7733
|
+
*/
|
|
7734
|
+
readonly viewKey: string;
|
|
7735
|
+
readonly search?: MagicBarSearch | null;
|
|
7736
|
+
/** Ordered clusters, separator-joined. */
|
|
7737
|
+
readonly groups?: readonly MagicBarGroup[];
|
|
7738
|
+
/** The accent-filled CTA ("New task", "Add signal"). */
|
|
7739
|
+
readonly primary?: MagicBarAction | null;
|
|
7740
|
+
/**
|
|
7741
|
+
* Ids of {@link AgentCommand}s this view considers most relevant, most-relevant
|
|
7742
|
+
* first — the Ask-AI menu's per-view sets.
|
|
7743
|
+
*
|
|
7744
|
+
* Ids, not command objects: the platform already models commands (manifest
|
|
7745
|
+
* `commands[]` → `AgentCommandRegistry`), and D5 §6 item 9 is explicit that
|
|
7746
|
+
* production must source these from manifests instead of the mock's hardcoded
|
|
7747
|
+
* `{ title, note, prompt }` triples. Duplicating that model here would fork the
|
|
7748
|
+
* palette and reintroduce hardcoded prompt text. Unknown ids are dropped by the
|
|
7749
|
+
* resolver; an empty list leaves the shell's affinity ranking in charge.
|
|
7750
|
+
*/
|
|
7751
|
+
readonly quickCommandIds?: readonly string[];
|
|
7752
|
+
/** The "…" overflow set. Reserved design intent (D5 §6 item 8) — Print / Export / Settings. */
|
|
7753
|
+
readonly overflow?: readonly MagicBarAction[];
|
|
7754
|
+
}
|
|
7755
|
+
/** The shell-facing projection of a contribution. See `magic-bar-projection.ts`. */
|
|
7756
|
+
interface MagicBarView {
|
|
7757
|
+
readonly appId: string;
|
|
7758
|
+
readonly windowId?: string;
|
|
7759
|
+
/** {@link magicBarOwnerKey} of the publisher. */
|
|
7760
|
+
readonly ownerKey: string;
|
|
7761
|
+
readonly viewKey: string;
|
|
7762
|
+
readonly search: MagicBarSearchView | null;
|
|
7763
|
+
readonly groups: readonly MagicBarGroupView[];
|
|
7764
|
+
readonly primary: MagicBarActionView | null;
|
|
7765
|
+
readonly quickCommandIds: readonly string[];
|
|
7766
|
+
readonly overflow: readonly MagicBarActionView[];
|
|
7767
|
+
}
|
|
7578
7768
|
/**
|
|
7579
|
-
*
|
|
7580
|
-
*
|
|
7581
|
-
*
|
|
7582
|
-
*
|
|
7583
|
-
*
|
|
7584
|
-
*
|
|
7585
|
-
* hashes candidates with a vendored **synchronous** SHA-256 ({@link sha256HexSync}
|
|
7586
|
-
* from `./sha256` — no `crypto.subtle`/promise overhead per candidate, which used
|
|
7587
|
-
* to dominate solve time), in chunks scheduled on `requestAnimationFrame` so a
|
|
7588
|
-
* chunk boundary still yields back to the browser between slices. It auto-starts
|
|
7589
|
-
* whenever the `[challenge]` input changes. Implements
|
|
7590
|
-
* {@link ControlValueAccessor} so it drops into a reactive form / `[(ngModel)]` —
|
|
7591
|
-
* the control value IS the token string.
|
|
7592
|
-
*
|
|
7593
|
-
* Expiry is the host's concern to refresh: the component checks `expiresAt` up
|
|
7594
|
-
* front and while solving, emits {@link expired}, and stops. i18n is
|
|
7595
|
-
* self-sufficient via the `captcha.*` baseline keys; RTL works via logical CSS.
|
|
7596
|
-
*
|
|
7597
|
-
* @example
|
|
7598
|
-
* ```html
|
|
7599
|
-
* <fly-captcha [challenge]="challenge()" (solved)="post($event)" (expired)="refresh()" />
|
|
7600
|
-
* ```
|
|
7769
|
+
* A view's handle on its magic-bar slot. Minted once per publisher (not per
|
|
7770
|
+
* publish) because the publish rate is the whole point of this surface: the
|
|
7771
|
+
* sibling registries hand back a handle per `register()` and expect a handful of
|
|
7772
|
+
* calls per app lifetime, whereas a magic-bar publisher re-emits on every
|
|
7773
|
+
* selection change. Handing out a fresh handle each time would leave the caller
|
|
7774
|
+
* holding a dead one and force it to reassign on every keystroke.
|
|
7601
7775
|
*/
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
readonly challenge: _angular_core.InputSignal<FlyCaptchaChallenge | null>;
|
|
7605
|
-
/** Candidates hashed synchronously in one slice before yielding back to the browser
|
|
7606
|
-
* on the next animation frame. Higher = fewer `requestAnimationFrame` hops (each
|
|
7607
|
-
* carries ~16ms of frame-boundary overhead), more synchronous work per slice.
|
|
7608
|
-
* 20,000 keeps a slice's own hashing time well under a long-task budget on modern
|
|
7609
|
-
* hardware (the vendored sync SHA-256 does several hundred thousand hashes/sec)
|
|
7610
|
-
* while needing only a handful of hops to clear the library's default difficulty. */
|
|
7611
|
-
readonly chunkSize: _angular_core.InputSignal<number>;
|
|
7612
|
-
/** The solution token once solved — the exact string to POST back to the backend. */
|
|
7613
|
-
readonly solved: _angular_core.OutputEmitterRef<string>;
|
|
7614
|
-
/** The challenge expired (up-front or mid-solve). The host should request a new one. */
|
|
7615
|
-
readonly expired: _angular_core.OutputEmitterRef<void>;
|
|
7616
|
-
readonly state: _angular_core.WritableSignal<FlyCaptchaState>;
|
|
7617
|
-
readonly token: _angular_core.WritableSignal<string | null>;
|
|
7618
|
-
/** Monotonic generation — bumped on every restart/destroy so a stale async chunk
|
|
7619
|
-
* or timer that captured an older generation no-ops instead of racing. */
|
|
7620
|
-
private _gen;
|
|
7621
|
-
private _raf;
|
|
7622
|
-
private _expiryTimer;
|
|
7623
|
-
private _onChange;
|
|
7624
|
-
private _onTouched;
|
|
7625
|
-
constructor();
|
|
7626
|
-
ngOnDestroy(): void;
|
|
7627
|
-
private _restart;
|
|
7776
|
+
interface MagicBarPublisher {
|
|
7777
|
+
readonly owner: MagicBarOwnerRef;
|
|
7628
7778
|
/**
|
|
7629
|
-
*
|
|
7630
|
-
*
|
|
7631
|
-
*
|
|
7632
|
-
*
|
|
7633
|
-
*
|
|
7634
|
-
*
|
|
7779
|
+
* Replace this owner's contribution. No-op after {@link dispose}, and no-op
|
|
7780
|
+
* after the shell has {@link MagicBarRegistry.clear}ed this owner key.
|
|
7781
|
+
*
|
|
7782
|
+
* **Publish is last-writer-wins and eviction is not** — a deliberate asymmetry.
|
|
7783
|
+
* A stale publisher (one that has been replaced on this key by a newer one)
|
|
7784
|
+
* cannot `dispose()` the newer one out of the slot, but it *can* still take the
|
|
7785
|
+
* slot back by publishing. Symmetry would need a "newest publisher wins" rule
|
|
7786
|
+
* enforced on write, which would make the first publish of a replacement
|
|
7787
|
+
* publisher silently drop whenever two live views briefly share a key. The
|
|
7788
|
+
* exposure is bounded: two live publishers on one owner key only happen while a
|
|
7789
|
+
* view is being replaced in place, and the loser re-publishes on its next
|
|
7790
|
+
* selection change. The unbounded case — a publisher that outlives its window —
|
|
7791
|
+
* is closed by `clear()`'s tombstone, not by write ordering.
|
|
7792
|
+
*/
|
|
7793
|
+
publish(contribution: MagicBarContribution): void;
|
|
7794
|
+
/**
|
|
7795
|
+
* Release the slot. Idempotent, and a no-op if another publisher has since
|
|
7796
|
+
* taken this owner key — the same stale-handle rule the sibling registries use.
|
|
7635
7797
|
*/
|
|
7636
|
-
|
|
7637
|
-
private _onSolved;
|
|
7638
|
-
private _cancel;
|
|
7639
|
-
private _schedule;
|
|
7640
|
-
private _cancelSchedule;
|
|
7641
|
-
writeValue(value: string | null): void;
|
|
7642
|
-
registerOnChange(fn: (v: string | null) => void): void;
|
|
7643
|
-
registerOnTouched(fn: () => void): void;
|
|
7644
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlyCaptchaComponent, never>;
|
|
7645
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyCaptchaComponent, "fly-captcha", never, { "challenge": { "alias": "challenge"; "required": false; "isSignal": true; }; "chunkSize": { "alias": "chunkSize"; "required": false; "isSignal": true; }; }, { "solved": "solved"; "expired": "expired"; }, never, never, true, never>;
|
|
7798
|
+
dispose(): void;
|
|
7646
7799
|
}
|
|
7647
7800
|
|
|
7648
7801
|
/**
|
|
7649
|
-
*
|
|
7802
|
+
* The Gantt **Period** control as a magic-bar radio-menu item.
|
|
7650
7803
|
*
|
|
7651
|
-
*
|
|
7652
|
-
*
|
|
7653
|
-
*
|
|
7804
|
+
* ## Why it is called Period and not Zoom
|
|
7805
|
+
* The control does not scale the chart — it changes the unit the time axis is measured in
|
|
7806
|
+
* (day / week / month / quarter), which is what a planner calls the *period*. "Zoom" invites the
|
|
7807
|
+
* browser's own Ctrl+wheel meaning, which this chart deliberately remaps to horizontal scrolling
|
|
7808
|
+
* (`gantt-pan.ts`), so two different verbs would have shared one word on the same surface. The
|
|
7809
|
+
* underlying type stays {@link GanttZoom} — renaming a shipped exported type is MAJOR under
|
|
7810
|
+
* `tools/ds-compat` and would fork the federation singleton for every remote over a caption.
|
|
7654
7811
|
*
|
|
7655
|
-
*
|
|
7656
|
-
*
|
|
7657
|
-
*
|
|
7658
|
-
*
|
|
7659
|
-
*
|
|
7660
|
-
*
|
|
7812
|
+
* ## Why it lives in the design system
|
|
7813
|
+
* A period picker is not app vocabulary: every screen that draws a `fly-gantt` needs exactly these
|
|
7814
|
+
* four levels under exactly these labels, and the first app to grow a second Gantt screen
|
|
7815
|
+
* immediately has two copies to keep in step (PPM had a project plan, a project schedule and a
|
|
7816
|
+
* portfolio roadmap). Shipping the item beside the chart means the labels ride the DS baseline
|
|
7817
|
+
* locales in all four languages and a consumer supplies only state and a callback.
|
|
7818
|
+
*
|
|
7819
|
+
* `defaultValue` is the CALLER's load-time default — `'week'` on a single project's plan, `'month'`
|
|
7820
|
+
* on a portfolio spanning years — because the trigger's accent "non-default" dot should light only
|
|
7821
|
+
* once the user has left that screen's own entry point.
|
|
7822
|
+
*
|
|
7823
|
+
* `labelKeyPrefix` exists for a consumer that already ships its own translated period labels and
|
|
7824
|
+
* does not want the DS baseline (PPM's `ppm.projects.plan.zoom.*` predate this helper). It appends
|
|
7825
|
+
* `.label` for the trigger and `.<zoom>` per option, matching the baseline layout exactly.
|
|
7661
7826
|
*/
|
|
7662
|
-
declare
|
|
7663
|
-
|
|
7664
|
-
|
|
7665
|
-
|
|
7666
|
-
/**
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
|
|
7686
|
-
|
|
7687
|
-
|
|
7688
|
-
|
|
7689
|
-
|
|
7690
|
-
|
|
7691
|
-
|
|
7692
|
-
|
|
7693
|
-
|
|
7694
|
-
|
|
7695
|
-
|
|
7827
|
+
declare function ganttPeriodBarItem(spec: {
|
|
7828
|
+
value: GanttZoom;
|
|
7829
|
+
defaultValue: GanttZoom;
|
|
7830
|
+
disabled?: boolean;
|
|
7831
|
+
/** Key namespace for the trigger + option captions. Defaults to the DS baseline `gantt.period`. */
|
|
7832
|
+
labelKeyPrefix?: string;
|
|
7833
|
+
onSelect: (zoom: GanttZoom) => void;
|
|
7834
|
+
}): MagicBarAction;
|
|
7835
|
+
/**
|
|
7836
|
+
* The **Indent** / **Outdent** pair as magic-bar actions, for a chart whose consumer maps outline
|
|
7837
|
+
* level onto something it can persist.
|
|
7838
|
+
*
|
|
7839
|
+
* Two actions rather than one toggle: they are opposite verbs with independent availability (a row
|
|
7840
|
+
* can be indentable and not outdentable, and at the top of a list neither applies), and a toggle
|
|
7841
|
+
* would have to pick a label for a state the user cannot see.
|
|
7842
|
+
*
|
|
7843
|
+
* ## Icon-only, and why they are still discoverable
|
|
7844
|
+
* Both are icon-only despite `skills/magic-bar-view-contributions.md` §5's default, because the
|
|
7845
|
+
* indent/outdent glyph pair is one of the few marks a user genuinely reads without help — it is the
|
|
7846
|
+
* same pair every word processor, IDE and desktop planner has shipped for thirty years, and the two
|
|
7847
|
+
* are identified by being MIRRORS of each other, which a label cannot improve on. They also sort
|
|
7848
|
+
* inside Add/Delete/Edit under {@link orderMagicBarItems}, so they never take the outer edge from a
|
|
7849
|
+
* verb that needs it.
|
|
7850
|
+
*
|
|
7851
|
+
* ## Disabled, never hidden
|
|
7852
|
+
* `canIndent` / `canOutdent` are state gates, not permission gates: the same row becomes indentable
|
|
7853
|
+
* the moment a suitable row appears above it. So both stay rendered and dimmed, with a tip saying
|
|
7854
|
+
* why — §6's default. Pass `disabledTipKey`s when your app's reason is more specific than the
|
|
7855
|
+
* baseline "this row cannot move any further".
|
|
7856
|
+
*/
|
|
7857
|
+
declare function ganttOutlineBarItems(spec: {
|
|
7858
|
+
canIndent: boolean;
|
|
7859
|
+
canOutdent: boolean;
|
|
7860
|
+
onIndent: () => void;
|
|
7861
|
+
onOutdent: () => void;
|
|
7862
|
+
/** Tip shown while Indent is dimmed. Defaults to the DS baseline reason. */
|
|
7863
|
+
indentDisabledTipKey?: string;
|
|
7864
|
+
/** Tip shown while Outdent is dimmed. Defaults to the DS baseline reason. */
|
|
7865
|
+
outdentDisabledTipKey?: string;
|
|
7866
|
+
}): MagicBarAction[];
|
|
7696
7867
|
|
|
7697
7868
|
/**
|
|
7698
|
-
*
|
|
7869
|
+
* Normalise a label / query for comparison: case-folded and stripped of combining marks, so a
|
|
7870
|
+
* search for `resume` finds `Résumé` and an Arabic query matches regardless of harakat.
|
|
7699
7871
|
*
|
|
7700
|
-
*
|
|
7701
|
-
* (`
|
|
7702
|
-
*
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
|
|
7872
|
+
* `NFD` + strip `\p{M}` rather than a hand-rolled accent table: the table approach covers Latin-1
|
|
7873
|
+
* and silently fails on every other script this platform ships (`ar`, `ur`), which is precisely the
|
|
7874
|
+
* locale pair where a user is most likely to type an unmarked form.
|
|
7875
|
+
*/
|
|
7876
|
+
declare function normalizeGanttSearchText(value: string): string;
|
|
7877
|
+
/**
|
|
7878
|
+
* Filter a Gantt row set to the rows a query is "about", **preserving tree context**.
|
|
7706
7879
|
*
|
|
7707
|
-
*
|
|
7708
|
-
*
|
|
7709
|
-
* `{appId}` is just a *priority hint* that bumps that lookup to the top of
|
|
7710
|
-
* the entity picker when the app is live. See {@link LookupRegistration.scope}
|
|
7711
|
-
* for the rationale.
|
|
7880
|
+
* A flat `rows.filter(matches)` is the obvious implementation and it is wrong here for two
|
|
7881
|
+
* independent reasons, both of which change what the user sees rather than merely how it looks:
|
|
7712
7882
|
*
|
|
7713
|
-
*
|
|
7714
|
-
* `
|
|
7715
|
-
*
|
|
7883
|
+
* 1. **A matching child whose parent is filtered out becomes a root.** `flattenRows` treats an
|
|
7884
|
+
* unknown `parentId` as a root, so a task matching "deploy" would jump to depth 0 and lose the
|
|
7885
|
+
* milestone that gives it meaning. The user asked to find a row, not to re-parent it.
|
|
7886
|
+
* 2. **A matching parent whose children are filtered out stops being a group.** Its chevron
|
|
7887
|
+
* disappears and its derived span collapses to its own dates — so searching for a milestone
|
|
7888
|
+
* silently changes the bar the chart draws for it.
|
|
7889
|
+
*
|
|
7890
|
+
* So the kept set is the **closure** of the matches over both directions of the tree: every match,
|
|
7891
|
+
* every ancestor of a match (context above), and every descendant of a match (context below).
|
|
7892
|
+
* Searching a milestone's name shows that milestone with its whole task list intact; searching a
|
|
7893
|
+
* task's name shows the task under its own milestone.
|
|
7894
|
+
*
|
|
7895
|
+
* Order is preserved — this is a filter, never a re-sort. An empty / whitespace query returns the
|
|
7896
|
+
* input array by reference, so a non-searching chart pays nothing and its `computed` never
|
|
7897
|
+
* invalidates on identity alone.
|
|
7716
7898
|
*/
|
|
7717
|
-
declare
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
|
|
7734
|
-
|
|
7735
|
-
|
|
7736
|
-
|
|
7737
|
-
|
|
7738
|
-
|
|
7739
|
-
|
|
7740
|
-
|
|
7741
|
-
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
|
|
7747
|
-
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
|
|
7752
|
-
|
|
7753
|
-
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
|
|
7773
|
-
*
|
|
7774
|
-
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
|
|
7786
|
-
|
|
7787
|
-
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
|
|
7899
|
+
declare function filterGanttRows(rows: readonly GanttRow[], query: string): readonly GanttRow[];
|
|
7900
|
+
|
|
7901
|
+
/**
|
|
7902
|
+
* Apply a {@link GanttRowReorder} to a plain `GanttRow[]`, returning a new array.
|
|
7903
|
+
*
|
|
7904
|
+
* Optional: a consumer that persists to a server and re-reads does not need it. It exists for the
|
|
7905
|
+
* two cases that do — an optimistic update while the write is in flight, and an app whose row
|
|
7906
|
+
* order is client-side only — because the fiddly part is not the parent change, it is keeping the
|
|
7907
|
+
* moved row's DESCENDANTS with it and landing the block after the previous sibling's whole
|
|
7908
|
+
* subtree rather than immediately after that sibling's own row.
|
|
7909
|
+
*
|
|
7910
|
+
* The moved row's `parentId` is rewritten to the move's parent; every other row is untouched, so a
|
|
7911
|
+
* consumer's extra fields survive.
|
|
7912
|
+
*/
|
|
7913
|
+
declare function applyGanttRowReorder(rows: readonly GanttRow[], move: GanttRowReorder): GanttRow[];
|
|
7914
|
+
|
|
7915
|
+
/** The 14 rendered field kinds. Drives the control the renderer picks. */
|
|
7916
|
+
type FlyFormQuestionType = 'Text' | 'MultilineText' | 'Number' | 'Email' | 'Date' | 'DateTime' | 'Boolean' | 'SingleSelect' | 'MultipleSelect' | 'RadioButton' | 'Country' | 'File' | 'MultiFile' | 'Image';
|
|
7917
|
+
/**
|
|
7918
|
+
* A selectable option on a choice field (SingleSelect / MultipleSelect /
|
|
7919
|
+
* RadioButton). `linkedQuestionIds` drive conditional branching: selecting this
|
|
7920
|
+
* option reveals those (branch-target) fields. `score` is author-only and is only
|
|
7921
|
+
* surfaced to the viewer when the host opts in via `[showScore]` (a scorecard);
|
|
7922
|
+
* a respondent-facing form leaves `showScore` false and never renders it.
|
|
7923
|
+
*/
|
|
7924
|
+
interface FlyFormOption {
|
|
7925
|
+
id: string;
|
|
7926
|
+
label: string;
|
|
7927
|
+
score?: number;
|
|
7928
|
+
linkedQuestionIds?: string[];
|
|
7929
|
+
}
|
|
7930
|
+
/** Per-type constraints/affordances an author can attach to a field. */
|
|
7931
|
+
interface FlyFormFieldOptions {
|
|
7932
|
+
minLength?: number;
|
|
7933
|
+
maxLength?: number;
|
|
7934
|
+
numericMin?: number;
|
|
7935
|
+
numericMax?: number;
|
|
7936
|
+
rows?: number;
|
|
7937
|
+
maxFileSizeMb?: number;
|
|
7938
|
+
maxFileCount?: number;
|
|
7939
|
+
allowedExtensions?: string[];
|
|
7940
|
+
hasSearch?: boolean;
|
|
7941
|
+
}
|
|
7942
|
+
/**
|
|
7943
|
+
* A single form field. `isBranchTarget` fields start hidden. `sectionId` /
|
|
7944
|
+
* `criteriaGroup` are additive grouping hints a scorecard uses; they are ignored
|
|
7945
|
+
* by the respondent-facing survey path, so binding them changes nothing there.
|
|
7946
|
+
*/
|
|
7947
|
+
interface FlyFormQuestion {
|
|
7948
|
+
id: string;
|
|
7949
|
+
text: string;
|
|
7950
|
+
description?: string;
|
|
7951
|
+
type: FlyFormQuestionType;
|
|
7952
|
+
required: boolean;
|
|
7953
|
+
isBranchTarget: boolean;
|
|
7954
|
+
/** Additive: an author-hidden field. `false` excludes it from the visible set (and thus from
|
|
7955
|
+
* required-enforcement); omitted / `true` renders as normal. Mirrors the backend `IsVisible`. */
|
|
7956
|
+
isVisible?: boolean;
|
|
7957
|
+
fieldOptions?: FlyFormFieldOptions;
|
|
7958
|
+
options: FlyFormOption[];
|
|
7959
|
+
/** Additive: groups fields into a visual section (scorecard). Ignored by surveys. */
|
|
7960
|
+
sectionId?: string;
|
|
7961
|
+
/** Additive: labels the weighted-criteria group a scored field belongs to. Ignored by surveys. */
|
|
7962
|
+
criteriaGroup?: string;
|
|
7963
|
+
}
|
|
7964
|
+
/** A full form definition — the top-level `[definition]` binding. */
|
|
7965
|
+
interface FlyFormDefinition {
|
|
7966
|
+
title: string;
|
|
7967
|
+
description?: string;
|
|
7968
|
+
declaration?: string;
|
|
7969
|
+
questions: FlyFormQuestion[];
|
|
7970
|
+
}
|
|
7971
|
+
/** How an opted-in `[showScore]` host renders a choice option's points. */
|
|
7972
|
+
type FlyFormScoreDisplay = 'inline' | 'badge';
|
|
7973
|
+
/**
|
|
7974
|
+
* The polymorphic answer payload for one field. Only the field(s) relevant to the
|
|
7975
|
+
* type are populated:
|
|
7976
|
+
* - text: Text / MultilineText / Email
|
|
7977
|
+
* - number: Number
|
|
7978
|
+
* - dateValue: Date / DateTime (raw `<input>` value string)
|
|
7979
|
+
* - boolValue: Boolean
|
|
7980
|
+
* - selectedOptionIds: SingleSelect / MultipleSelect / RadioButton / Country
|
|
7981
|
+
* - fileIds: File / MultiFile / Image (filled by the host after upload; this
|
|
7982
|
+
* component emits it empty and surfaces the raw selection via `fileSelected`)
|
|
7983
|
+
*/
|
|
7984
|
+
interface FlyFormAnswerValue {
|
|
7985
|
+
text?: string;
|
|
7986
|
+
number?: number;
|
|
7987
|
+
dateValue?: string;
|
|
7988
|
+
boolValue?: boolean;
|
|
7989
|
+
selectedOptionIds?: string[];
|
|
7990
|
+
fileIds?: string[];
|
|
7991
|
+
}
|
|
7992
|
+
/** One field's answer — the unit emitted by `answersChange` / `submit`. */
|
|
7993
|
+
interface FlyFormAnswer {
|
|
7994
|
+
questionId: string;
|
|
7995
|
+
value: FlyFormAnswerValue;
|
|
7996
|
+
}
|
|
7997
|
+
/**
|
|
7998
|
+
* Raw file selection surfaced by File / MultiFile / Image fields. The host wires
|
|
7999
|
+
* this to its own upload API and, once ids are known, feeds them back via the
|
|
8000
|
+
* `[answers]` prefill (`fileIds`). The DS component never touches an upload endpoint.
|
|
8001
|
+
*/
|
|
8002
|
+
interface FlyFileSelection {
|
|
8003
|
+
questionId: string;
|
|
8004
|
+
files: File[];
|
|
7795
8005
|
}
|
|
7796
8006
|
|
|
8007
|
+
/** A render segment: either an ungrouped field (`group === null`) or a titled `criteriaGroup` section.
|
|
8008
|
+
* `index` is the field's running position across the whole form (drives unique element ids). */
|
|
8009
|
+
interface FlyFormFieldGroup {
|
|
8010
|
+
group: string | null;
|
|
8011
|
+
items: {
|
|
8012
|
+
q: FlyFormQuestion;
|
|
8013
|
+
index: number;
|
|
8014
|
+
}[];
|
|
8015
|
+
}
|
|
7797
8016
|
/**
|
|
7798
|
-
*
|
|
7799
|
-
* items, keyed by `kind` and `appId`.
|
|
8017
|
+
* **`fly-dynamic-form`** — the design-system data-contract-driven form renderer.
|
|
7800
8018
|
*
|
|
7801
|
-
*
|
|
7802
|
-
*
|
|
7803
|
-
*
|
|
8019
|
+
* Renders a {@link FlyFormDefinition} (14 field types) into an accessible,
|
|
8020
|
+
* theme-aware form, owning all the fiddly behaviour a form needs: conditional
|
|
8021
|
+
* **branching** (options reveal branch-target fields), per-visible-field
|
|
8022
|
+
* **required validation**, a **declaration** acceptance gate, and a **readonly**
|
|
8023
|
+
* replay mode. It is a platform surface — zero coupling to any specific app, and
|
|
8024
|
+
* (deliberately) no coupling to an upload API: File / Image / MultiFile fields
|
|
8025
|
+
* surface the raw selection via {@link fileSelected} and emit `fileIds` empty; the
|
|
8026
|
+
* host wires the upload and feeds ids back through the `[answers]` prefill.
|
|
7804
8027
|
*
|
|
7805
|
-
*
|
|
7806
|
-
*
|
|
8028
|
+
* The historical **`fly-survey-form`** selector is retained on this same component
|
|
8029
|
+
* (multi-selector), so every existing `<fly-survey-form>` binding keeps working
|
|
8030
|
+
* unchanged. Surveys never sets {@link showScore}, so its behaviour (never rendering
|
|
8031
|
+
* `option.score`) is identical. A scorecard host opts into score display with
|
|
8032
|
+
* `[showScore]="true"`.
|
|
7807
8033
|
*
|
|
7808
|
-
*
|
|
7809
|
-
*
|
|
8034
|
+
* i18n is self-sufficient through the `form.*` keys in `DS_BASELINE_LOCALES`
|
|
8035
|
+
* (en/ar/fr/ur), overridable by any consumer key of the same name. RTL works via
|
|
8036
|
+
* logical CSS. Styling uses DS theme tokens (`--surface-*`, `--label-*`,
|
|
8037
|
+
* `--separator`, `--fill-*`, `--accent`, `--system-*`) with light-neutral
|
|
8038
|
+
* fallbacks so it stays readable even in a consumer that hasn't mapped them.
|
|
8039
|
+
*
|
|
8040
|
+
* @example
|
|
8041
|
+
* ```html
|
|
8042
|
+
* <fly-dynamic-form
|
|
8043
|
+
* [definition]="def"
|
|
8044
|
+
* [answers]="prefill"
|
|
8045
|
+
* [showScore]="true"
|
|
8046
|
+
* (answersChange)="draft = $event"
|
|
8047
|
+
* (validityChange)="valid = $event"
|
|
8048
|
+
* (fileSelected)="upload($event)"
|
|
8049
|
+
* (submit)="persist($event)" />
|
|
8050
|
+
* ```
|
|
7810
8051
|
*/
|
|
7811
|
-
declare class
|
|
7812
|
-
private readonly
|
|
7813
|
-
/**
|
|
7814
|
-
|
|
8052
|
+
declare class FlyDynamicFormComponent implements OnInit {
|
|
8053
|
+
private readonly _i18n;
|
|
8054
|
+
/** The form to render. */
|
|
8055
|
+
readonly definition: _angular_core.InputSignal<FlyFormDefinition>;
|
|
8056
|
+
/** Replay mode — every control is disabled and no validation errors / submit show.
|
|
8057
|
+
* Aliased to `[readonly]` (the public binding); the class member avoids shadowing
|
|
8058
|
+
* the TypeScript `readonly` keyword. */
|
|
8059
|
+
readonly isReadonly: _angular_core.InputSignal<boolean>;
|
|
8060
|
+
/** Hides the submit button while leaving every control interactive — the author's
|
|
8061
|
+
* pre-publish PREVIEW, which must let you open dropdowns and try the form out but has
|
|
8062
|
+
* nothing to submit to. Distinct from `readonly`, which disables the controls outright
|
|
8063
|
+
* (a submission replay). A host that hides submit should not bind `(submit)`. */
|
|
8064
|
+
readonly hideSubmit: _angular_core.InputSignal<boolean>;
|
|
8065
|
+
/** Prefill answers (e.g. a saved draft or a completed response). Answers for
|
|
8066
|
+
* currently-hidden branch targets are ignored. */
|
|
8067
|
+
readonly answers: _angular_core.InputSignal<readonly FlyFormAnswer[]>;
|
|
8068
|
+
/** Additive, opt-in: render each choice option's `score` (a weighted scorecard).
|
|
8069
|
+
* Defaults false so the respondent-facing survey path never leaks the answer key. */
|
|
8070
|
+
readonly showScore: _angular_core.InputSignal<boolean>;
|
|
8071
|
+
/** How an opted-in score is rendered next to an option (`badge` chip or `inline` text). */
|
|
8072
|
+
readonly scoreDisplay: _angular_core.InputSignal<FlyFormScoreDisplay>;
|
|
8073
|
+
/** The full visible answer set on every change. */
|
|
8074
|
+
readonly answersChange: _angular_core.OutputEmitterRef<FlyFormAnswer[]>;
|
|
8075
|
+
/** Required-field validity on every change (does NOT include the declaration gate). */
|
|
8076
|
+
readonly validityChange: _angular_core.OutputEmitterRef<boolean>;
|
|
8077
|
+
/** Fires only when the form is valid AND (if a declaration is set) accepted. */
|
|
8078
|
+
readonly submit: _angular_core.OutputEmitterRef<FlyFormAnswer[]>;
|
|
8079
|
+
/** Raw file selection for a File / MultiFile / Image field — the host uploads
|
|
8080
|
+
* and feeds the resulting ids back via `[answers]`. */
|
|
8081
|
+
readonly fileSelected: _angular_core.OutputEmitterRef<FlyFileSelection>;
|
|
8082
|
+
private readonly _base;
|
|
8083
|
+
/** questionId → answer value. Only ever contains VISIBLE, non-empty answers. */
|
|
8084
|
+
private readonly _values;
|
|
8085
|
+
/** questionId → locally-picked File[] (transient, pre-upload). Never emitted as ids. */
|
|
8086
|
+
private readonly _fileSelections;
|
|
8087
|
+
private readonly _declarationAccepted;
|
|
8088
|
+
private readonly _submitAttempted;
|
|
8089
|
+
/** questionIds the user has interacted with — gates when a required error shows. */
|
|
8090
|
+
private readonly _interacted;
|
|
8091
|
+
/** Per-field local file-validation error message (already localized). */
|
|
8092
|
+
private readonly _fileErrors;
|
|
8093
|
+
private readonly _countryOptions;
|
|
8094
|
+
constructor();
|
|
8095
|
+
ngOnInit(): void;
|
|
8096
|
+
/** The set of field ids currently shown (base fields + revealed branch targets). */
|
|
8097
|
+
readonly visibleQuestionIds: _angular_core.Signal<Set<string>>;
|
|
8098
|
+
/** Definition fields filtered to the visible set, in definition order. */
|
|
8099
|
+
readonly visibleQuestions: _angular_core.Signal<FlyFormQuestion[]>;
|
|
7815
8100
|
/**
|
|
7816
|
-
*
|
|
7817
|
-
*
|
|
7818
|
-
* `
|
|
7819
|
-
*
|
|
7820
|
-
* Returns `null` when no renderer is registered; the host falls back to a generic
|
|
7821
|
-
* `plainTextFallback` chip.
|
|
8101
|
+
* The visible fields laid out in render order, segmented by `criteriaGroup`: fields that share a
|
|
8102
|
+
* (non-empty) group render together inside one titled section (a scorecard's weighted-criteria
|
|
8103
|
+
* grouping); a field with no `criteriaGroup` is its own ungrouped segment and renders flat, exactly
|
|
8104
|
+
* as before. Each item keeps its running index across the whole form so element ids stay unique.
|
|
7822
8105
|
*/
|
|
7823
|
-
|
|
8106
|
+
readonly groupedQuestions: _angular_core.Signal<FlyFormFieldGroup[]>;
|
|
8107
|
+
readonly declarationRequired: _angular_core.Signal<boolean>;
|
|
8108
|
+
/** Required-field validity (declaration NOT included — see {@link canSubmit}). */
|
|
8109
|
+
readonly isValid: _angular_core.Signal<boolean>;
|
|
8110
|
+
/** Whether `(submit)` may fire: valid required set AND declaration accepted (if any). */
|
|
8111
|
+
readonly canSubmit: _angular_core.Signal<boolean>;
|
|
8112
|
+
readonly declarationAccepted: _angular_core.Signal<boolean>;
|
|
8113
|
+
fieldId(index: number): string;
|
|
8114
|
+
descId(index: number): string;
|
|
8115
|
+
errId(index: number): string;
|
|
8116
|
+
describedBy(q: FlyFormQuestion, index: number): string | null;
|
|
8117
|
+
isChoice(type: FlyFormQuestionType): boolean;
|
|
8118
|
+
isFile(type: FlyFormQuestionType): boolean;
|
|
8119
|
+
/** Types rendered as a native input group inside `<fieldset><legend>`. */
|
|
8120
|
+
isFieldset(type: FlyFormQuestionType): boolean;
|
|
8121
|
+
isCountry(type: FlyFormQuestionType): boolean;
|
|
7824
8122
|
/**
|
|
7825
|
-
*
|
|
7826
|
-
* replaces the prior entry; the disposal handle for the prior registration becomes
|
|
7827
|
-
* a no-op.
|
|
8123
|
+
* Types rendered with the DS `<fly-select>` (labelled via `ariaLabel`).
|
|
7828
8124
|
*
|
|
7829
|
-
*
|
|
7830
|
-
*
|
|
8125
|
+
* Every select-like type now qualifies. `hasSearch` used to gate the CONTROL, which left a plain
|
|
8126
|
+
* SingleSelect on a native `<select>` — an OS-chrome popup that cannot be themed (it paints its
|
|
8127
|
+
* rows with the control's translucent background over a white backing, so the list rendered
|
|
8128
|
+
* white-on-white on the dark shell). `hasSearch` now only decides whether the DS panel carries a
|
|
8129
|
+
* search box; see {@link selectSearchable}.
|
|
7831
8130
|
*/
|
|
7832
|
-
|
|
8131
|
+
usesDsSelect(q: FlyFormQuestion): boolean;
|
|
8132
|
+
/** Search box: always for Country (the list is ~200 long), else only when the author asked. */
|
|
8133
|
+
selectSearchable(q: FlyFormQuestion): boolean;
|
|
7833
8134
|
/**
|
|
7834
|
-
*
|
|
7835
|
-
*
|
|
7836
|
-
*
|
|
8135
|
+
* The points to show for a choice option, or null to render nothing. Non-null only when the host
|
|
8136
|
+
* opted in via `[showScore]` and the option actually carries a score — this is the sole gate that
|
|
8137
|
+
* keeps a respondent-facing survey (which never binds `showScore`) from leaking the answer key.
|
|
7837
8138
|
*/
|
|
7838
|
-
|
|
8139
|
+
optionScore(opt: FlyFormOption): number | null;
|
|
8140
|
+
/** Whether a required error should be visible for a field right now. */
|
|
8141
|
+
showError(q: FlyFormQuestion): boolean;
|
|
8142
|
+
fileError(q: FlyFormQuestion): string | null;
|
|
8143
|
+
textValue(q: FlyFormQuestion): string;
|
|
8144
|
+
numberValue(q: FlyFormQuestion): number | null;
|
|
8145
|
+
dateValue(q: FlyFormQuestion): string;
|
|
8146
|
+
boolValue(q: FlyFormQuestion): boolean | null;
|
|
8147
|
+
singleValue(q: FlyFormQuestion): string | null;
|
|
8148
|
+
isSelected(q: FlyFormQuestion, optionId: string): boolean;
|
|
8149
|
+
countryOptions(q: FlyFormQuestion): readonly FlySelectOption[];
|
|
8150
|
+
selectOptions(q: FlyFormQuestion): readonly FlySelectOption[];
|
|
8151
|
+
fileNames(q: FlyFormQuestion): string[];
|
|
8152
|
+
acceptFor(q: FlyFormQuestion): string;
|
|
8153
|
+
onText(q: FlyFormQuestion, value: string): void;
|
|
8154
|
+
onNumber(q: FlyFormQuestion, value: string): void;
|
|
8155
|
+
onDate(q: FlyFormQuestion, value: string): void;
|
|
8156
|
+
onBoolean(q: FlyFormQuestion, value: boolean): void;
|
|
8157
|
+
onSingleSelect(q: FlyFormQuestion, value: string | readonly string[] | null): void;
|
|
8158
|
+
onRadio(q: FlyFormQuestion, optionId: string): void;
|
|
8159
|
+
onMultiToggle(q: FlyFormQuestion, optionId: string, checked: boolean): void;
|
|
8160
|
+
onFiles(q: FlyFormQuestion, input: HTMLInputElement): void;
|
|
8161
|
+
onDeclarationToggle(checked: boolean): void;
|
|
8162
|
+
onSubmit(): void;
|
|
8163
|
+
private _touch;
|
|
8164
|
+
private _setFileError;
|
|
8165
|
+
private _mutate;
|
|
8166
|
+
private _emit;
|
|
8167
|
+
private _collectAnswers;
|
|
8168
|
+
private _isAnswered;
|
|
8169
|
+
private _isEmptyValue;
|
|
8170
|
+
private _selectedIds;
|
|
7839
8171
|
/**
|
|
7840
|
-
*
|
|
7841
|
-
*
|
|
7842
|
-
*
|
|
8172
|
+
* The set of visible field ids for a given answer map. Base (non-branch-target)
|
|
8173
|
+
* fields are always visible; a branch target becomes visible when a
|
|
8174
|
+
* currently-visible field has a selected option that links to it. Computed to a
|
|
8175
|
+
* fixpoint so chained reveals work, and cycle-safe: the visible set only grows and
|
|
8176
|
+
* iteration is capped at `questions.length` passes, so an A↔B link cycle terminates.
|
|
8177
|
+
*
|
|
8178
|
+
* This is the TypeScript twin of the backend Fly.Sdk.Forms `BranchResolver`
|
|
8179
|
+
* fixpoint — the two must stay in lockstep so server + client agree on which fields
|
|
8180
|
+
* are active.
|
|
7843
8181
|
*/
|
|
7844
|
-
|
|
7845
|
-
/**
|
|
7846
|
-
private
|
|
7847
|
-
|
|
7848
|
-
|
|
7849
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AgentDropRegistry, never>;
|
|
7850
|
-
static ɵprov: _angular_core.ɵɵInjectableDeclaration<AgentDropRegistry>;
|
|
8182
|
+
private _computeVisibleIds;
|
|
8183
|
+
/** Imperative localization for file-validation messages (the pipe covers view strings). */
|
|
8184
|
+
private _t;
|
|
8185
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlyDynamicFormComponent, never>;
|
|
8186
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyDynamicFormComponent, "fly-dynamic-form, fly-survey-form", never, { "definition": { "alias": "definition"; "required": true; "isSignal": true; }; "isReadonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "hideSubmit": { "alias": "hideSubmit"; "required": false; "isSignal": true; }; "answers": { "alias": "answers"; "required": false; "isSignal": true; }; "showScore": { "alias": "showScore"; "required": false; "isSignal": true; }; "scoreDisplay": { "alias": "scoreDisplay"; "required": false; "isSignal": true; }; }, { "answersChange": "answersChange"; "validityChange": "validityChange"; "submit": "submit"; "fileSelected": "fileSelected"; }, never, never, true, never>;
|
|
7851
8187
|
}
|
|
7852
8188
|
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
*/
|
|
7863
|
-
type
|
|
7864
|
-
/**
|
|
7865
|
-
|
|
7866
|
-
|
|
7867
|
-
*
|
|
7868
|
-
*
|
|
7869
|
-
*
|
|
7870
|
-
*
|
|
7871
|
-
*
|
|
7872
|
-
*/
|
|
7873
|
-
|
|
7874
|
-
|
|
7875
|
-
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
|
|
7880
|
-
|
|
7881
|
-
|
|
7882
|
-
|
|
7883
|
-
|
|
7884
|
-
|
|
7885
|
-
|
|
7886
|
-
|
|
7887
|
-
|
|
7888
|
-
|
|
7889
|
-
readonly originRect?: DOMRect;
|
|
7890
|
-
/** Optional HTML snippet rendered inside the flight ghost. Callers are
|
|
7891
|
-
* responsible for escaping untrusted text — the bus does not sanitise.
|
|
7892
|
-
* Defaults (when omitted) to a strong-wrapped escape of the payload's
|
|
7893
|
-
* `plainTextFallback` rendered by the panel host. */
|
|
7894
|
-
readonly originPreviewHtml?: string;
|
|
8189
|
+
interface FlyCountry {
|
|
8190
|
+
/** ISO 3166-1 alpha-2 code (uppercase), e.g. `AE`. */
|
|
8191
|
+
code: string;
|
|
8192
|
+
/** English display name. */
|
|
8193
|
+
name: string;
|
|
8194
|
+
}
|
|
8195
|
+
/** Frozen alpha-2 list, alphabetical by English name. */
|
|
8196
|
+
declare const FLY_COUNTRIES: readonly FlyCountry[];
|
|
8197
|
+
|
|
8198
|
+
/** Backend `CommentReportReason` enum — string-persisted, member names frozen. */
|
|
8199
|
+
type FlyCommentReportReason = 'Spam' | 'Harassment' | 'OffTopic' | 'Misinformation' | 'Inappropriate' | 'Other';
|
|
8200
|
+
/** Backend `CommentReportStatus` enum — string-persisted, member names frozen. */
|
|
8201
|
+
type FlyCommentReportStatus = 'Open' | 'UnderReview' | 'ActionTaken' | 'Dismissed';
|
|
8202
|
+
/**
|
|
8203
|
+
* One comment, at any depth. `isDeleted` comments render as a tombstone (the
|
|
8204
|
+
* host still supplies `body`-less structural fields so the reply subtree stays
|
|
8205
|
+
* navigable; the component never assumes `body` is present when `isDeleted`).
|
|
8206
|
+
* `canEdit` / `canDelete` / `canModerate` are pre-resolved by the host (Cerbos
|
|
8207
|
+
* decision or equivalent) — the component never evaluates authorization itself.
|
|
8208
|
+
*/
|
|
8209
|
+
interface FlyComment {
|
|
8210
|
+
id: string;
|
|
8211
|
+
authorUserId: string;
|
|
8212
|
+
authorDisplayName?: string;
|
|
8213
|
+
authorAvatarUrl?: string;
|
|
8214
|
+
parentCommentId?: string;
|
|
8215
|
+
depth: number;
|
|
8216
|
+
body: string;
|
|
8217
|
+
replyCount: number;
|
|
8218
|
+
isEdited: boolean;
|
|
8219
|
+
isDeleted: boolean;
|
|
8220
|
+
createdAt: string;
|
|
8221
|
+
updatedAt?: string;
|
|
8222
|
+
canEdit: boolean;
|
|
8223
|
+
canDelete: boolean;
|
|
8224
|
+
canModerate: boolean;
|
|
7895
8225
|
}
|
|
7896
8226
|
/**
|
|
7897
|
-
*
|
|
7898
|
-
*
|
|
7899
|
-
*
|
|
7900
|
-
*
|
|
8227
|
+
* A paged slice of comments at one nesting level — mirrors the service's
|
|
8228
|
+
* `GET .../comments?parentCommentId=&page=&pageSize=` shape. Every depth is
|
|
8229
|
+
* paged independently: the root page and each expanded parent's reply page are
|
|
8230
|
+
* separate {@link FlyCommentPage} instances tracked by the host.
|
|
7901
8231
|
*/
|
|
7902
|
-
|
|
7903
|
-
|
|
7904
|
-
|
|
8232
|
+
interface FlyCommentPage {
|
|
8233
|
+
items: FlyComment[];
|
|
8234
|
+
page: number;
|
|
8235
|
+
pageSize: number;
|
|
8236
|
+
total: number;
|
|
8237
|
+
hasMore: boolean;
|
|
8238
|
+
}
|
|
8239
|
+
/** `loadReplies` request — expand a collapsed reply subtree, one page at a time. */
|
|
8240
|
+
interface FlyCommentLoadRepliesRequest {
|
|
8241
|
+
parentCommentId: string;
|
|
8242
|
+
page: number;
|
|
8243
|
+
}
|
|
8244
|
+
/** `loadMore` request — next page at the root level (`parentCommentId` omitted) or under a parent. */
|
|
8245
|
+
interface FlyCommentLoadMoreRequest {
|
|
8246
|
+
parentCommentId?: string;
|
|
8247
|
+
page: number;
|
|
8248
|
+
}
|
|
8249
|
+
/** `submit` request — a new root comment (`parentCommentId` omitted) or a reply. */
|
|
8250
|
+
interface FlyCommentSubmitRequest {
|
|
8251
|
+
body: string;
|
|
8252
|
+
parentCommentId?: string;
|
|
8253
|
+
}
|
|
8254
|
+
/** `edit` request — author-only body edit of an existing comment. */
|
|
8255
|
+
interface FlyCommentEditRequest {
|
|
8256
|
+
commentId: string;
|
|
8257
|
+
body: string;
|
|
8258
|
+
}
|
|
8259
|
+
/** `delete` request — soft delete (tombstone), author or moderator. */
|
|
8260
|
+
interface FlyCommentDeleteRequest {
|
|
8261
|
+
commentId: string;
|
|
8262
|
+
}
|
|
8263
|
+
/** `report` request — typed reason + optional free-text detail. */
|
|
8264
|
+
interface FlyCommentReportRequest {
|
|
8265
|
+
commentId: string;
|
|
8266
|
+
reason: FlyCommentReportReason;
|
|
8267
|
+
detail?: string;
|
|
8268
|
+
}
|
|
8269
|
+
/** `lockToggle` request — moderator lock/unlock of the whole thread. */
|
|
8270
|
+
interface FlyCommentLockToggleRequest {
|
|
8271
|
+
locked: boolean;
|
|
7905
8272
|
}
|
|
7906
8273
|
|
|
7907
8274
|
/**
|
|
7908
|
-
*
|
|
8275
|
+
* **`fly-comment-thread`** — the design-system generic threaded-comments renderer.
|
|
7909
8276
|
*
|
|
7910
|
-
*
|
|
7911
|
-
*
|
|
7912
|
-
*
|
|
7913
|
-
*
|
|
7914
|
-
*
|
|
7915
|
-
*
|
|
8277
|
+
* Renders a {@link FlyCommentPage} (root comments) plus lazily-fetched nested
|
|
8278
|
+
* reply pages into an accessible, theme-aware thread: reply composer, inline
|
|
8279
|
+
* edit, soft-delete (tombstone render), typed report-with-reason dialog, and
|
|
8280
|
+
* moderator affordances (lock/unlock, delete-any). It is a platform surface —
|
|
8281
|
+
* transport-agnostic like `fly-survey-form` / `fly-dynamic-form`: this component
|
|
8282
|
+
* never calls an API. It only renders the pages the host hands it via
|
|
8283
|
+
* `[rootPage]` / `[repliesByParent]` and emits typed requests
|
|
8284
|
+
* (`loadReplies`/`loadMore`/`submit`/`edit`/`delete`/`report`/`lockToggle`) —
|
|
8285
|
+
* the host owns HTTP, optimistic-insert reconciliation, and any live-update
|
|
8286
|
+
* channel (SignalR, polling, …).
|
|
7916
8287
|
*
|
|
7917
|
-
*
|
|
7918
|
-
*
|
|
7919
|
-
*
|
|
8288
|
+
* Nested replies are fetched **lazily on expand** (`loadReplies`, never an
|
|
8289
|
+
* eager load-all) — the explicit fix for the legacy unpaged-children scale bug
|
|
8290
|
+
* — and each level pages independently via `loadMore`.
|
|
7920
8291
|
*
|
|
7921
|
-
*
|
|
7922
|
-
*
|
|
7923
|
-
*
|
|
8292
|
+
* The `comments` core app owns no user profile data, so `FlyComment` carries
|
|
8293
|
+
* `authorUserId` and an OPTIONAL `authorDisplayName`. Rather than make every host
|
|
8294
|
+
* map names in itself (and render GUIDs when it forgets), bind
|
|
8295
|
+
* `[resolveDisplayName]` to `FlyUserDirectoryService.label` — see
|
|
8296
|
+
* {@link FlyCommentThreadComponent.resolveDisplayName}. Still transport-agnostic:
|
|
8297
|
+
* the resolver is a function the host hands over, not a call this component makes.
|
|
8298
|
+
*
|
|
8299
|
+
* i18n is self-sufficient through the `comment.*` keys in `DS_BASELINE_LOCALES`
|
|
8300
|
+
* (en/ar/fr/ur), overridable by any consumer key of the same name. RTL works via
|
|
8301
|
+
* logical CSS. Styling uses DS theme tokens (`--surface-*`, `--label-*`,
|
|
8302
|
+
* `--separator`, `--fill-*`, `--accent`, `--system-*`) with light-neutral
|
|
8303
|
+
* fallbacks so it stays readable even in a consumer that hasn't mapped them.
|
|
8304
|
+
*
|
|
8305
|
+
* @example
|
|
8306
|
+
* ```html
|
|
8307
|
+
* <fly-comment-thread
|
|
8308
|
+
* [rootPage]="rootPage()"
|
|
8309
|
+
* [repliesByParent]="repliesByParent()"
|
|
8310
|
+
* [currentUserId]="me.id"
|
|
8311
|
+
* [resolveDisplayName]="directory.label"
|
|
8312
|
+
* [canModerateThread]="canModerate()"
|
|
8313
|
+
* [isLocked]="thread().isLocked"
|
|
8314
|
+
* (loadReplies)="onLoadReplies($event)"
|
|
8315
|
+
* (loadMore)="onLoadMore($event)"
|
|
8316
|
+
* (submit)="onSubmit($event)"
|
|
8317
|
+
* (edit)="onEdit($event)"
|
|
8318
|
+
* (delete)="onDelete($event)"
|
|
8319
|
+
* (report)="onReport($event)"
|
|
8320
|
+
* (lockToggle)="onLockToggle($event)" />
|
|
8321
|
+
* ```
|
|
7924
8322
|
*/
|
|
7925
|
-
declare class
|
|
7926
|
-
|
|
7927
|
-
|
|
7928
|
-
* actions dispatched AFTER they subscribe — late subscribers see nothing
|
|
7929
|
-
* retroactively. Use {@link lastAction} for the latest snapshot. */
|
|
7930
|
-
readonly actions$: Observable<AgentAction>;
|
|
7931
|
-
/** Most recent action — for DevTools, smoke tests, and late-subscriber
|
|
7932
|
-
* catch-up. Null until the first successful dispatch. */
|
|
7933
|
-
readonly lastAction: _angular_core.WritableSignal<AgentAction<unknown> | null>;
|
|
8323
|
+
declare class FlyCommentThreadComponent {
|
|
8324
|
+
/** The root-level comment page (accumulated across `loadMore` calls by the host). */
|
|
8325
|
+
readonly rootPage: _angular_core.InputSignal<FlyCommentPage>;
|
|
7934
8326
|
/**
|
|
7935
|
-
*
|
|
7936
|
-
*
|
|
7937
|
-
*
|
|
7938
|
-
*
|
|
7939
|
-
* a busy state on the originating control — e.g. a card swapping its
|
|
7940
|
-
* sparkle icon for a spinner while the agent panel mints the optimistic
|
|
7941
|
-
* thread and starts the request. Identity check (`bus.inFlight() === act`)
|
|
7942
|
-
* is the panel-side contract; dispatchers usually project to a stable id
|
|
7943
|
-
* inside the payload (e.g. <c>reportId</c>) to scope busy-state visually.
|
|
7944
|
-
*
|
|
7945
|
-
* If multiple dispatches race, the latest wins — the prior in-flight
|
|
7946
|
-
* action is dropped on the floor here (the panel may still handle it,
|
|
7947
|
-
* but the dispatcher's busy indicator follows the newer action). Apps
|
|
7948
|
-
* that need stricter single-flight semantics should guard at the call
|
|
7949
|
-
* site (the agent-panel's <c>_pendingTempThreadId</c> already does so
|
|
7950
|
-
* for the explain verb).
|
|
8327
|
+
* Accumulated reply page per expanded parent (keyed by `parentCommentId`), also
|
|
8328
|
+
* accumulated across `loadMore` calls by the host. Additive to the frozen
|
|
8329
|
+
* contract's `rootPage` input — required because a lazily-nested tree has no
|
|
8330
|
+
* other channel to carry fetched reply data back into the component.
|
|
7951
8331
|
*/
|
|
7952
|
-
readonly
|
|
8332
|
+
readonly repliesByParent: _angular_core.InputSignal<Readonly<Record<string, FlyCommentPage>>>;
|
|
8333
|
+
/** Current sort order label (host owns re-fetch on {@link sortChange}; purely descriptive here otherwise). */
|
|
8334
|
+
readonly sort: _angular_core.InputSignal<"newest" | "oldest">;
|
|
8335
|
+
/** Locked threads disable the composer (root + reply) entirely, for every user. */
|
|
8336
|
+
readonly isLocked: _angular_core.InputSignal<boolean>;
|
|
8337
|
+
/** The signed-in user's id — gates the "report" affordance (can't report your own comment). */
|
|
8338
|
+
readonly currentUserId: _angular_core.InputSignal<string | null>;
|
|
8339
|
+
/** Replay / read-only mode — hides composer, reply, edit, delete, report, and lock affordances.
|
|
8340
|
+
* Aliased to `[readonly]` (the public binding); the class member avoids shadowing the
|
|
8341
|
+
* TypeScript `readonly` keyword. */
|
|
8342
|
+
readonly isReadonly: _angular_core.InputSignal<boolean>;
|
|
8343
|
+
/** Thread-scoped moderator permission (lock/unlock). Additive — distinct from the
|
|
8344
|
+
* per-comment `canModerate` flag, which gates delete-any on that specific comment. */
|
|
8345
|
+
readonly canModerateThread: _angular_core.InputSignal<boolean>;
|
|
7953
8346
|
/**
|
|
7954
|
-
*
|
|
8347
|
+
* Optional id→name lookup, for the common case where the backend DTO carries only
|
|
8348
|
+
* `authorUserId`. The `comments` core app owns no user profile data, so without
|
|
8349
|
+
* this every host had to map display names into `authorDisplayName` itself — and
|
|
8350
|
+
* a host that forgot rendered raw GUIDs at the reader.
|
|
7955
8351
|
*
|
|
7956
|
-
*
|
|
7957
|
-
*
|
|
7958
|
-
*
|
|
7959
|
-
*
|
|
7960
|
-
* version, invalid kind). The error message carries the field path
|
|
7961
|
-
* so the caller can fix the offending field.
|
|
8352
|
+
* Bind `FlyUserDirectoryService.label` (a signal-backed read-through cache that
|
|
8353
|
+
* resolves on demand and batches). Because the component reads it during render,
|
|
8354
|
+
* the name appears by itself once the lookup lands — the host keeps a plain
|
|
8355
|
+
* page signal, with no `computed` derivation and no priming.
|
|
7962
8356
|
*
|
|
7963
|
-
*
|
|
7964
|
-
*
|
|
7965
|
-
*
|
|
7966
|
-
|
|
7967
|
-
dispatch<T>(action: AgentAction<T>): void;
|
|
7968
|
-
/**
|
|
7969
|
-
* Subscriber contract: call after the handler for {@link inFlight}
|
|
7970
|
-
* completes (success or fail). Only clears {@link inFlight} if it still
|
|
7971
|
-
* points at the passed action — a no-op when a later dispatch already
|
|
7972
|
-
* superseded it. Pass the same action reference the subscriber received
|
|
7973
|
-
* from {@link actions$}; identity is the gate.
|
|
8357
|
+
* The component still never calls an API: this is a function the HOST supplies,
|
|
8358
|
+
* exactly like `fly-entity-lookup`'s `LOOKUP_APP_NAME_RESOLVER`. Absent (or
|
|
8359
|
+
* returning `null`), rendering falls back as before. See {@link authorLabel} for
|
|
8360
|
+
* the resolution order.
|
|
7974
8361
|
*/
|
|
7975
|
-
|
|
8362
|
+
readonly resolveDisplayName: _angular_core.InputSignal<((userId: string) => string | null) | null>;
|
|
8363
|
+
/** Expand a collapsed reply subtree — always page 1 of that parent. */
|
|
8364
|
+
readonly loadReplies: _angular_core.OutputEmitterRef<{
|
|
8365
|
+
parentCommentId: string;
|
|
8366
|
+
page: number;
|
|
8367
|
+
}>;
|
|
8368
|
+
/** Fetch the next page at a level: root when `parentCommentId` is omitted, else that parent's replies. */
|
|
8369
|
+
readonly loadMore: _angular_core.OutputEmitterRef<{
|
|
8370
|
+
parentCommentId?: string;
|
|
8371
|
+
page: number;
|
|
8372
|
+
}>;
|
|
8373
|
+
/** A new root comment (`parentCommentId` omitted) or reply. */
|
|
8374
|
+
readonly submit: _angular_core.OutputEmitterRef<{
|
|
8375
|
+
body: string;
|
|
8376
|
+
parentCommentId?: string;
|
|
8377
|
+
}>;
|
|
8378
|
+
/** Author-only body edit of an existing comment. */
|
|
8379
|
+
readonly edit: _angular_core.OutputEmitterRef<{
|
|
8380
|
+
commentId: string;
|
|
8381
|
+
body: string;
|
|
8382
|
+
}>;
|
|
8383
|
+
/** Soft delete (tombstone) — author's own comment, or any comment for a moderator. */
|
|
8384
|
+
readonly delete: _angular_core.OutputEmitterRef<{
|
|
8385
|
+
commentId: string;
|
|
8386
|
+
}>;
|
|
8387
|
+
/** Typed report submission. */
|
|
8388
|
+
readonly report: _angular_core.OutputEmitterRef<{
|
|
8389
|
+
commentId: string;
|
|
8390
|
+
reason: FlyCommentReportReason;
|
|
8391
|
+
detail?: string;
|
|
8392
|
+
}>;
|
|
8393
|
+
/** Moderator lock/unlock of the whole thread. */
|
|
8394
|
+
readonly lockToggle: _angular_core.OutputEmitterRef<{
|
|
8395
|
+
locked: boolean;
|
|
8396
|
+
}>;
|
|
8397
|
+
/** Additive: a sort-order pick from the header control — the host re-fetches page 1 in that order. */
|
|
8398
|
+
readonly sortChange: _angular_core.OutputEmitterRef<"newest" | "oldest">;
|
|
8399
|
+
private readonly _base;
|
|
8400
|
+
readonly reportReasons: readonly FlyCommentReportReason[];
|
|
8401
|
+
/** commentIds whose reply subtree is currently expanded/visible. */
|
|
8402
|
+
private readonly _expanded;
|
|
8403
|
+
/** Composer draft text, keyed by parentCommentId (root uses {@link ROOT_DRAFT_KEY}). */
|
|
8404
|
+
private readonly _drafts;
|
|
8405
|
+
/** commentIds whose reply composer box is currently open (distinct from `_expanded`, which toggles the read view). */
|
|
8406
|
+
private readonly _replyBoxOpen;
|
|
8407
|
+
private readonly _editingId;
|
|
8408
|
+
private readonly _editDraft;
|
|
8409
|
+
private readonly _confirmingDeleteId;
|
|
8410
|
+
private readonly _reportingId;
|
|
8411
|
+
private readonly _reportReason;
|
|
8412
|
+
private readonly _reportDetail;
|
|
8413
|
+
readonly rootDraft: _angular_core.Signal<string>;
|
|
8414
|
+
readonly editingId: _angular_core.Signal<string | null>;
|
|
8415
|
+
readonly confirmingDeleteId: _angular_core.Signal<string | null>;
|
|
8416
|
+
readonly reportingId: _angular_core.Signal<string | null>;
|
|
8417
|
+
readonly reportReason: _angular_core.Signal<FlyCommentReportReason | null>;
|
|
8418
|
+
readonly reportDetail: _angular_core.Signal<string>;
|
|
8419
|
+
fieldId(suffix: string): string;
|
|
8420
|
+
isExpanded(commentId: string): boolean;
|
|
8421
|
+
isReplyBoxOpen(commentId: string): boolean;
|
|
8422
|
+
repliesFor(commentId: string): FlyCommentPage | undefined;
|
|
8423
|
+
replyDraft(commentId: string): string;
|
|
8424
|
+
isOwn(comment: FlyComment): boolean;
|
|
7976
8425
|
/**
|
|
7977
|
-
*
|
|
7978
|
-
*
|
|
7979
|
-
*
|
|
7980
|
-
*
|
|
7981
|
-
* lets the UI distinguish "handler finished" from "user said no" in
|
|
7982
|
-
* telemetry / logs without sniffing a "reason" parameter.
|
|
8426
|
+
* The name to render for a comment's author. Resolution order:
|
|
8427
|
+
* explicit `authorDisplayName` (a host that already knows the name, or a
|
|
8428
|
+
* backend that returns one, always wins) → {@link resolveDisplayName} →
|
|
8429
|
+
* the raw `authorUserId`.
|
|
7983
8430
|
*
|
|
7984
|
-
*
|
|
7985
|
-
*
|
|
8431
|
+
* The raw id remains the last resort rather than a placeholder: it is stable,
|
|
8432
|
+
* unique, and lets a reader correlate two comments by the same author even
|
|
8433
|
+
* when the directory is unreachable.
|
|
7986
8434
|
*/
|
|
7987
|
-
|
|
7988
|
-
|
|
7989
|
-
|
|
8435
|
+
authorLabel(comment: FlyComment): string;
|
|
8436
|
+
/** First character of {@link authorLabel}, for the avatar-initials fallback. */
|
|
8437
|
+
authorInitial(comment: FlyComment): string;
|
|
8438
|
+
canReport(comment: FlyComment): boolean;
|
|
8439
|
+
canReply(): boolean;
|
|
8440
|
+
canDeleteComment(comment: FlyComment): boolean;
|
|
8441
|
+
canEditComment(comment: FlyComment): boolean;
|
|
8442
|
+
formatDate(iso: string): string;
|
|
8443
|
+
onRootDraftChange(value: string): void;
|
|
8444
|
+
submitRoot(): void;
|
|
8445
|
+
toggleReplies(comment: FlyComment): void;
|
|
8446
|
+
private _expand;
|
|
8447
|
+
loadMoreRoot(): void;
|
|
8448
|
+
loadMoreReplies(parentId: string): void;
|
|
8449
|
+
openReplyBox(commentId: string): void;
|
|
8450
|
+
closeReplyBox(commentId: string): void;
|
|
8451
|
+
onReplyDraftChange(commentId: string, value: string): void;
|
|
8452
|
+
submitReply(commentId: string): void;
|
|
8453
|
+
startEdit(comment: FlyComment): void;
|
|
8454
|
+
onEditDraftChange(value: string): void;
|
|
8455
|
+
saveEdit(comment: FlyComment): void;
|
|
8456
|
+
cancelEdit(): void;
|
|
8457
|
+
requestDelete(comment: FlyComment): void;
|
|
8458
|
+
confirmDelete(comment: FlyComment): void;
|
|
8459
|
+
cancelDelete(): void;
|
|
8460
|
+
openReport(comment: FlyComment): void;
|
|
8461
|
+
onReportReasonChange(reason: FlyCommentReportReason): void;
|
|
8462
|
+
onReportDetailChange(value: string): void;
|
|
8463
|
+
submitReport(): void;
|
|
8464
|
+
closeReport(): void;
|
|
8465
|
+
/** Space would otherwise scroll the page while the backdrop (role="button") is focused. */
|
|
8466
|
+
onOverlayBackdropSpace(event: Event): void;
|
|
8467
|
+
toggleLock(): void;
|
|
8468
|
+
onSortPick(next: 'newest' | 'oldest'): void;
|
|
8469
|
+
private _setDraft;
|
|
8470
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlyCommentThreadComponent, never>;
|
|
8471
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyCommentThreadComponent, "fly-comment-thread", never, { "rootPage": { "alias": "rootPage"; "required": true; "isSignal": true; }; "repliesByParent": { "alias": "repliesByParent"; "required": false; "isSignal": true; }; "sort": { "alias": "sort"; "required": false; "isSignal": true; }; "isLocked": { "alias": "isLocked"; "required": false; "isSignal": true; }; "currentUserId": { "alias": "currentUserId"; "required": false; "isSignal": true; }; "isReadonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "canModerateThread": { "alias": "canModerateThread"; "required": false; "isSignal": true; }; "resolveDisplayName": { "alias": "resolveDisplayName"; "required": false; "isSignal": true; }; }, { "loadReplies": "loadReplies"; "loadMore": "loadMore"; "submit": "submit"; "edit": "edit"; "delete": "delete"; "report": "report"; "lockToggle": "lockToggle"; "sortChange": "sortChange"; }, never, never, true, never>;
|
|
7990
8472
|
}
|
|
7991
8473
|
|
|
7992
8474
|
/**
|
|
7993
|
-
*
|
|
7994
|
-
*
|
|
7995
|
-
*
|
|
7996
|
-
* no CSS transitions racing layout. Honours `prefers-reduced-motion`: the
|
|
7997
|
-
* ghost is appended then removed without animating when the user asked for
|
|
7998
|
-
* less motion (so DOM side-effects stay consistent).
|
|
7999
|
-
*
|
|
8000
|
-
* Lifecycle:
|
|
8001
|
-
* 1. The agent panel calls {@link registerTarget} in `ngAfterViewInit`
|
|
8002
|
-
* with its header element.
|
|
8003
|
-
* 2. A source app dispatches an `AgentAction` carrying an `originRect`
|
|
8004
|
-
* from `getBoundingClientRect()` on the click target.
|
|
8005
|
-
* 3. The bus subscriber calls {@link flyInto} with that rect.
|
|
8006
|
-
* 4. The animator creates a fixed-position ghost at the origin, animates
|
|
8007
|
-
* transform + opacity toward the registered target's rect, then
|
|
8008
|
-
* removes itself on `onfinish` / `oncancel`.
|
|
8009
|
-
*
|
|
8010
|
-
* Uses `getBoundingClientRect()` (physical viewport coords) so the animation
|
|
8011
|
-
* is RTL-correct without inset-inline math — the rect already encodes the
|
|
8012
|
-
* physical position regardless of `dir`.
|
|
8013
|
-
*
|
|
8014
|
-
* The 900 ms duration and easing curve are deliberately hardcoded — making
|
|
8015
|
-
* them configurable surfaces an API the host can't usefully tune without
|
|
8016
|
-
* understanding motion design as a whole.
|
|
8475
|
+
* A proof-of-work challenge issued by `Fly.Sdk.Captcha` (`CaptchaChallenge`).
|
|
8476
|
+
* The solver must find `n` in `[0, maxNumber)` such that
|
|
8477
|
+
* `sha256HexLower(salt + n) === challenge`.
|
|
8017
8478
|
*/
|
|
8018
|
-
|
|
8019
|
-
/**
|
|
8020
|
-
|
|
8021
|
-
|
|
8022
|
-
|
|
8023
|
-
|
|
8024
|
-
|
|
8025
|
-
|
|
8026
|
-
|
|
8027
|
-
|
|
8028
|
-
|
|
8029
|
-
|
|
8030
|
-
|
|
8031
|
-
* Animate a ghost element from {@link from} to the registered target's
|
|
8032
|
-
* rect. No-ops when:
|
|
8033
|
-
* - no target is registered (silent — panel may not be mounted yet)
|
|
8034
|
-
* - running outside a browser (SSR safety)
|
|
8035
|
-
* - the user has `prefers-reduced-motion: reduce` set (DOM is still
|
|
8036
|
-
* touched so callers see consistent side-effects, but no animation
|
|
8037
|
-
* runs)
|
|
8038
|
-
*
|
|
8039
|
-
* The ghost is appended to `document.body` (not the panel) so a parent
|
|
8040
|
-
* `overflow: hidden` on the panel can't clip the flight path.
|
|
8041
|
-
*/
|
|
8042
|
-
flyInto(from: DOMRect, opts?: {
|
|
8043
|
-
previewHtml?: string;
|
|
8044
|
-
}): void;
|
|
8045
|
-
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AgentFlightAnimator, never>;
|
|
8046
|
-
static ɵprov: _angular_core.ɵɵInjectableDeclaration<AgentFlightAnimator>;
|
|
8479
|
+
interface FlyCaptchaChallenge {
|
|
8480
|
+
/** Always `"SHA-256"` today. */
|
|
8481
|
+
algorithm: string;
|
|
8482
|
+
/** Lowercase-hex SHA-256 of `salt + number` for the secret solution number. */
|
|
8483
|
+
challenge: string;
|
|
8484
|
+
/** Base64 random salt, unique per challenge. */
|
|
8485
|
+
salt: string;
|
|
8486
|
+
/** HMAC signature binding challenge + maxNumber + expiresAt (server-verified). */
|
|
8487
|
+
signature: string;
|
|
8488
|
+
/** Exclusive upper bound of the search space (difficulty). */
|
|
8489
|
+
maxNumber: number;
|
|
8490
|
+
/** ISO-8601 instant after which the solution is rejected. Echoed back verbatim. */
|
|
8491
|
+
expiresAt: string;
|
|
8047
8492
|
}
|
|
8048
|
-
|
|
8049
8493
|
/**
|
|
8050
|
-
*
|
|
8051
|
-
*
|
|
8052
|
-
*
|
|
8053
|
-
*
|
|
8054
|
-
*
|
|
8055
|
-
* looking at**, and the design's reference implementation re-publishes the whole
|
|
8056
|
-
* set on every selection, tab and save (`pubTabActions`). Two consequences shape
|
|
8057
|
-
* every type below:
|
|
8058
|
-
*
|
|
8059
|
-
* 1. **A contribution is a full replace, never a patch.** There is no "add one
|
|
8060
|
-
* action" call, because the publisher never knows what the previous view left
|
|
8061
|
-
* behind. That also collapses D5's `search: null` ("suppress") vs `search`
|
|
8062
|
-
* absent distinction — under full replace both simply mean "this view offers
|
|
8063
|
-
* no search".
|
|
8064
|
-
* 2. **Render data and behaviour are separated in the type system.** Each family
|
|
8065
|
-
* has a `*Spec` base carrying ONLY the fields that affect what is painted;
|
|
8066
|
-
* the publisher-facing type extends it with callbacks, and the shell-facing
|
|
8067
|
-
* `*View` type extends it with bound invokers. The base IS the equality
|
|
8068
|
-
* surface {@link MagicBarRegistry} dedupes on — a re-publish whose specs are
|
|
8069
|
-
* unchanged must not disturb the shell, even though its closures are brand
|
|
8070
|
-
* new objects every time (an arrow function in a component method never
|
|
8071
|
-
* compares equal to its predecessor). See `magic-bar-projection.ts`.
|
|
8072
|
-
*
|
|
8073
|
-
* **Strings are i18n keys, never resolved text** — same rule as
|
|
8074
|
-
* {@link AgentCommandRegistration} (`labelKey` / `descriptionKey` / `hintKey`),
|
|
8075
|
-
* for the same two reasons: a contribution outlives a locale switch (a resolved
|
|
8076
|
-
* label would silently go stale until the publisher happened to re-publish), and
|
|
8077
|
-
* keys are locale-invariant so the dedupe fingerprint doesn't churn when the user
|
|
8078
|
-
* changes language. Keys resolve in the OWNING app's bundle.
|
|
8079
|
-
*
|
|
8080
|
-
* **Every `*Key` has an optional `*Params` sibling** ({@link MagicBarTextParams}),
|
|
8081
|
-
* fed straight to `I18nService.t(key, params)`. Without it a count-carrying string
|
|
8082
|
-
* ("Search 1,204 tasks…") forces the publisher to pass pre-formatted TEXT as the
|
|
8083
|
-
* key: it renders correctly in `en`, renders identically untranslated in ar/fr/ur,
|
|
8084
|
-
* and no locale tool can see it. Params participate in the dedupe fingerprint, so
|
|
8085
|
-
* a changing count re-paints.
|
|
8086
|
-
*
|
|
8087
|
-
* Which of D5 §4's "dynamics the shell must honor" live where:
|
|
8088
|
-
*
|
|
8089
|
-
* | # | Dynamic | Owner |
|
|
8090
|
-
* |---|---|---|
|
|
8091
|
-
* | 1 | Live re-publication, idempotent replace | {@link MagicBarRegistry} (here) |
|
|
8092
|
-
* | 2 | Disabled ≠ hidden, auto disabled-tooltip | contract keeps `disabled` rows; `fly-magic-actions` renders + suffixes |
|
|
8093
|
-
* | 3 | `toolbarPopIn` 40 ms stagger | renderer — it tracks on {@link MagicBarActionSpec.id}, which is why ids are unique across the WHOLE contribution |
|
|
8094
|
-
* | 4 | i18n on every label/tip | contract (keys + params, above) |
|
|
8095
|
-
* | 5 | Fixed right cluster is not contributable | contract — no slot exists for it |
|
|
8096
|
-
* | 6 | Mobile renders the same contribution | contract carries no form-factor branch; `openWidth` is a desktop hint mobile ignores |
|
|
8097
|
-
* | 7 | `shortcut` reserved (design has no shortcut affordance yet) | contract — carried, unrendered |
|
|
8098
|
-
*
|
|
8099
|
-
* On dynamic 3 specifically: the registry's dedupe does NOT stop the stagger
|
|
8100
|
-
* replaying, and believing it does would produce a renderer that re-animates on
|
|
8101
|
-
* every click. Dedupe fires only when *nothing painted* changed, and the dominant
|
|
8102
|
-
* case — `disabled: !hasSelection` — changes the fingerprint on every selection.
|
|
8103
|
-
* What holds the DOM still is the renderer's `@for (…; track item.id)`.
|
|
8494
|
+
* The solved payload, matching `Fly.Sdk.Captcha.CaptchaSolution` field-for-field
|
|
8495
|
+
* (camelCase Web JSON). Serialized to the opaque base64 token the backend decodes:
|
|
8496
|
+
* `base64(utf8(JSON.stringify(solution)))` — i.e. `Convert.ToBase64String` +
|
|
8497
|
+
* `JsonSerializerDefaults.Web`. Every field except `number` is echoed from the
|
|
8498
|
+
* challenge unchanged so the server's stateless signature check passes.
|
|
8104
8499
|
*/
|
|
8105
|
-
|
|
8106
|
-
|
|
8500
|
+
interface FlyCaptchaSolution {
|
|
8501
|
+
algorithm: string;
|
|
8502
|
+
challenge: string;
|
|
8503
|
+
salt: string;
|
|
8504
|
+
number: number;
|
|
8505
|
+
signature: string;
|
|
8506
|
+
maxNumber: number;
|
|
8507
|
+
expiresAt: string;
|
|
8508
|
+
}
|
|
8509
|
+
/** The solver lifecycle surfaced by the component's `state()` signal. */
|
|
8510
|
+
type FlyCaptchaState = 'idle' | 'verifying' | 'verified' | 'expired' | 'error';
|
|
8511
|
+
|
|
8512
|
+
/** Lowercase-hex SHA-256 of `input` via Web Crypto — matches `Convert.ToHexStringLower(SHA256…)`. */
|
|
8513
|
+
declare function flyCaptchaSha256Hex(input: string): Promise<string>;
|
|
8514
|
+
/** Standard base64 of the UTF-8 bytes of `s` — matches .NET `Convert.ToBase64String`. */
|
|
8515
|
+
declare function flyCaptchaBase64Utf8(s: string): string;
|
|
8107
8516
|
/**
|
|
8108
|
-
*
|
|
8109
|
-
*
|
|
8110
|
-
*
|
|
8111
|
-
*
|
|
8112
|
-
* A union rather than the boolean `danger` this started as: the design already
|
|
8113
|
-
* demands a second colour, and widening a shipped `danger?: boolean` into a union
|
|
8114
|
-
* later would mean REMOVING an interface member — MAJOR under `tools/ds-compat`
|
|
8115
|
-
* (rule 7), which forks the federation singleton for every remote.
|
|
8517
|
+
* Builds the opaque base64 token the backend's `CaptchaSolution.FromToken` expects.
|
|
8518
|
+
* Exported so a host (or a test) can construct/verify the token shape without the
|
|
8519
|
+
* component.
|
|
8116
8520
|
*/
|
|
8117
|
-
|
|
8521
|
+
declare function flyCaptchaBuildToken(solution: FlyCaptchaSolution): string;
|
|
8118
8522
|
/**
|
|
8119
|
-
*
|
|
8120
|
-
* `
|
|
8523
|
+
* **`fly-captcha`** — the design-system client for the self-hosted proof-of-work
|
|
8524
|
+
* captcha (`Fly.Sdk.Captcha`).
|
|
8121
8525
|
*
|
|
8122
|
-
*
|
|
8123
|
-
*
|
|
8124
|
-
*
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
*
|
|
8129
|
-
*
|
|
8526
|
+
* Given a {@link FlyCaptchaChallenge}, it brute-forces `n` in `[0, maxNumber)`
|
|
8527
|
+
* until `sha256HexLower(salt + n) === challenge`, then emits the solution as the
|
|
8528
|
+
* base64 token the backend decodes ({@link flyCaptchaBuildToken}). The search
|
|
8529
|
+
* hashes candidates with a vendored **synchronous** SHA-256 ({@link sha256HexSync}
|
|
8530
|
+
* from `./sha256` — no `crypto.subtle`/promise overhead per candidate, which used
|
|
8531
|
+
* to dominate solve time), in chunks scheduled on `requestAnimationFrame` so a
|
|
8532
|
+
* chunk boundary still yields back to the browser between slices. It auto-starts
|
|
8533
|
+
* whenever the `[challenge]` input changes. Implements
|
|
8534
|
+
* {@link ControlValueAccessor} so it drops into a reactive form / `[(ngModel)]` —
|
|
8535
|
+
* the control value IS the token string.
|
|
8130
8536
|
*
|
|
8131
|
-
*
|
|
8132
|
-
*
|
|
8133
|
-
*
|
|
8134
|
-
* federated remote that predates per-window plumbing can still contribute —
|
|
8135
|
-
* {@link MagicBarRegistry} resolves an `appId`-keyed slot as a fallback.
|
|
8537
|
+
* Expiry is the host's concern to refresh: the component checks `expiresAt` up
|
|
8538
|
+
* front and while solving, emits {@link expired}, and stops. i18n is
|
|
8539
|
+
* self-sufficient via the `captcha.*` baseline keys; RTL works via logical CSS.
|
|
8136
8540
|
*
|
|
8137
|
-
*
|
|
8138
|
-
*
|
|
8139
|
-
*
|
|
8140
|
-
*
|
|
8541
|
+
* @example
|
|
8542
|
+
* ```html
|
|
8543
|
+
* <fly-captcha [challenge]="challenge()" (solved)="post($event)" (expired)="refresh()" />
|
|
8544
|
+
* ```
|
|
8141
8545
|
*/
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
readonly
|
|
8546
|
+
declare class FlyCaptchaComponent implements ControlValueAccessor, OnDestroy {
|
|
8547
|
+
/** The challenge to solve. Setting (or replacing) it auto-starts a fresh solve. */
|
|
8548
|
+
readonly challenge: _angular_core.InputSignal<FlyCaptchaChallenge | null>;
|
|
8549
|
+
/** Candidates hashed synchronously in one slice before yielding back to the browser
|
|
8550
|
+
* on the next animation frame. Higher = fewer `requestAnimationFrame` hops (each
|
|
8551
|
+
* carries ~16ms of frame-boundary overhead), more synchronous work per slice.
|
|
8552
|
+
* 20,000 keeps a slice's own hashing time well under a long-task budget on modern
|
|
8553
|
+
* hardware (the vendored sync SHA-256 does several hundred thousand hashes/sec)
|
|
8554
|
+
* while needing only a handful of hops to clear the library's default difficulty. */
|
|
8555
|
+
readonly chunkSize: _angular_core.InputSignal<number>;
|
|
8556
|
+
/** The solution token once solved — the exact string to POST back to the backend. */
|
|
8557
|
+
readonly solved: _angular_core.OutputEmitterRef<string>;
|
|
8558
|
+
/** The challenge expired (up-front or mid-solve). The host should request a new one. */
|
|
8559
|
+
readonly expired: _angular_core.OutputEmitterRef<void>;
|
|
8560
|
+
readonly state: _angular_core.WritableSignal<FlyCaptchaState>;
|
|
8561
|
+
readonly token: _angular_core.WritableSignal<string | null>;
|
|
8562
|
+
/** Monotonic generation — bumped on every restart/destroy so a stale async chunk
|
|
8563
|
+
* or timer that captured an older generation no-ops instead of racing. */
|
|
8564
|
+
private _gen;
|
|
8565
|
+
private _raf;
|
|
8566
|
+
private _expiryTimer;
|
|
8567
|
+
private _onChange;
|
|
8568
|
+
private _onTouched;
|
|
8569
|
+
constructor();
|
|
8570
|
+
ngOnDestroy(): void;
|
|
8571
|
+
private _restart;
|
|
8572
|
+
/**
|
|
8573
|
+
* Hashes `[start, end)` synchronously with {@link sha256HexSync} — no per-candidate
|
|
8574
|
+
* `await`, so there is no promise/microtask overhead between candidates — then
|
|
8575
|
+
* yields to the next animation frame for the remainder. Bails to `error` state if
|
|
8576
|
+
* hashing itself throws (defensive; a pure function over a short string should not)
|
|
8577
|
+
* or if the whole `[0, maxNumber)` space is exhausted with no match, which means the
|
|
8578
|
+
* challenge is corrupt or was tampered with.
|
|
8579
|
+
*/
|
|
8580
|
+
private _solveChunk;
|
|
8581
|
+
private _onSolved;
|
|
8582
|
+
private _cancel;
|
|
8583
|
+
private _schedule;
|
|
8584
|
+
private _cancelSchedule;
|
|
8585
|
+
writeValue(value: string | null): void;
|
|
8586
|
+
registerOnChange(fn: (v: string | null) => void): void;
|
|
8587
|
+
registerOnTouched(fn: () => void): void;
|
|
8588
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlyCaptchaComponent, never>;
|
|
8589
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlyCaptchaComponent, "fly-captcha", never, { "challenge": { "alias": "challenge"; "required": false; "isSignal": true; }; "chunkSize": { "alias": "chunkSize"; "required": false; "isSignal": true; }; }, { "solved": "solved"; "expired": "expired"; }, never, never, true, never>;
|
|
8145
8590
|
}
|
|
8591
|
+
|
|
8146
8592
|
/**
|
|
8147
|
-
*
|
|
8148
|
-
* on the janitor path (`clear` after a window closes) without holding the
|
|
8149
|
-
* publisher.
|
|
8593
|
+
* Singleton registry of slash commands offered by the agent input palette.
|
|
8150
8594
|
*
|
|
8151
|
-
*
|
|
8152
|
-
*
|
|
8153
|
-
*
|
|
8154
|
-
*
|
|
8155
|
-
*
|
|
8156
|
-
*
|
|
8157
|
-
*
|
|
8595
|
+
* Lives in the DS so it crosses the federation boundary as a single instance via
|
|
8596
|
+
* `sharedMappings: ['@flyos/design-system']`. Federated remotes register
|
|
8597
|
+
* their commands at boot (and dispose on window close) without forking the shell.
|
|
8598
|
+
*
|
|
8599
|
+
* Storage is a signal store. `register` is O(1) for the unique-id case and O(n) when
|
|
8600
|
+
* replacing an existing id (filter then push). The append-then-replace strategy is
|
|
8601
|
+
* deliberate: registrations are rare (each one corresponds to a remote's app-init
|
|
8602
|
+
* effect), and the tradeoff buys us a stable id-collision contract — the *latest*
|
|
8603
|
+
* registration wins, and the previous handle's `dispose()` becomes a no-op rather
|
|
8604
|
+
* than removing the new entry.
|
|
8158
8605
|
*/
|
|
8159
|
-
declare
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
readonly
|
|
8606
|
+
declare class AgentCommandRegistry {
|
|
8607
|
+
private readonly _commands;
|
|
8608
|
+
/** All currently-registered commands, in insertion order. */
|
|
8609
|
+
readonly all: Signal<readonly AgentCommandRegistration[]>;
|
|
8163
8610
|
/**
|
|
8164
|
-
*
|
|
8165
|
-
*
|
|
8166
|
-
*
|
|
8167
|
-
*
|
|
8611
|
+
* Returns a signal of commands whose scope is `'global'` OR whose `scope.appId` is in
|
|
8612
|
+
* the live app set. The signal recomputes when either the registry or `liveAppIds`
|
|
8613
|
+
* changes — pass a `Signal<ReadonlySet<string>>` from the host's app-registry service
|
|
8614
|
+
* for reactive filtering.
|
|
8168
8615
|
*/
|
|
8169
|
-
|
|
8170
|
-
/** Params for {@link labelKey} — the count-badged option ("All statuses ({{count}})"). */
|
|
8171
|
-
readonly labelParams?: MagicBarTextParams;
|
|
8616
|
+
visible(liveAppIds: ReadonlySet<string> | Signal<ReadonlySet<string>>): Signal<readonly AgentCommandRegistration[]>;
|
|
8172
8617
|
/**
|
|
8173
|
-
*
|
|
8174
|
-
*
|
|
8175
|
-
*
|
|
8176
|
-
|
|
8177
|
-
|
|
8178
|
-
|
|
8179
|
-
*
|
|
8180
|
-
*
|
|
8181
|
-
*
|
|
8182
|
-
* Thoughts' `top-trending` chose the second and kept its campaign/area filters in-page — that
|
|
8183
|
-
* is the gap this closes.
|
|
8184
|
-
*
|
|
8185
|
-
* ## What it does NOT license
|
|
8186
|
-
* Do not use it for captions. If the string is something your app authored — "All statuses",
|
|
8187
|
-
* "Newest first", an action name — it belongs in a locale bundle and `labelKey` is the field.
|
|
8188
|
-
* The test is where the string comes from: shipped with the app ⇒ `labelKey`; read from the
|
|
8189
|
-
* tenant's data ⇒ `label`. A resolved caption here is untranslatable text smuggled past the
|
|
8190
|
-
* locale tooling, which is precisely what the key-only rule exists to prevent.
|
|
8618
|
+
* Register a single command. Returns a handle whose `dispose()` removes the row by
|
|
8619
|
+
* id. If the same id is later re-registered, the original handle's `dispose()`
|
|
8620
|
+
* becomes a no-op (the newer registration owns the row). Idempotent disposal.
|
|
8621
|
+
*/
|
|
8622
|
+
register(cmd: AgentCommandRegistration): AgentCommandHandle;
|
|
8623
|
+
/**
|
|
8624
|
+
* Bulk register. Rolls back on duplicate id within the input batch (throws before any
|
|
8625
|
+
* row lands). Cross-batch duplicates against existing rows follow the standard
|
|
8626
|
+
* "latest wins" rule and do NOT trigger rollback.
|
|
8191
8627
|
*
|
|
8192
|
-
*
|
|
8628
|
+
* Returns a handle whose `dispose()` tears down every row registered by this call.
|
|
8193
8629
|
*/
|
|
8194
|
-
readonly
|
|
8195
|
-
|
|
8196
|
-
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
/** Current selection — check glyph + 600 weight on the matching row. */
|
|
8204
|
-
readonly value: string;
|
|
8205
|
-
/** The unfiltered/unsorted baseline; the trigger shows its accent dot iff `value !== defaultValue`. */
|
|
8206
|
-
readonly defaultValue: string;
|
|
8207
|
-
}
|
|
8208
|
-
/** What a publisher supplies for a radio menu. */
|
|
8209
|
-
interface MagicBarRadioMenu extends MagicBarRadioMenuSpec {
|
|
8210
|
-
readonly onSelect?: (value: string) => void;
|
|
8211
|
-
}
|
|
8212
|
-
/** What the shell renders. `select` always exists; it no-ops when the publisher supplied no handler. */
|
|
8213
|
-
interface MagicBarRadioMenuView extends MagicBarRadioMenuSpec {
|
|
8214
|
-
select(value: string): void;
|
|
8630
|
+
registerAll(cmds: readonly AgentCommandRegistration[]): AgentCommandHandle;
|
|
8631
|
+
/** Tear down by id. Idempotent. */
|
|
8632
|
+
unregister(id: string): void;
|
|
8633
|
+
/** Monotonic counter; identifies which registration call currently owns each id. */
|
|
8634
|
+
private _generation;
|
|
8635
|
+
/** id → generation. Used so a stale handle's `dispose()` is a no-op after replacement. */
|
|
8636
|
+
private readonly _owners;
|
|
8637
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AgentCommandRegistry, never>;
|
|
8638
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<AgentCommandRegistry>;
|
|
8215
8639
|
}
|
|
8640
|
+
|
|
8216
8641
|
/**
|
|
8217
|
-
*
|
|
8642
|
+
* Singleton registry of entity lookups offered by the `/lookup` typeahead.
|
|
8218
8643
|
*
|
|
8219
|
-
*
|
|
8220
|
-
*
|
|
8221
|
-
*
|
|
8644
|
+
* Mirrors {@link AgentCommandRegistry}'s federation-singleton story
|
|
8645
|
+
* (`sharedMappings: ['@flyos/design-system']`), id-collision
|
|
8646
|
+
* "latest wins" contract, and disposable-handle ergonomics. OS-core entities
|
|
8647
|
+
* (note / calendar event / file) register once at shell bootstrap via
|
|
8648
|
+
* `CORE_APP_LOOKUPS`; federated remotes (Circles: scenario / trend / signal)
|
|
8649
|
+
* register at remote-component boot and dispose on window close.
|
|
8650
|
+
*
|
|
8651
|
+
* **Scope semantics diverge from commands.** Commands HIDE when their `appId`
|
|
8652
|
+
* isn't in `liveAppIds`. Lookups DO NOT — they're always offered, and
|
|
8653
|
+
* `{appId}` is just a *priority hint* that bumps that lookup to the top of
|
|
8654
|
+
* the entity picker when the app is live. See {@link LookupRegistration.scope}
|
|
8655
|
+
* for the rationale.
|
|
8656
|
+
*
|
|
8657
|
+
* Storage is a signal store keyed on {@link LookupRegistration.entity}. Because
|
|
8658
|
+
* `entity` is the collision key, an app re-registering the same entity replaces
|
|
8659
|
+
* the prior descriptor; a stale handle's `dispose()` then no-ops.
|
|
8222
8660
|
*/
|
|
8223
|
-
|
|
8224
|
-
readonly
|
|
8225
|
-
/**
|
|
8226
|
-
readonly
|
|
8227
|
-
/** Params for {@link labelKey}, e.g. `{ count: 3 }` for "Delete {{count}} items". */
|
|
8228
|
-
readonly labelParams?: MagicBarTextParams;
|
|
8661
|
+
declare class AgentLookupRegistry {
|
|
8662
|
+
private readonly _lookups;
|
|
8663
|
+
/** All currently-registered lookups, in insertion order. */
|
|
8664
|
+
readonly all: Signal<readonly LookupRegistration[]>;
|
|
8229
8665
|
/**
|
|
8230
|
-
*
|
|
8231
|
-
* the design's icon transport. Reference {@link FLY_MAGIC_BAR_ICONS} by name
|
|
8232
|
-
* rather than hand-authoring; a publisher MAY author its own, subject to the
|
|
8233
|
-
* contract below.
|
|
8666
|
+
* All registered lookups, sorted by affinity to `liveAppIds`:
|
|
8234
8667
|
*
|
|
8235
|
-
*
|
|
8236
|
-
*
|
|
8237
|
-
*
|
|
8238
|
-
*
|
|
8239
|
-
* Anything else (a container element, an `on*` handler, `style`, `href`,
|
|
8240
|
-
* `fill="url(…)"`, a stray text node) rejects the WHOLE fragment: the button
|
|
8241
|
-
* renders with no glyph and logs. See `magic-actions-icon.ts`.
|
|
8668
|
+
* 1. Lookups whose `scope.appId` is in the live app set (in registration
|
|
8669
|
+
* order within that bucket).
|
|
8670
|
+
* 2. Then everything else — `'global'` lookups AND scoped lookups whose
|
|
8671
|
+
* app isn't currently live — in registration order.
|
|
8242
8672
|
*
|
|
8243
|
-
*
|
|
8244
|
-
*
|
|
8245
|
-
*
|
|
8246
|
-
*
|
|
8247
|
-
|
|
8248
|
-
readonly iconPath?: string;
|
|
8249
|
-
/** Default `'icon'`. */
|
|
8250
|
-
readonly kind?: MagicBarActionKind;
|
|
8251
|
-
/** Dimmed (`opacity .38`), NEVER hidden — a vanishing action teaches the user nothing. */
|
|
8252
|
-
readonly disabled?: boolean;
|
|
8253
|
-
/**
|
|
8254
|
-
* Tooltip override while disabled. Absent is the normal case: the renderer
|
|
8255
|
-
* auto-suffixes the resolved label ("… — select an item first"). Resolution
|
|
8256
|
-
* and the connector phrasing are the renderer's job precisely because they are
|
|
8257
|
-
* locale work, and this store holds keys rather than text.
|
|
8258
|
-
*/
|
|
8259
|
-
readonly disabledTipKey?: string;
|
|
8260
|
-
/** Params for {@link disabledTipKey}. */
|
|
8261
|
-
readonly disabledTipParams?: MagicBarTextParams;
|
|
8262
|
-
/** Tooltip override while enabled. Absent → the renderer uses `labelKey`. */
|
|
8263
|
-
readonly tipKey?: string;
|
|
8264
|
-
/** Params for {@link tipKey}. */
|
|
8265
|
-
readonly tipParams?: MagicBarTextParams;
|
|
8266
|
-
/**
|
|
8267
|
-
* Semantic colour. Default `'default'`; `'danger'` is the ONLY thing that makes
|
|
8268
|
-
* an icon red (D7), `'success'` the green completed-toggle treatment.
|
|
8673
|
+
* Recomputes when either the registry or `liveAppIds` changes. Pass a
|
|
8674
|
+
* `Signal<ReadonlySet<string>>` from the host's app-registry for reactive
|
|
8675
|
+
* re-sorting. **Always returns the full registry** — see the type doc on
|
|
8676
|
+
* {@link LookupRegistration.scope} for why this differs from
|
|
8677
|
+
* {@link AgentCommandRegistry.visible}.
|
|
8269
8678
|
*/
|
|
8270
|
-
readonly
|
|
8271
|
-
/**
|
|
8272
|
-
|
|
8273
|
-
|
|
8274
|
-
|
|
8275
|
-
/**
|
|
8276
|
-
* Reserved (D5 §4 item 7). The designs carry no keyboard-shortcut affordance
|
|
8277
|
-
* anywhere; the field exists so adding one later is a renderer change rather
|
|
8278
|
-
* than a contract break. Nothing renders it today.
|
|
8679
|
+
visible(liveAppIds: ReadonlySet<string> | Signal<ReadonlySet<string>>): Signal<readonly LookupRegistration[]>;
|
|
8680
|
+
/**
|
|
8681
|
+
* Register one lookup. Returns a handle whose `dispose()` removes the row by
|
|
8682
|
+
* `entity`. A later re-registration of the same entity makes the original
|
|
8683
|
+
* handle's `dispose()` a no-op (the newer registration owns the row).
|
|
8279
8684
|
*/
|
|
8280
|
-
|
|
8281
|
-
}
|
|
8282
|
-
/** What a publisher supplies for one action. */
|
|
8283
|
-
interface MagicBarAction extends MagicBarActionSpec {
|
|
8284
|
-
readonly menu?: MagicBarRadioMenu;
|
|
8685
|
+
register(lookup: LookupRegistration): LookupHandle;
|
|
8285
8686
|
/**
|
|
8286
|
-
*
|
|
8287
|
-
*
|
|
8288
|
-
*
|
|
8289
|
-
* handler it has always been.
|
|
8687
|
+
* Bulk register. Rolls back on a duplicate entity WITHIN the input batch
|
|
8688
|
+
* (throws before any row lands). Cross-batch duplicates against existing rows
|
|
8689
|
+
* follow the standard "latest wins" rule and do NOT trigger rollback.
|
|
8290
8690
|
*/
|
|
8291
|
-
readonly
|
|
8292
|
-
}
|
|
8293
|
-
/**
|
|
8294
|
-
* What the shell renders. `run()` always exists and always dispatches to the
|
|
8295
|
-
* publisher's LATEST handler for this id — including after a re-publish the
|
|
8296
|
-
* registry deliberately did not propagate (see `magic-bar-projection.ts`).
|
|
8297
|
-
*/
|
|
8298
|
-
interface MagicBarActionView extends MagicBarActionSpec {
|
|
8299
|
-
readonly menu: MagicBarRadioMenuView | null;
|
|
8691
|
+
registerAll(lookups: readonly LookupRegistration[]): LookupHandle;
|
|
8300
8692
|
/**
|
|
8301
|
-
*
|
|
8302
|
-
*
|
|
8303
|
-
* ## Why it carries the trigger element
|
|
8304
|
-
* An action that opens a POPOVER the publisher owns — the canonical case is a
|
|
8305
|
-
* listing screen's advanced-filter panel — has to position that popover under
|
|
8306
|
-
* the button the user just pressed. The publisher cannot find that button:
|
|
8307
|
-
* embedded, it is painted by `fly-magic-actions` inside the shell's top-bar
|
|
8308
|
-
* pill, in the shell's DOM, several stacking contexts and one federation
|
|
8309
|
-
* boundary away from the remote that published the action. Before this argument
|
|
8310
|
-
* existed, PPM's projects register had to anchor its panel to its own page
|
|
8311
|
-
* header instead, which put the panel in the middle of the window while the
|
|
8312
|
-
* button that opened it sat in the chrome above — an affordance with no visible
|
|
8313
|
-
* relationship to its own trigger.
|
|
8693
|
+
* Resolve a deep-link anchor to a concrete launch target.
|
|
8314
8694
|
*
|
|
8315
|
-
*
|
|
8316
|
-
*
|
|
8317
|
-
*
|
|
8318
|
-
*
|
|
8319
|
-
*
|
|
8320
|
-
*
|
|
8321
|
-
*
|
|
8695
|
+
* `kind` is the dotted `<appId>.<entity>` token the agents backend emits
|
|
8696
|
+
* inside `flyos:<kind>/<id>` chat-answer anchors — the same entity-kind
|
|
8697
|
+
* vocabulary as drag-payload kinds and `ref` parts. Returns
|
|
8698
|
+
* `{ appId, route }` when a registered lookup for that `(appId, entity)`
|
|
8699
|
+
* pair carries a {@link LookupDescriptor.deepLinkRoute} template; `null`
|
|
8700
|
+
* otherwise (unknown entity, app mismatch, or no template — e.g. the
|
|
8701
|
+
* owning app isn't installed) so the caller renders plain text rather than
|
|
8702
|
+
* a dead link.
|
|
8322
8703
|
*
|
|
8323
|
-
*
|
|
8324
|
-
*
|
|
8325
|
-
*
|
|
8326
|
-
*
|
|
8327
|
-
|
|
8328
|
-
|
|
8704
|
+
* `appId` and `entity` are both dot-free by their own grammars, so the
|
|
8705
|
+
* FIRST dot is the unambiguous split point; a dotless `kind` can't carry an
|
|
8706
|
+
* app and never resolves. The template's single `{id}` placeholder is
|
|
8707
|
+
* substituted URL-encoded.
|
|
8708
|
+
*/
|
|
8709
|
+
resolveDeepLink(kind: string, id: string): {
|
|
8710
|
+
readonly appId: string;
|
|
8711
|
+
readonly route: string;
|
|
8712
|
+
} | null;
|
|
8713
|
+
/**
|
|
8714
|
+
* Resolve a deep-link target from a bare `(entity, id)` pair — the shape a
|
|
8715
|
+
* `/lookup` ref carries (it has no `<appId>.<entity>` kind token; the owning
|
|
8716
|
+
* app is implicit in the registered descriptor). `entity` is the registry's
|
|
8717
|
+
* unique storage key, so it identifies the descriptor unambiguously without
|
|
8718
|
+
* an app prefix.
|
|
8329
8719
|
*
|
|
8330
|
-
*
|
|
8331
|
-
*
|
|
8332
|
-
*
|
|
8333
|
-
*
|
|
8334
|
-
*
|
|
8720
|
+
* Returns `{ appId, route }` (the descriptor's {@link LookupDescriptor.appId}
|
|
8721
|
+
* / affinity `scope.appId` as the owner, `{id}` substituted URL-encoded) when
|
|
8722
|
+
* a matching descriptor carries a {@link LookupDescriptor.deepLinkRoute};
|
|
8723
|
+
* `null` otherwise (unknown entity, no template, or the owning app has since
|
|
8724
|
+
* unregistered) so callers render plain text rather than a dead link — the
|
|
8725
|
+
* same graceful-degrade contract as {@link resolveDeepLink}.
|
|
8335
8726
|
*/
|
|
8336
|
-
|
|
8337
|
-
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
8346
|
-
|
|
8347
|
-
|
|
8348
|
-
}
|
|
8349
|
-
interface MagicBarGroupView extends MagicBarGroupSpec {
|
|
8350
|
-
readonly items: readonly MagicBarActionView[];
|
|
8727
|
+
resolveDeepLinkForEntity(entity: string, id: string): {
|
|
8728
|
+
readonly appId: string;
|
|
8729
|
+
readonly route: string;
|
|
8730
|
+
} | null;
|
|
8731
|
+
/** Tear down by entity. Idempotent. */
|
|
8732
|
+
unregister(entity: string): void;
|
|
8733
|
+
/** Monotonic counter; identifies which registration call currently owns each entity. */
|
|
8734
|
+
private _generation;
|
|
8735
|
+
/** entity → generation. Lets a stale handle's `dispose()` no-op after replacement. */
|
|
8736
|
+
private readonly _owners;
|
|
8737
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AgentLookupRegistry, never>;
|
|
8738
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<AgentLookupRegistry>;
|
|
8351
8739
|
}
|
|
8740
|
+
|
|
8352
8741
|
/**
|
|
8353
|
-
*
|
|
8354
|
-
*
|
|
8742
|
+
* Singleton registry of chip-renderer components and keyboard-alternative draggable
|
|
8743
|
+
* items, keyed by `kind` and `appId`.
|
|
8355
8744
|
*
|
|
8356
|
-
*
|
|
8357
|
-
*
|
|
8745
|
+
* Like {@link AgentCommandRegistry}, this lives in the DS so it crosses the federation
|
|
8746
|
+
* boundary as a single instance. Hosts (the shell `<fly-agent-input>`) lookup
|
|
8747
|
+
* renderers; remotes register them.
|
|
8748
|
+
*
|
|
8749
|
+
* Renderer lookup is `O(n)` over the registered list — the registry is small (one or
|
|
8750
|
+
* two entries per app) and lookups happen on drop, not per frame.
|
|
8751
|
+
*
|
|
8752
|
+
* Draggable storage is per-`appId` writable signal cached in a Map, so each `appId`
|
|
8753
|
+
* gets a stable {@link Signal} reference across reads (callers can `===`-compare).
|
|
8358
8754
|
*/
|
|
8359
|
-
|
|
8360
|
-
|
|
8361
|
-
|
|
8362
|
-
|
|
8363
|
-
readonly placeholderParams?: MagicBarTextParams;
|
|
8755
|
+
declare class AgentDropRegistry {
|
|
8756
|
+
private readonly _renderers;
|
|
8757
|
+
/** Per-appId writable store for draggables. Read-only mirror returned to callers. */
|
|
8758
|
+
private readonly _draggablesByApp;
|
|
8364
8759
|
/**
|
|
8365
|
-
*
|
|
8366
|
-
*
|
|
8367
|
-
*
|
|
8368
|
-
* Exists because a view can arrive **already filtered**: a deep link carrying
|
|
8369
|
-
* `?q=…`, a restored session, a filter applied from a detail pane. Without it the
|
|
8370
|
-
* box renders empty over a visibly filtered list, and the user is looking at a
|
|
8371
|
-
* contradiction the chrome cannot explain.
|
|
8372
|
-
*
|
|
8373
|
-
* ## Why it is not called `query`
|
|
8374
|
-
* {@link MagicBarSearchView} — which extends this interface — already declares
|
|
8375
|
-
* `query(text: string): void`, the late-bound invoker. A `query?: string` here
|
|
8376
|
-
* would make that view an illegal extension (TS2430: `(text: string) => void` is
|
|
8377
|
-
* not assignable to `string | undefined`), and the only other way out — renaming
|
|
8378
|
-
* the invoker — removes a member of a shipped exported interface, which is a
|
|
8379
|
-
* ds-compat MAJOR (rule 7) and forks the federation singleton for every remote.
|
|
8380
|
-
* So the field takes the name that pairs with the invoker instead of colliding
|
|
8381
|
-
* with it: `queryText` is the text, `query()` submits it.
|
|
8382
|
-
*
|
|
8383
|
-
* ## Precedence — this is a SEED, not a controlled value
|
|
8384
|
-
* The field's live text is owned by the **shell**, because the user types into
|
|
8385
|
-
* it. This field is the publisher's chance to move it, and the shell adopts the
|
|
8386
|
-
* published value exactly three times:
|
|
8387
|
-
*
|
|
8388
|
-
* 1. the first time it binds this view,
|
|
8389
|
-
* 2. when {@link MagicBarContribution.viewKey} changes (reset-on-navigate — the
|
|
8390
|
-
* previous view's query must not survive into the next one), and
|
|
8391
|
-
* 3. when the published value **itself changes** from the one previously
|
|
8392
|
-
* published.
|
|
8393
|
-
*
|
|
8394
|
-
* A re-publish carrying an UNCHANGED `queryText` never touches what the user has
|
|
8395
|
-
* typed. That third clause is the whole rule: the dominant re-publish is
|
|
8396
|
-
* `disabled: !hasSelection` flipping on a selection change, and a shell that
|
|
8397
|
-
* re-read `queryText` on every emitted view would revert a keystroke every time
|
|
8398
|
-
* the user selected a row mid-search — the classic controlled-input bug. The rule
|
|
8399
|
-
* is authored once, as {@link magicBarSearchText}, so no renderer re-derives it.
|
|
8400
|
-
*
|
|
8401
|
-
* `undefined` and `''` are **different** and the difference is load-bearing:
|
|
8402
|
-
* absent means "this view does not manage the field" (nothing is ever forced),
|
|
8403
|
-
* `''` means "clear it". Both the fingerprint and the seed comparison distinguish
|
|
8404
|
-
* them.
|
|
8760
|
+
* Look up the chip-renderer component class for a `kind`. The newest registration for
|
|
8761
|
+
* a given `kind` wins, regardless of `appId` — we scan the list in reverse so a later
|
|
8762
|
+
* `register` call shadows an earlier one for the same `kind`.
|
|
8405
8763
|
*
|
|
8406
|
-
*
|
|
8407
|
-
*
|
|
8408
|
-
* is harmless (the seed changes to text the field already shows). A publisher
|
|
8409
|
-
* that mirrors it back **debounced** is not: typing "abc" then publishing
|
|
8410
|
-
* `queryText: 'a'` 300 ms later is, by rule 3, a genuine publisher-initiated
|
|
8411
|
-
* change, and the field snaps back to "a". Publish here only for state the view
|
|
8412
|
-
* owns independently of the field.
|
|
8764
|
+
* Returns `null` when no renderer is registered; the host falls back to a generic
|
|
8765
|
+
* `plainTextFallback` chip.
|
|
8413
8766
|
*/
|
|
8414
|
-
|
|
8767
|
+
rendererFor(kind: string): Type<AgentChipHostInputs> | null;
|
|
8415
8768
|
/**
|
|
8416
|
-
*
|
|
8769
|
+
* Register a renderer for a `(kind, appId)` pair. Re-registering the same pair
|
|
8770
|
+
* replaces the prior entry; the disposal handle for the prior registration becomes
|
|
8771
|
+
* a no-op.
|
|
8417
8772
|
*
|
|
8418
|
-
*
|
|
8419
|
-
*
|
|
8420
|
-
* contribution over a cosmetic hint (leaving the previous view's actions in the
|
|
8421
|
-
* chrome), and mobile ignores the field entirely, so there is no single range to
|
|
8422
|
-
* enforce. `fly-magic-actions` clamps to the design range at paint time and is
|
|
8423
|
-
* the only place that decides what an out-of-range or non-finite value means.
|
|
8773
|
+
* Returns a {@link AgentCommandHandle} (re-used to keep the disposable shape uniform
|
|
8774
|
+
* across registries) whose `dispose()` removes this exact registration.
|
|
8424
8775
|
*/
|
|
8425
|
-
|
|
8426
|
-
/**
|
|
8427
|
-
|
|
8776
|
+
register<T = unknown>(reg: AgentDropRendererRegistration<T>): AgentCommandHandle;
|
|
8777
|
+
/**
|
|
8778
|
+
* Apps publish their live "draggable from focused window" set so the keyboard
|
|
8779
|
+
* "Attach from app…" menu can offer them. Hosts call this each time the user-visible
|
|
8780
|
+
* draggable list changes; passing an empty array clears the entry for this `appId`.
|
|
8781
|
+
*/
|
|
8782
|
+
publishDraggables(appId: string, items: readonly AgentDraggableItem[]): void;
|
|
8783
|
+
/**
|
|
8784
|
+
* Reactive read of the draggable set published for `appId`. Empty when none. The
|
|
8785
|
+
* returned signal is stable across calls (cached by `appId`), so consumers can use
|
|
8786
|
+
* it as a stable input to `computed()`.
|
|
8787
|
+
*/
|
|
8788
|
+
draggablesFor(appId: string): Signal<readonly AgentDraggableItem[]>;
|
|
8789
|
+
/** Lazy-init the per-appId writable bucket. Returns the writable handle for internal use. */
|
|
8790
|
+
private bucketFor;
|
|
8791
|
+
private _generation;
|
|
8792
|
+
private readonly _owners;
|
|
8793
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AgentDropRegistry, never>;
|
|
8794
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<AgentDropRegistry>;
|
|
8795
|
+
}
|
|
8796
|
+
|
|
8797
|
+
/**
|
|
8798
|
+
* Imperative action published by an app, consumed by the agent panel.
|
|
8799
|
+
*
|
|
8800
|
+
* Re-uses {@link AgentDragPayload} as the wire envelope so a dragged item
|
|
8801
|
+
* and a programmatic "Explain" click are byte-for-byte the same shape —
|
|
8802
|
+
* renderers, validators, and serialisation paths never fork on transport.
|
|
8803
|
+
*
|
|
8804
|
+
* Adding a verb is a minor DS bump (consumers ignore unknown verbs in
|
|
8805
|
+
* their `switch`). Removing one is a major DS bump.
|
|
8806
|
+
*/
|
|
8807
|
+
type AgentActionVerb = 'explain' | 'why-empty' | 'compose-query' | 'compare' | 'summarize';
|
|
8808
|
+
/**
|
|
8809
|
+
* Whether the agent panel sends the staged payload immediately or stages
|
|
8810
|
+
* the chip for the user to edit and send manually.
|
|
8811
|
+
*
|
|
8812
|
+
* Phase 1 (DS v2.6.0) supports `'stage'` only. Dispatching with `'auto'`
|
|
8813
|
+
* throws {@link AgentActionUnsupportedDispatchError} so callers don't
|
|
8814
|
+
* silently fail. `'auto'` lands once `AgentInputComponent.programmaticSubmit`
|
|
8815
|
+
* is exposed and reviewed against the input's state machine.
|
|
8816
|
+
*/
|
|
8817
|
+
type AgentActionDispatch = 'auto' | 'stage';
|
|
8818
|
+
interface AgentAction<T = unknown> {
|
|
8819
|
+
/** Intent the agent should apply to {@link payload}. */
|
|
8820
|
+
readonly verb: AgentActionVerb;
|
|
8821
|
+
/** The wire envelope. Validated against {@link validateAgentPayload}'s
|
|
8822
|
+
* size caps before the bus fans it out. */
|
|
8823
|
+
readonly payload: AgentDragPayload<T>;
|
|
8824
|
+
/** Optional slash command id to bind before send (e.g. `'explain-report'`).
|
|
8825
|
+
* Phase 1 captures this for telemetry only — actual binding lands when
|
|
8826
|
+
* the input's programmatic-send API ships. An unknown id is dropped
|
|
8827
|
+
* silently with a console warning, the chip still arrives. */
|
|
8828
|
+
readonly autoCommandId?: string;
|
|
8829
|
+
/** Phase 1 supports `'stage'` only. See {@link AgentActionDispatch}. */
|
|
8830
|
+
readonly dispatch: AgentActionDispatch;
|
|
8831
|
+
/** Source DOM rect for the FLIP entry animation. Omit to skip the
|
|
8832
|
+
* animation (e.g. dispatching from a keyboard shortcut with no anchor). */
|
|
8833
|
+
readonly originRect?: DOMRect;
|
|
8834
|
+
/** Optional HTML snippet rendered inside the flight ghost. Callers are
|
|
8835
|
+
* responsible for escaping untrusted text — the bus does not sanitise.
|
|
8836
|
+
* Defaults (when omitted) to a strong-wrapped escape of the payload's
|
|
8837
|
+
* `plainTextFallback` rendered by the panel host. */
|
|
8838
|
+
readonly originPreviewHtml?: string;
|
|
8428
8839
|
}
|
|
8429
|
-
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
8433
|
-
|
|
8434
|
-
|
|
8435
|
-
|
|
8436
|
-
|
|
8437
|
-
|
|
8438
|
-
readonly onOpenFilters?: (trigger?: HTMLElement) => void;
|
|
8840
|
+
/**
|
|
8841
|
+
* Thrown synchronously by {@link AgentActionBus.dispatch} when a caller
|
|
8842
|
+
* supplies a dispatch mode this DS version doesn't implement yet. Catching
|
|
8843
|
+
* by class name lets a forward-compatible caller fall back to `'stage'`
|
|
8844
|
+
* without depending on instanceof across federation boundaries.
|
|
8845
|
+
*/
|
|
8846
|
+
declare class AgentActionUnsupportedDispatchError extends Error {
|
|
8847
|
+
readonly dispatch: AgentActionDispatch;
|
|
8848
|
+
constructor(dispatch: AgentActionDispatch);
|
|
8439
8849
|
}
|
|
8440
|
-
|
|
8441
|
-
|
|
8442
|
-
|
|
8850
|
+
|
|
8851
|
+
/**
|
|
8852
|
+
* Imperative sibling to {@link AgentCommandRegistry} / {@link AgentDropRegistry}.
|
|
8853
|
+
*
|
|
8854
|
+
* Apps call {@link dispatch} to push a typed {@link AgentAction} onto the bus;
|
|
8855
|
+
* the agent panel subscribes once at construct and routes by verb. The bus
|
|
8856
|
+
* itself is a thin pass-through — it does NOT decide UI behaviour. The
|
|
8857
|
+
* subscriber (agent-panel) owns: showing the panel, staging the chip,
|
|
8858
|
+
* triggering the flight animation, and binding the command. This keeps the
|
|
8859
|
+
* DS free of host policy.
|
|
8860
|
+
*
|
|
8861
|
+
* Federation-safe: `providedIn: 'root'` + `sharedMappings: ['@flyos/design-system']`
|
|
8862
|
+
* give every federated remote the same singleton, so a remote's "Explain"
|
|
8863
|
+
* button reaches the host's panel without any cross-bundle wiring.
|
|
8864
|
+
*
|
|
8865
|
+
* Validation runs synchronously inside `dispatch` so a caller that sends an
|
|
8866
|
+
* oversize payload sees the throw at their site, not on the subscriber. The
|
|
8867
|
+
* subscriber therefore never has to defend against malformed envelopes.
|
|
8868
|
+
*/
|
|
8869
|
+
declare class AgentActionBus {
|
|
8870
|
+
private readonly _actions$;
|
|
8871
|
+
/** Hot stream of actions in dispatch order. Subscribers receive only
|
|
8872
|
+
* actions dispatched AFTER they subscribe — late subscribers see nothing
|
|
8873
|
+
* retroactively. Use {@link lastAction} for the latest snapshot. */
|
|
8874
|
+
readonly actions$: Observable<AgentAction>;
|
|
8875
|
+
/** Most recent action — for DevTools, smoke tests, and late-subscriber
|
|
8876
|
+
* catch-up. Null until the first successful dispatch. */
|
|
8877
|
+
readonly lastAction: _angular_core.WritableSignal<AgentAction<unknown> | null>;
|
|
8443
8878
|
/**
|
|
8444
|
-
*
|
|
8445
|
-
*
|
|
8446
|
-
* {@link
|
|
8447
|
-
*
|
|
8879
|
+
* The action currently being processed by the subscriber, or null when
|
|
8880
|
+
* none. Set by {@link dispatch} immediately before emitting on
|
|
8881
|
+
* {@link actions$}; cleared by the subscriber via {@link settle} once
|
|
8882
|
+
* it finishes its handler (success or fail). Lets the dispatcher render
|
|
8883
|
+
* a busy state on the originating control — e.g. a card swapping its
|
|
8884
|
+
* sparkle icon for a spinner while the agent panel mints the optimistic
|
|
8885
|
+
* thread and starts the request. Identity check (`bus.inFlight() === act`)
|
|
8886
|
+
* is the panel-side contract; dispatchers usually project to a stable id
|
|
8887
|
+
* inside the payload (e.g. <c>reportId</c>) to scope busy-state visually.
|
|
8888
|
+
*
|
|
8889
|
+
* If multiple dispatches race, the latest wins — the prior in-flight
|
|
8890
|
+
* action is dropped on the floor here (the panel may still handle it,
|
|
8891
|
+
* but the dispatcher's busy indicator follows the newer action). Apps
|
|
8892
|
+
* that need stricter single-flight semantics should guard at the call
|
|
8893
|
+
* site (the agent-panel's <c>_pendingTempThreadId</c> already does so
|
|
8894
|
+
* for the explain verb).
|
|
8448
8895
|
*/
|
|
8449
|
-
|
|
8896
|
+
readonly inFlight: _angular_core.WritableSignal<AgentAction<unknown> | null>;
|
|
8450
8897
|
/**
|
|
8451
|
-
*
|
|
8452
|
-
*
|
|
8453
|
-
*
|
|
8454
|
-
*
|
|
8898
|
+
* Push an action onto the bus.
|
|
8899
|
+
*
|
|
8900
|
+
* Throws synchronously when:
|
|
8901
|
+
* - `dispatch === 'auto'` (not implemented in this DS version) — see
|
|
8902
|
+
* {@link AgentActionUnsupportedDispatchError}.
|
|
8903
|
+
* - the payload fails {@link validateAgentPayload} (oversize, invalid
|
|
8904
|
+
* version, invalid kind). The error message carries the field path
|
|
8905
|
+
* so the caller can fix the offending field.
|
|
8906
|
+
*
|
|
8907
|
+
* Subscribers see the action via {@link actions$} on the next tick of
|
|
8908
|
+
* the Subject; the {@link lastAction} signal updates synchronously
|
|
8909
|
+
* before the Subject emits so an effect reading both stays consistent.
|
|
8455
8910
|
*/
|
|
8456
|
-
|
|
8457
|
-
}
|
|
8458
|
-
/**
|
|
8459
|
-
* One view's complete claim on the magic bar.
|
|
8460
|
-
*
|
|
8461
|
-
* Identity (`appId` / `windowId`) is deliberately absent: it belongs to the
|
|
8462
|
-
* {@link MagicBarPublisher} that was minted for this owner, so a later publish
|
|
8463
|
-
* cannot re-target another app's slot.
|
|
8464
|
-
*/
|
|
8465
|
-
interface MagicBarContribution {
|
|
8911
|
+
dispatch<T>(action: AgentAction<T>): void;
|
|
8466
8912
|
/**
|
|
8467
|
-
*
|
|
8468
|
-
*
|
|
8469
|
-
*
|
|
8913
|
+
* Subscriber contract: call after the handler for {@link inFlight}
|
|
8914
|
+
* completes (success or fail). Only clears {@link inFlight} if it still
|
|
8915
|
+
* points at the passed action — a no-op when a later dispatch already
|
|
8916
|
+
* superseded it. Pass the same action reference the subscriber received
|
|
8917
|
+
* from {@link actions$}; identity is the gate.
|
|
8470
8918
|
*/
|
|
8471
|
-
|
|
8472
|
-
readonly search?: MagicBarSearch | null;
|
|
8473
|
-
/** Ordered clusters, separator-joined. */
|
|
8474
|
-
readonly groups?: readonly MagicBarGroup[];
|
|
8475
|
-
/** The accent-filled CTA ("New task", "Add signal"). */
|
|
8476
|
-
readonly primary?: MagicBarAction | null;
|
|
8919
|
+
settle(action: AgentAction): void;
|
|
8477
8920
|
/**
|
|
8478
|
-
*
|
|
8479
|
-
*
|
|
8921
|
+
* Semantic alias of {@link settle} for explicit user-driven cancellation —
|
|
8922
|
+
* e.g. a future "Stop" button in the agent input tray, or a dispatcher
|
|
8923
|
+
* teardown that wants to abandon its own in-flight action. Identical
|
|
8924
|
+
* runtime behaviour (identity check + clear), but the two-method surface
|
|
8925
|
+
* lets the UI distinguish "handler finished" from "user said no" in
|
|
8926
|
+
* telemetry / logs without sniffing a "reason" parameter.
|
|
8480
8927
|
*
|
|
8481
|
-
*
|
|
8482
|
-
*
|
|
8483
|
-
* production must source these from manifests instead of the mock's hardcoded
|
|
8484
|
-
* `{ title, note, prompt }` triples. Duplicating that model here would fork the
|
|
8485
|
-
* palette and reintroduce hardcoded prompt text. Unknown ids are dropped by the
|
|
8486
|
-
* resolver; an empty list leaves the shell's affinity ranking in charge.
|
|
8928
|
+
* Pass the same action reference returned from {@link inFlight} or held
|
|
8929
|
+
* by the dispatcher; identity is the gate.
|
|
8487
8930
|
*/
|
|
8488
|
-
|
|
8489
|
-
|
|
8490
|
-
|
|
8491
|
-
}
|
|
8492
|
-
/** The shell-facing projection of a contribution. See `magic-bar-projection.ts`. */
|
|
8493
|
-
interface MagicBarView {
|
|
8494
|
-
readonly appId: string;
|
|
8495
|
-
readonly windowId?: string;
|
|
8496
|
-
/** {@link magicBarOwnerKey} of the publisher. */
|
|
8497
|
-
readonly ownerKey: string;
|
|
8498
|
-
readonly viewKey: string;
|
|
8499
|
-
readonly search: MagicBarSearchView | null;
|
|
8500
|
-
readonly groups: readonly MagicBarGroupView[];
|
|
8501
|
-
readonly primary: MagicBarActionView | null;
|
|
8502
|
-
readonly quickCommandIds: readonly string[];
|
|
8503
|
-
readonly overflow: readonly MagicBarActionView[];
|
|
8931
|
+
cancel(action: AgentAction): void;
|
|
8932
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AgentActionBus, never>;
|
|
8933
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<AgentActionBus>;
|
|
8504
8934
|
}
|
|
8935
|
+
|
|
8505
8936
|
/**
|
|
8506
|
-
*
|
|
8507
|
-
*
|
|
8508
|
-
*
|
|
8509
|
-
*
|
|
8510
|
-
*
|
|
8511
|
-
*
|
|
8937
|
+
* FLIP-style entry animation for payloads landing in the agent panel.
|
|
8938
|
+
*
|
|
8939
|
+
* Pure DOM + Web Animations API — no Chart.js, no Angular animations module,
|
|
8940
|
+
* no CSS transitions racing layout. Honours `prefers-reduced-motion`: the
|
|
8941
|
+
* ghost is appended then removed without animating when the user asked for
|
|
8942
|
+
* less motion (so DOM side-effects stay consistent).
|
|
8943
|
+
*
|
|
8944
|
+
* Lifecycle:
|
|
8945
|
+
* 1. The agent panel calls {@link registerTarget} in `ngAfterViewInit`
|
|
8946
|
+
* with its header element.
|
|
8947
|
+
* 2. A source app dispatches an `AgentAction` carrying an `originRect`
|
|
8948
|
+
* from `getBoundingClientRect()` on the click target.
|
|
8949
|
+
* 3. The bus subscriber calls {@link flyInto} with that rect.
|
|
8950
|
+
* 4. The animator creates a fixed-position ghost at the origin, animates
|
|
8951
|
+
* transform + opacity toward the registered target's rect, then
|
|
8952
|
+
* removes itself on `onfinish` / `oncancel`.
|
|
8953
|
+
*
|
|
8954
|
+
* Uses `getBoundingClientRect()` (physical viewport coords) so the animation
|
|
8955
|
+
* is RTL-correct without inset-inline math — the rect already encodes the
|
|
8956
|
+
* physical position regardless of `dir`.
|
|
8957
|
+
*
|
|
8958
|
+
* The 900 ms duration and easing curve are deliberately hardcoded — making
|
|
8959
|
+
* them configurable surfaces an API the host can't usefully tune without
|
|
8960
|
+
* understanding motion design as a whole.
|
|
8512
8961
|
*/
|
|
8513
|
-
|
|
8514
|
-
|
|
8962
|
+
declare class AgentFlightAnimator {
|
|
8963
|
+
/** Hardcoded — see class doc. */
|
|
8964
|
+
private static readonly DURATION_MS;
|
|
8965
|
+
private static readonly EASING;
|
|
8966
|
+
/** Floor the target/source scale ratio so a tiny target rect doesn't
|
|
8967
|
+
* collapse the ghost to invisibility before the animation finishes. */
|
|
8968
|
+
private static readonly MIN_SCALE;
|
|
8969
|
+
private targetEl;
|
|
8970
|
+
/** Called by the panel host to publish where flights should land. Pass
|
|
8971
|
+
* `null` on destroy so a re-mounted panel doesn't leave the animator
|
|
8972
|
+
* pointing at a detached node. */
|
|
8973
|
+
registerTarget(el: HTMLElement | null): void;
|
|
8515
8974
|
/**
|
|
8516
|
-
*
|
|
8517
|
-
*
|
|
8975
|
+
* Animate a ghost element from {@link from} to the registered target's
|
|
8976
|
+
* rect. No-ops when:
|
|
8977
|
+
* - no target is registered (silent — panel may not be mounted yet)
|
|
8978
|
+
* - running outside a browser (SSR safety)
|
|
8979
|
+
* - the user has `prefers-reduced-motion: reduce` set (DOM is still
|
|
8980
|
+
* touched so callers see consistent side-effects, but no animation
|
|
8981
|
+
* runs)
|
|
8518
8982
|
*
|
|
8519
|
-
*
|
|
8520
|
-
*
|
|
8521
|
-
* cannot `dispose()` the newer one out of the slot, but it *can* still take the
|
|
8522
|
-
* slot back by publishing. Symmetry would need a "newest publisher wins" rule
|
|
8523
|
-
* enforced on write, which would make the first publish of a replacement
|
|
8524
|
-
* publisher silently drop whenever two live views briefly share a key. The
|
|
8525
|
-
* exposure is bounded: two live publishers on one owner key only happen while a
|
|
8526
|
-
* view is being replaced in place, and the loser re-publishes on its next
|
|
8527
|
-
* selection change. The unbounded case — a publisher that outlives its window —
|
|
8528
|
-
* is closed by `clear()`'s tombstone, not by write ordering.
|
|
8529
|
-
*/
|
|
8530
|
-
publish(contribution: MagicBarContribution): void;
|
|
8531
|
-
/**
|
|
8532
|
-
* Release the slot. Idempotent, and a no-op if another publisher has since
|
|
8533
|
-
* taken this owner key — the same stale-handle rule the sibling registries use.
|
|
8983
|
+
* The ghost is appended to `document.body` (not the panel) so a parent
|
|
8984
|
+
* `overflow: hidden` on the panel can't clip the flight path.
|
|
8534
8985
|
*/
|
|
8535
|
-
|
|
8986
|
+
flyInto(from: DOMRect, opts?: {
|
|
8987
|
+
previewHtml?: string;
|
|
8988
|
+
}): void;
|
|
8989
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AgentFlightAnimator, never>;
|
|
8990
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<AgentFlightAnimator>;
|
|
8536
8991
|
}
|
|
8537
8992
|
|
|
8538
8993
|
/**
|
|
@@ -8813,6 +9268,36 @@ interface MagicBarSearchSeed {
|
|
|
8813
9268
|
*/
|
|
8814
9269
|
declare function magicBarSearchText(previous: MagicBarSearchSeed | null, next: MagicBarSearchSeed): string | null;
|
|
8815
9270
|
|
|
9271
|
+
/**
|
|
9272
|
+
* Order one group's items the way every FlyOS bar orders them.
|
|
9273
|
+
*
|
|
9274
|
+
* **Icon-only actions occupy the outer edge of the flow — the right in LTR — in the precedence
|
|
9275
|
+
* Add, Delete, Edit reading inward; labelled (icon+label) actions sit inside them.**
|
|
9276
|
+
*
|
|
9277
|
+
* The outer edge is where the hand and the eye finish, so it belongs to the actions that need no
|
|
9278
|
+
* reading: a bare glyph is fastest to hit and slowest to identify, and putting the glyphs where
|
|
9279
|
+
* they are found by position rather than by reading is what makes that trade pay. A labelled
|
|
9280
|
+
* action is identified by its text wherever it sits, so it gives the edge up.
|
|
9281
|
+
*
|
|
9282
|
+
* Order is expressed as FLOW order, never as physical left/right: the bar mirrors under RTL, so
|
|
9283
|
+
* "outermost" becomes the left edge in `ar`/`ur` automatically. Encoding it as a physical side
|
|
9284
|
+
* would be a bug in three of this platform's four locales.
|
|
9285
|
+
*
|
|
9286
|
+
* Stable within each band — callers keep authoring items in whatever order reads best in source,
|
|
9287
|
+
* and two labelled actions stay in the order they were written (PPM's "Promote to schedule" stays
|
|
9288
|
+
* after "Add backlog task").
|
|
9289
|
+
*
|
|
9290
|
+
* ## Why this lives in the design system
|
|
9291
|
+
* It shipped first inside PPM (`ppm/shared/magic-bar-order.util.ts`) and
|
|
9292
|
+
* `skills/magic-bar-view-contributions.md` §7 named that file as the reference implementation —
|
|
9293
|
+
* which is exactly the shape of a rule that is about to be copy-pasted into the next External App.
|
|
9294
|
+
* The ordering is a property of the BAR, not of any one app: the same renderer paints every
|
|
9295
|
+
* contribution, so two apps disagreeing about it is a platform-visible inconsistency, not a local
|
|
9296
|
+
* style choice. Same reasoning as {@link magicBarSearchText} — a documented-but-unimplemented rule
|
|
9297
|
+
* gets re-derived per consumer, and the copies disagree on precisely the case that is hard to see.
|
|
9298
|
+
*/
|
|
9299
|
+
declare function orderMagicBarItems(items: readonly MagicBarAction[]): MagicBarAction[];
|
|
9300
|
+
|
|
8816
9301
|
/**
|
|
8817
9302
|
* Allowlist parser for {@link MagicBarActionSpec.iconPath} — the geometry-only
|
|
8818
9303
|
* gate between a publisher-supplied glyph fragment and the DOM.
|
|
@@ -9034,6 +9519,15 @@ declare class FlyMagicActionsComponent {
|
|
|
9034
9519
|
* what stops `@for (…; track $index)` rebuilding the glyph each time.
|
|
9035
9520
|
*/
|
|
9036
9521
|
protected iconNodes(action: MagicBarActionView): readonly FlyMagicBarIconNode[];
|
|
9522
|
+
/**
|
|
9523
|
+
* Whether this action has a glyph to paint at all.
|
|
9524
|
+
*
|
|
9525
|
+
* Derived from the PARSED nodes, never from `iconPath` being a non-empty string: a fragment the
|
|
9526
|
+
* allowlist rejected parses to zero nodes, and treating that as "has an icon" would paint an
|
|
9527
|
+
* empty `<svg>` box — on a labelled action, a permanent gap in front of the text. The parse
|
|
9528
|
+
* memoizes, so asking twice costs nothing.
|
|
9529
|
+
*/
|
|
9530
|
+
protected hasGlyph(action: MagicBarActionView): boolean;
|
|
9037
9531
|
/** `null` (not `'default'`) so `[attr.data-tone]` omits the attribute entirely for the common case. */
|
|
9038
9532
|
protected toneAttr(action: MagicBarActionView): string | null;
|
|
9039
9533
|
/**
|
|
@@ -9164,6 +9658,17 @@ declare const FLY_MAGIC_BAR_ICONS: {
|
|
|
9164
9658
|
* the settings gear, not the mode switcher).
|
|
9165
9659
|
*/
|
|
9166
9660
|
readonly calendarView: "<rect x=\"3.5\" y=\"3.5\" width=\"17\" height=\"17\" rx=\"2.5\"/><path d=\"M3.5 12h17M12 3.5v17\"/>";
|
|
9661
|
+
/**
|
|
9662
|
+
* Gantt / outline "Indent" — the block pushed in, with the arrow pointing INTO the indent.
|
|
9663
|
+
* Pairs with {@link outdent}: the two differ only in the arrow, which is the convention every
|
|
9664
|
+
* word processor and desktop planner has shipped for decades and the reason both stay icon-only.
|
|
9665
|
+
*
|
|
9666
|
+
* Directional, so publishers pass `mirrorInRtl: true` alongside it — the block sits on the
|
|
9667
|
+
* reading-start side, which is the right edge in `ar`/`ur`.
|
|
9668
|
+
*/
|
|
9669
|
+
readonly indent: "<path d=\"M4 5h16M4 19h16\"/><path d=\"M11 9.7h9M11 14.3h9\"/><path d=\"M4.5 9.7 7.5 12l-3 2.3\"/>";
|
|
9670
|
+
/** Gantt / outline "Outdent" — {@link indent}'s block with the arrow pulling back out. */
|
|
9671
|
+
readonly outdent: "<path d=\"M4 5h16M4 19h16\"/><path d=\"M11 9.7h9M11 14.3h9\"/><path d=\"M7.5 9.7 4.5 12l3 2.3\"/>";
|
|
9167
9672
|
/** `UX/FlyOS Desktop-app/MainContent.dc.html:927` (`pubTabActions`'s local `P` table). */
|
|
9168
9673
|
readonly addEvidence: "<path d=\"M10.5 13.5a4 4 0 0 0 5.7 0l2-2a4 4 0 0 0-5.7-5.7l-.6.6\"/><path d=\"M13.5 10.5a4 4 0 0 0-5.7 0l-2 2a4 4 0 0 0 4.2 6.5\"/><path d=\"M17.5 15.5v5M15 18h5\"/>";
|
|
9169
9674
|
/** `MainContent.dc.html:928`. Reused for every "Edit …" action (evidence, link, task). */
|
|
@@ -14314,6 +14819,6 @@ declare const AUDIENCE_ERROR_CODES: {
|
|
|
14314
14819
|
};
|
|
14315
14820
|
type AudienceErrorCode = (typeof AUDIENCE_ERROR_CODES)[keyof typeof AUDIENCE_ERROR_CODES];
|
|
14316
14821
|
|
|
14317
|
-
export { AGENT_DRAG_MIME, AGENT_PAYLOAD_VERSION, APP_LOOKUP, AUDIENCE_ERROR_CODES, AUDIENCE_LIMITS, AUDIENCE_PRESETS, AUDIENCE_TERM_KINDS, AgentActionBus, AgentActionUnsupportedDispatchError, AgentCommandRegistry, AgentDropRegistry, AgentFlightAnimator, AgentLookupRegistry, AgentPayloadOversizeError, AudienceBuilderComponent, AuthService, BilingualFieldComponent, CRON_MODES, CRON_WEEKDAYS, ContextMenuComponent, DEFAULT_AGENT_PAYLOAD_LIMITS, DEFAULT_FLY_THEME_MODE, DS_BASELINE_LOCALES, DashboardKpiComponent, DialogResult, ENTITY_LINK_LAUNCHER, EntityLookupComponent, FLYOS_LAUNCH_EVENT, FLYOS_LAUNCH_REQUEST_EVENT, FLYOS_REMOTE_ROUTE_EVENT, FLY_ACCENT_PROPERTY, FLY_ADMIN_ROLES, FLY_CHUNK_RELOAD_FLAG, FLY_COMPACT_THRESHOLD, FLY_COUNTRIES, FLY_CURRENCIES_BRIEF_ENDPOINT, FLY_CURRENCY_DEFAULT_ENDPOINT, FLY_EMOJI_BY_ID, FLY_EMOJI_CATEGORIES, FLY_EMOJI_CATEGORY_BY_ID, FLY_EMOJI_DEFAULT_CATEGORIES, FLY_EMOJI_PACK, FLY_EMOJI_PACK_MISSING_MESSAGE, FLY_EMOJI_PREVIEW_COUNT, FLY_EMPTY_VALUE, FLY_LOCALE_CATALOG, FLY_MAGIC_BAR_EVENT, FLY_MAGIC_BAR_ICONS, FLY_MAGIC_BAR_STORE_KEY, FLY_NF_CACHE_HEAL_FLAG, FLY_RELOAD_DEBOUNCE_MS, FLY_RELOAD_REARM_MS, FLY_REMOTE_BASE_PATH, FLY_REMOTE_CONTEXT_EVENT, FLY_REMOTE_CONTEXT_STORE_KEY, FLY_REMOTE_OUTLET_DEPTH, FLY_REMOTE_ROUTES, FLY_SCAN_PENDING_DEFAULT_DELAY_MS, FLY_SCAN_PENDING_MAX_RETRIES, FLY_SCAN_PENDING_STATUS, FLY_SEARCH_DEBOUNCE_MS, FLY_SKIN_TONES, FLY_STANDALONE_AUTH_CONFIG, FLY_STRATEGY_OBJECTIVES_LOOKUP_ENDPOINT, FLY_THEME_MODE_IDS, FLY_VIEWPORT_IS_MOBILE, FLY_WINDOW_BREADCRUMBS_EVENT, FLY_WINDOW_BREADCRUMBS_STORE_KEY, FLY_WINDOW_HELP_HINT_EVENT, FLY_WINDOW_PAGE_TITLE_EVENT, FlyAchievementProgressComponent, FlyActionMenuComponent, FlyActionStackComponent, FlyAgentDraggableDirective, FlyAnimatedEmojiComponent, FlyAppHomeComponent, FlyAppTopbarComponent, FlyAppUnavailableComponent, FlyAuthLiveRefresh, FlyBadgeWallComponent, FlyBlockUiComponent, FlyBreadcrumbComponent, FlyButtonComponent, FlyBytesPipe, FlyCaptchaComponent, FlyCardActionsComponent, FlyCardBodyComponent, FlyCardComponent, FlyCardFooterComponent, FlyCardGridComponent, FlyCardMediaComponent, FlyCardMetaComponent, FlyCardStatusComponent, FlyCardTitleComponent, FlyCellDirective, FlyCheckboxComponent, FlyChipComponent, FlyChunkReloadErrorHandler, FlyClickOutsideDirective, FlyCollapsibleComponent, FlyCommentThreadComponent, FlyCompactNumberPipe, FlyConfirmDialogComponent, FlyControlDirective, FlyCronBuilderComponent, FlyCurrencyCatalogService, FlyCurrencySelectorComponent, FlyDataTableComponent, FlyDatePipe, FlyDateTimePipe, FlyDebouncer, FlyDecimalNumberPipe, FlyDeepLinkPrefetchService, FlyDetailCardComponent, FlyDetailShellComponent, FlyDrawerComponent, FlyDurationPipe, FlyDynamicFormComponent, FlyEmojiPickerComponent, FlyFieldComponent, FlyFileDownloadService, FlyFileUploadComponent, FlyFilterPanelComponent, FlyFormBannerComponent, FlyFormFooterComponent, FlyFormGridComponent, FlyFormSectionComponent, FlyFullNumberPipe, FlyGanttComponent, FlyHubClient, FlyIconButtonComponent, FlyIfAdminDirective, FlyIfRoleDirective, FlyImageUploadComponent, FlyLeaderboardComponent, FlyLifecyclePipelineComponent, FlyMagicActionsComponent, FlyMetaListComponent, FlyModalComponent, FlyModerationQueueComponent, FlyModuleIconDirective, FlyMoneyPipe, FlyOverviewKpiRowComponent, FlyOverviewRowsComponent, FlyOverviewSectionComponent, FlyOverviewSurfaceComponent, FlyPagerComponent, FlyPaginationComponent, FlyPeoplePickerComponent, FlyPointsTierComponent, FlyProgressComponent, FlyRelativeTimePipe, FlyRemoteContextService, FlyRemoteRouter, FlyRemoteRouterOutletComponent, FlySearchInputComponent, FlySectionHeaderComponent, FlySecureSrcDirective, FlySegmentedComponent, FlySelectComponent, FlySkeletonComponent, FlySliderComponent, FlySparklineComponent, FlySpinnerComponent, FlyStandaloneAuthCallbackComponent, FlyStandaloneAuthService, FlyStandaloneMagicActionsComponent, FlyStateMessageComponent, FlyStrategySelectorComponent, FlyDynamicFormComponent as FlySurveyFormComponent, FlyTabComponent, FlyTabsComponent, FlyTagsInputComponent, FlyThemeService, FlyTimePipe, FlyToastService, FlyToggleComponent, FlyTooltipDirective, FlyTreeNavComponent, FlyTypeaheadComponent, FlyUserDirectoryService, FlyWindowHelpService, FlyWindowTitleService, FlyosPendingLaunchesGlobalKey, FlyosShellHandlesLaunchRequestsGlobalKey, FlyosShellOwnsHistoryGlobalKey, GANTT_DEPENDENCY_TYPES, GANTT_ROW_TINT_ALPHA, GANTT_ZOOMS, I18nService, LAUNCH_CONTEXT, MAGIC_BAR_SEARCH_WIDTH_DEFAULT, MAGIC_BAR_SEARCH_WIDTH_MAX, MAGIC_BAR_SEARCH_WIDTH_MIN, MagicBarRegistry, MessageBoxButtons, MessageBoxComponent, MessageBoxIcon, MessageBoxService, MockAuthService, NOVA_PRIORITY_TONE, NOVA_STATUS_TONE, NOVA_TONE_FALLBACK, OverlayStack, PRESENCE_COLORS, PageHeaderComponent, RTL_LOCALE_SET, SHARE_ORG_CHART_SYSTEM_KEY_APPS, SHARE_ORG_CHART_SYSTEM_KEY_DEFAULT, SHARE_PANEL_DEFAULT_FILE_LEVELS, STATE_DEFAULT_ICONS, STATE_DEFAULT_MESSAGE_KEYS, STEP_UP_CODE, STEP_UP_REAUTH_HANDLER, STEP_UP_RETURN_KEY, SUPPORTED_AGENT_PAYLOAD_VERSIONS, SharePanelComponent, SourceAppResolver, StandaloneWindowManagerService, StatusBadgeComponent, StepUpService, ToastHostComponent, TranslatePipe, WINDOW_DATA, WINDOW_HELP_HINT, WindowBreadcrumbsRegistry, WindowManagerService, applySkinTone, applySuggestion, ariaSort, buildCron, canConfirm, canGoNext$1 as canGoNext, canGoPrev$1 as canGoPrev, captureFocus, clampMagicBarSearchWidth, clampPage$1 as clampPage, clampSliderValue, connectRemoteLaunch, deepestFlyMatch, enterActivatesNatively, filterGroup, filterSuggestions, findLocaleByDialect, findLocaleByPrefix, firstEnabledIndex, firstModuleIndex, flattenModules, flyAdminGuard, flyApiErrorMessage, flyCaptchaBase64Utf8, flyCaptchaBuildToken, flyCaptchaSha256Hex, flyCompactNumber, flyDebounced, flyDecimalNumber, flyDownloadBlob, flyDuration, flyEmojiFor, flyEmojiIsTonable, flyEmojiPackUrl, flyExportFileName, flyFirstEnabledIndex, flyFormatBytes, flyFormatDate, flyFormatDateTime, flyFormatMoney, flyFormatTime, flyFullNumber, flyNextEnabledIndex, flyNextSegmentIndex, flyRelativeTime, flyResolveActiveTab, flyRoleGuard, flyScanPendingDelayMs, flyScanRetry, flySignedCompact, flySkinToneLabelKey, flyStandaloneAuthGuard, flyStandaloneAuthInterceptor, flyToDateOnly, flyToPage, flyUnwrap, flyUnwrapCurrencies, flyUnwrapCurrency, flyUnwrapLenient, flyUnwrapObjectiveLookup, hasAnyRoleIn, healNativeFederationCacheOnce, initialExpanded, isAccentColor, isChunkLoadError, isFlyAuthStorePopulated, isNativeFederationCacheError, isRtlLocale, isRtlLocaleEntry, isValidCron, isValidSingleField, loadRemoteStyles, magicBarOwnerKey, magicBarSearchText, matchFlyRoutePattern, matchFlyRoutePrefix, matchFlyRouteTable, nextEnabledIndex, nextModuleIndex, nextSegmentIndex, nextSort, normalizeFlyTheme, normalizeRoles, novaPriorityToneVar, novaStatusToneVar, overlayStack, canGoNext as pagerCanGoNext, canGoPrev as pagerCanGoPrev, clampPage as pagerClampPage, parseCron, parseStepUpChallenge, parseTags, prefetchRemoteStyles, presenceColorFor, printConsoleSecurityWarning, provideFlyChunkReloadRecovery, provideFlyEmojiPack, provideFlyOfflineAuth, provideFlyStandaloneAuth, reloadOnceForChunkError, requestAppLaunch, resolveActiveModule, resolveActiveSection, resolveActiveTab, resolveCellValue, resolveStateIcon, resolveStateMessageKey, restoreFocus, sameTags, sectionHintKey, sectionLayout, sliderTrackGradient, sparklinePath, sparklinePoints, stepUpInterceptor, stepUpReturnKey, trimAgentPayload, trimAgentString, unloadRemoteStyles, utf8ByteLength, validateAgentPayload, warnIfEmbeddedSessionMissing };
|
|
14318
|
-
export type { ActionMenuItem, AgentAction, AgentActionDispatch, AgentActionVerb, AgentChipHostInputs, AgentCommand, AgentCommandContextBinding, AgentCommandHandle, AgentCommandRegistration, AgentCommandScope, AgentCommandSlashSpec, AgentDragPayload, AgentDraggableItem, AgentDropChipMode, AgentDropRendererRegistration, AgentEnvelopeAttachment, AgentMcpScope, AgentMessageEnvelope, AgentPayloadLimits, AgentPayloadValidationResult, AppEveryonePrincipal, AppEveryoneTerm, AppLookup, AppLookupEntry, AudienceEditTarget, AudienceErrorCode, AudienceFilter, AudienceOptions, AudiencePresetKind, AudienceTerm, AudienceTermKind, BreadcrumbItem, ButtonSize, ButtonVariant, CardDensity, CardLayout, ChartTerm, ChildWindowData, ChipTone, ConfirmKind, ConnectRemoteLaunchOptions, ContextMenuAlign, ContextMenuItem, ContextMenuSection, CronAdvancedFieldDef, CronMode, CronParts, CronWeekday, DesktopApp, DesktopAppCategory, DesktopAppKind, DetailSection, DialogResultWithAcknowledgement, EmbeddedSessionProbe, EntityLinkLauncher, EntityLinkSelection, FilterGroup, FlyAchievementRow, FlyApiError, FlyApiResponse, FlyAppHomeLayout, FlyAppModule, FlyAppModuleSection, FlyAppUnavailableState, FlyAuthRefreshPayload, FlyAuthStoreReadable, FlyBadgeTile, FlyBreadcrumbItem, FlyCaptchaChallenge, FlyCaptchaSolution, FlyCaptchaState, FlyCellContext, FlyColumn, FlyColumnKind, FlyComment, FlyCommentDeleteRequest, FlyCommentEditRequest, FlyCommentLoadMoreRequest, FlyCommentLoadRepliesRequest, FlyCommentLockToggleRequest, FlyCommentPage, FlyCommentReportReason, FlyCommentReportRequest, FlyCommentReportStatus, FlyCommentSubmitRequest, FlyCountry, FlyCurrency, FlyCurrencyFetchFn, FlyCurrencySelectorMode, FlyCurrencySelectorValue, FlyDeepLinkPrefetchRoute, FlyDrawerBodyPadding, FlyDrawerPosition, FlyDrawerSide, FlyDrawerSize, FlyDrawerVariant, FlyEmojiCategory, FlyEmojiCell, FlyEmojiEntry, FlyEmojiPack, FlyEmojiPackEntry, FlyEmojiPackManifest, FlyEmojiPickerSize, FlyEmojiPickerTab, FlyEmojiSection, FlyFileInfo, FlyFileSelection, FlyFormAnswer, FlyFormAnswerValue, FlyFormDefinition, FlyFormFieldOptions, FlyFormOption, FlyFormQuestion, FlyFormQuestionType, FlyFormScoreDisplay, FlyFormatMoneyOptions, FlyLaunchEventDetail, FlyLaunchRequestDetail, FlyLeaderboardRow, FlyLiveRefreshOptions, FlyLocaleEntry, FlyMagicBarIconName, FlyMetaItem, FlyModerationLoadPageRequest, FlyModerationLockThreadRequest, FlyModerationOpenSubjectRequest, FlyModerationReport, FlyModerationReportPage, FlyModerationResolutionStatus, FlyModerationResolveRequest, FlyMoneyDisplay, FlyNavigableItem, FlyOfflineAuthConfig, FlyPageMeta, FlyPageResult, FlyPaged, FlyPeoplePickerMode, FlyPeoplePickerOption, FlyPeopleSearchFn, FlyPointsSummary, FlyRemoteContext, FlyRemoteEagerRoute, FlyRemoteLazyRoute, FlyRemoteLoadedComponent, FlyRemoteMatch, FlyRemoteRoute, FlyRemoteRouteEventDetail, FlySearchExpandTrigger, FlySearchInputSize, FlySecureSrcState, FlySelectOption, FlySelectValue, FlySkeletonAnimation, FlySkeletonLayout, FlySkeletonShape, FlySkinTone, FlySort, FlyStandaloneAuthConfig, FlyStrategyObjectiveRef, FlyStrategyObjectiveSearchFn, FlyFileSelection as FlySurveyFileSelection, FlyFormAnswer as FlySurveyFormAnswer, FlyFormAnswerValue as FlySurveyFormAnswerValue, FlyFormDefinition as FlySurveyFormDefinition, FlyFormFieldOptions as FlySurveyFormFieldOptions, FlyFormOption as FlySurveyFormOption, FlyFormQuestion as FlySurveyFormQuestion, FlyFormQuestionType as FlySurveyQuestionType, FlyTenantDefaultCurrencyFetchFn, FlyThemeMode, FlyTooltipPlacement, FlyTreeNavNode, FlyTypeaheadOption, FlyWindowHelpHintEventDetail, FlyWindowHelpPublisher, FlyWindowPageTitleEventDetail, FlyWindowTitlePublisher, FlyosPendingLaunches, FocusRestore, FormBannerKind, GanttDependency, GanttDependencyCreate, GanttDependencyDelete, GanttDependencyType, GanttRow, GanttRowDatesChange, GanttRowKind, GanttZoom, IconButtonVariant, LaunchContext, LifecycleRollupItem, LifecycleStep, LoadBundleOptions, LoadRemoteStylesOptions, LookupDescriptor, LookupHandle, LookupRegistration, LookupResult, LookupSearch, MagicBarAction, MagicBarActionKind, MagicBarActionSpec, MagicBarActionView, MagicBarContribution, MagicBarGroup, MagicBarGroupSpec, MagicBarGroupView, MagicBarOwnerRef, MagicBarPublisher, MagicBarRadioMenu, MagicBarRadioMenuSpec, MagicBarRadioMenuView, MagicBarRadioOption, MagicBarSearch, MagicBarSearchSeed, MagicBarSearchSpec, MagicBarSearchView, MagicBarTextParams, MagicBarTone, MagicBarView, MessageBoxButton, MessageBoxDontAskAgainConfig, MessageBoxOptions, MessageBoxOptionsWithAcknowledgement, MockAuthConfig, OpenWindowOptions, OuPrincipal, OuTerm, OverlayHandle, OverviewKpiItem, OverviewKpiTone, OverviewRow, PageHeaderVariant, PresetTerm, ProgressTone, RemoteAppDef, RequestAppLaunchOptions, RoleOuLookupRow, RolePrincipal, RolesTerm, SegmentedOption, SegmentedVariant, ShareOrgChartOption, ShareOuNode, SharePanelLevelOption, SharePermissionEntry, SharePrincipal, SharePrincipalKind, ShareUserResult, StateMessageKind, StepUpChallenge, StepUpReauthHandler, StepUpReauthRequest, TabsVariant, ToastAction, ToastEntry, ToastOptions, ToastVariant, User, UserPrincipal, UsersTerm, WindowBreadcrumb, WindowHelpHint, WindowInstance, WindowState };
|
|
14822
|
+
export { AGENT_DRAG_MIME, AGENT_PAYLOAD_VERSION, APP_LOOKUP, AUDIENCE_ERROR_CODES, AUDIENCE_LIMITS, AUDIENCE_PRESETS, AUDIENCE_TERM_KINDS, AgentActionBus, AgentActionUnsupportedDispatchError, AgentCommandRegistry, AgentDropRegistry, AgentFlightAnimator, AgentLookupRegistry, AgentPayloadOversizeError, AudienceBuilderComponent, AuthService, BilingualFieldComponent, CRON_MODES, CRON_WEEKDAYS, ContextMenuComponent, DEFAULT_AGENT_PAYLOAD_LIMITS, DEFAULT_FLY_THEME_MODE, DS_BASELINE_LOCALES, DashboardKpiComponent, DialogResult, ENTITY_LINK_LAUNCHER, EntityLookupComponent, FLYOS_LAUNCH_EVENT, FLYOS_LAUNCH_REQUEST_EVENT, FLYOS_REMOTE_ROUTE_EVENT, FLY_ACCENT_PROPERTY, FLY_ADMIN_ROLES, FLY_CHUNK_RELOAD_FLAG, FLY_COMPACT_THRESHOLD, FLY_COUNTRIES, FLY_CURRENCIES_BRIEF_ENDPOINT, FLY_CURRENCY_DEFAULT_ENDPOINT, FLY_EMOJI_BY_ID, FLY_EMOJI_CATEGORIES, FLY_EMOJI_CATEGORY_BY_ID, FLY_EMOJI_DEFAULT_CATEGORIES, FLY_EMOJI_PACK, FLY_EMOJI_PACK_MISSING_MESSAGE, FLY_EMOJI_PREVIEW_COUNT, FLY_EMPTY_VALUE, FLY_GANTT_DEFAULTS, FLY_LOCALE_CATALOG, FLY_MAGIC_BAR_EVENT, FLY_MAGIC_BAR_ICONS, FLY_MAGIC_BAR_STORE_KEY, FLY_NF_CACHE_HEAL_FLAG, FLY_RELOAD_DEBOUNCE_MS, FLY_RELOAD_REARM_MS, FLY_REMOTE_BASE_PATH, FLY_REMOTE_CONTEXT_EVENT, FLY_REMOTE_CONTEXT_STORE_KEY, FLY_REMOTE_OUTLET_DEPTH, FLY_REMOTE_ROUTES, FLY_SCAN_PENDING_DEFAULT_DELAY_MS, FLY_SCAN_PENDING_MAX_RETRIES, FLY_SCAN_PENDING_STATUS, FLY_SEARCH_DEBOUNCE_MS, FLY_SKIN_TONES, FLY_STANDALONE_AUTH_CONFIG, FLY_STRATEGY_OBJECTIVES_LOOKUP_ENDPOINT, FLY_THEME_MODE_IDS, FLY_VIEWPORT_IS_MOBILE, FLY_WINDOW_BREADCRUMBS_EVENT, FLY_WINDOW_BREADCRUMBS_STORE_KEY, FLY_WINDOW_HELP_HINT_EVENT, FLY_WINDOW_PAGE_TITLE_EVENT, FlyAchievementProgressComponent, FlyActionMenuComponent, FlyActionStackComponent, FlyAgentDraggableDirective, FlyAnimatedEmojiComponent, FlyAppHomeComponent, FlyAppTopbarComponent, FlyAppUnavailableComponent, FlyAuthLiveRefresh, FlyBadgeWallComponent, FlyBlockUiComponent, FlyBreadcrumbComponent, FlyButtonComponent, FlyBytesPipe, FlyCaptchaComponent, FlyCardActionsComponent, FlyCardBodyComponent, FlyCardComponent, FlyCardFooterComponent, FlyCardGridComponent, FlyCardMediaComponent, FlyCardMetaComponent, FlyCardStatusComponent, FlyCardTitleComponent, FlyCellDirective, FlyCheckboxComponent, FlyChipComponent, FlyChunkReloadErrorHandler, FlyClickOutsideDirective, FlyCollapsibleComponent, FlyCommentThreadComponent, FlyCompactNumberPipe, FlyConfirmDialogComponent, FlyControlDirective, FlyCronBuilderComponent, FlyCurrencyCatalogService, FlyCurrencySelectorComponent, FlyDataTableComponent, FlyDatePipe, FlyDateTimePipe, FlyDebouncer, FlyDecimalNumberPipe, FlyDeepLinkPrefetchService, FlyDetailCardComponent, FlyDetailShellComponent, FlyDrawerComponent, FlyDurationPipe, FlyDynamicFormComponent, FlyEmojiPickerComponent, FlyFieldComponent, FlyFileDownloadService, FlyFileUploadComponent, FlyFilterPanelComponent, FlyFormBannerComponent, FlyFormFooterComponent, FlyFormGridComponent, FlyFormSectionComponent, FlyFullNumberPipe, FlyGanttComponent, FlyHubClient, FlyIconButtonComponent, FlyIfAdminDirective, FlyIfRoleDirective, FlyImageUploadComponent, FlyLeaderboardComponent, FlyLifecyclePipelineComponent, FlyMagicActionsComponent, FlyMetaListComponent, FlyModalComponent, FlyModerationQueueComponent, FlyModuleIconDirective, FlyMoneyPipe, FlyOverviewKpiRowComponent, FlyOverviewRowsComponent, FlyOverviewSectionComponent, FlyOverviewSurfaceComponent, FlyPagerComponent, FlyPaginationComponent, FlyPeoplePickerComponent, FlyPointsTierComponent, FlyProgressComponent, FlyRelativeTimePipe, FlyRemoteContextService, FlyRemoteRouter, FlyRemoteRouterOutletComponent, FlySearchInputComponent, FlySectionHeaderComponent, FlySecureSrcDirective, FlySegmentedComponent, FlySelectComponent, FlySkeletonComponent, FlySliderComponent, FlySparklineComponent, FlySpinnerComponent, FlyStandaloneAuthCallbackComponent, FlyStandaloneAuthService, FlyStandaloneMagicActionsComponent, FlyStateMessageComponent, FlyStrategySelectorComponent, FlyDynamicFormComponent as FlySurveyFormComponent, FlyTabComponent, FlyTabsComponent, FlyTagsInputComponent, FlyThemeService, FlyTimePipe, FlyToastService, FlyToggleComponent, FlyTooltipDirective, FlyTreeNavComponent, FlyTypeaheadComponent, FlyUserDirectoryService, FlyWindowHelpService, FlyWindowTitleService, FlyosPendingLaunchesGlobalKey, FlyosShellHandlesLaunchRequestsGlobalKey, FlyosShellOwnsHistoryGlobalKey, GANTT_DEPENDENCY_TYPES, GANTT_LABEL_W_DEFAULT, GANTT_LABEL_W_MAX, GANTT_LABEL_W_MIN, GANTT_ROW_TINT_ALPHA, GANTT_ZOOMS, I18nService, LAUNCH_CONTEXT, MAGIC_BAR_SEARCH_WIDTH_DEFAULT, MAGIC_BAR_SEARCH_WIDTH_MAX, MAGIC_BAR_SEARCH_WIDTH_MIN, MagicBarRegistry, MessageBoxButtons, MessageBoxComponent, MessageBoxIcon, MessageBoxService, MockAuthService, NOVA_PRIORITY_TONE, NOVA_STATUS_TONE, NOVA_TONE_FALLBACK, OverlayStack, PRESENCE_COLORS, PageHeaderComponent, RTL_LOCALE_SET, SHARE_ORG_CHART_SYSTEM_KEY_APPS, SHARE_ORG_CHART_SYSTEM_KEY_DEFAULT, SHARE_PANEL_DEFAULT_FILE_LEVELS, STATE_DEFAULT_ICONS, STATE_DEFAULT_MESSAGE_KEYS, STEP_UP_CODE, STEP_UP_REAUTH_HANDLER, STEP_UP_RETURN_KEY, SUPPORTED_AGENT_PAYLOAD_VERSIONS, SharePanelComponent, SourceAppResolver, StandaloneWindowManagerService, StatusBadgeComponent, StepUpService, ToastHostComponent, TranslatePipe, WINDOW_DATA, WINDOW_HELP_HINT, WindowBreadcrumbsRegistry, WindowManagerService, applyGanttRowReorder, applySkinTone, applySuggestion, ariaSort, buildCron, canConfirm, canGoNext$1 as canGoNext, canGoPrev$1 as canGoPrev, captureFocus, clampMagicBarSearchWidth, clampPage$1 as clampPage, clampSliderValue, connectRemoteLaunch, deepestFlyMatch, enterActivatesNatively, filterGanttRows, filterGroup, filterSuggestions, findLocaleByDialect, findLocaleByPrefix, firstEnabledIndex, firstModuleIndex, flattenModules, flyAdminGuard, flyApiErrorMessage, flyCaptchaBase64Utf8, flyCaptchaBuildToken, flyCaptchaSha256Hex, flyCompactNumber, flyDebounced, flyDecimalNumber, flyDownloadBlob, flyDuration, flyEmojiFor, flyEmojiIsTonable, flyEmojiPackUrl, flyExportFileName, flyFirstEnabledIndex, flyFormatBytes, flyFormatDate, flyFormatDateTime, flyFormatMoney, flyFormatTime, flyFullNumber, flyNextEnabledIndex, flyNextSegmentIndex, flyRelativeTime, flyResolveActiveTab, flyRoleGuard, flyScanPendingDelayMs, flyScanRetry, flySignedCompact, flySkinToneLabelKey, flyStandaloneAuthGuard, flyStandaloneAuthInterceptor, flyToDateOnly, flyToPage, flyUnwrap, flyUnwrapCurrencies, flyUnwrapCurrency, flyUnwrapLenient, flyUnwrapObjectiveLookup, ganttOutlineBarItems, ganttPeriodBarItem, hasAnyRoleIn, healNativeFederationCacheOnce, initialExpanded, isAccentColor, isChunkLoadError, isFlyAuthStorePopulated, isNativeFederationCacheError, isRtlLocale, isRtlLocaleEntry, isValidCron, isValidSingleField, loadRemoteStyles, magicBarOwnerKey, magicBarSearchText, matchFlyRoutePattern, matchFlyRoutePrefix, matchFlyRouteTable, nextEnabledIndex, nextModuleIndex, nextSegmentIndex, nextSort, normalizeFlyTheme, normalizeGanttSearchText, normalizeRoles, novaPriorityToneVar, novaStatusToneVar, orderMagicBarItems, overlayStack, canGoNext as pagerCanGoNext, canGoPrev as pagerCanGoPrev, clampPage as pagerClampPage, parseCron, parseStepUpChallenge, parseTags, prefetchRemoteStyles, presenceColorFor, printConsoleSecurityWarning, provideFlyChunkReloadRecovery, provideFlyEmojiPack, provideFlyGanttDefaults, provideFlyOfflineAuth, provideFlyStandaloneAuth, reloadOnceForChunkError, requestAppLaunch, resolveActiveModule, resolveActiveSection, resolveActiveTab, resolveCellValue, resolveStateIcon, resolveStateMessageKey, restoreFocus, sameTags, sectionHintKey, sectionLayout, sliderTrackGradient, sparklinePath, sparklinePoints, stepUpInterceptor, stepUpReturnKey, trimAgentPayload, trimAgentString, unloadRemoteStyles, utf8ByteLength, validateAgentPayload, warnIfEmbeddedSessionMissing };
|
|
14823
|
+
export type { ActionMenuItem, AgentAction, AgentActionDispatch, AgentActionVerb, AgentChipHostInputs, AgentCommand, AgentCommandContextBinding, AgentCommandHandle, AgentCommandRegistration, AgentCommandScope, AgentCommandSlashSpec, AgentDragPayload, AgentDraggableItem, AgentDropChipMode, AgentDropRendererRegistration, AgentEnvelopeAttachment, AgentMcpScope, AgentMessageEnvelope, AgentPayloadLimits, AgentPayloadValidationResult, AppEveryonePrincipal, AppEveryoneTerm, AppLookup, AppLookupEntry, AudienceEditTarget, AudienceErrorCode, AudienceFilter, AudienceOptions, AudiencePresetKind, AudienceTerm, AudienceTermKind, BreadcrumbItem, ButtonSize, ButtonVariant, CardDensity, CardLayout, ChartTerm, ChildWindowData, ChipTone, ConfirmKind, ConnectRemoteLaunchOptions, ContextMenuAlign, ContextMenuItem, ContextMenuSection, CronAdvancedFieldDef, CronMode, CronParts, CronWeekday, DesktopApp, DesktopAppCategory, DesktopAppKind, DetailSection, DialogResultWithAcknowledgement, EmbeddedSessionProbe, EntityLinkLauncher, EntityLinkSelection, FilterGroup, FlyAchievementRow, FlyApiError, FlyApiResponse, FlyAppHomeLayout, FlyAppModule, FlyAppModuleSection, FlyAppUnavailableState, FlyAuthRefreshPayload, FlyAuthStoreReadable, FlyBadgeTile, FlyBreadcrumbItem, FlyCaptchaChallenge, FlyCaptchaSolution, FlyCaptchaState, FlyCellContext, FlyColumn, FlyColumnKind, FlyComment, FlyCommentDeleteRequest, FlyCommentEditRequest, FlyCommentLoadMoreRequest, FlyCommentLoadRepliesRequest, FlyCommentLockToggleRequest, FlyCommentPage, FlyCommentReportReason, FlyCommentReportRequest, FlyCommentReportStatus, FlyCommentSubmitRequest, FlyCountry, FlyCurrency, FlyCurrencyFetchFn, FlyCurrencySelectorMode, FlyCurrencySelectorValue, FlyDeepLinkPrefetchRoute, FlyDrawerBodyPadding, FlyDrawerPosition, FlyDrawerSide, FlyDrawerSize, FlyDrawerVariant, FlyEmojiCategory, FlyEmojiCell, FlyEmojiEntry, FlyEmojiPack, FlyEmojiPackEntry, FlyEmojiPackManifest, FlyEmojiPickerSize, FlyEmojiPickerTab, FlyEmojiSection, FlyFileInfo, FlyFileSelection, FlyFormAnswer, FlyFormAnswerValue, FlyFormDefinition, FlyFormFieldOptions, FlyFormOption, FlyFormQuestion, FlyFormQuestionType, FlyFormScoreDisplay, FlyFormatMoneyOptions, FlyGanttDefaults, FlyLaunchEventDetail, FlyLaunchRequestDetail, FlyLeaderboardRow, FlyLiveRefreshOptions, FlyLocaleEntry, FlyMagicBarIconName, FlyMetaItem, FlyModerationLoadPageRequest, FlyModerationLockThreadRequest, FlyModerationOpenSubjectRequest, FlyModerationReport, FlyModerationReportPage, FlyModerationResolutionStatus, FlyModerationResolveRequest, FlyMoneyDisplay, FlyNavigableItem, FlyOfflineAuthConfig, FlyPageMeta, FlyPageResult, FlyPaged, FlyPeoplePickerMode, FlyPeoplePickerOption, FlyPeopleSearchFn, FlyPointsSummary, FlyRemoteContext, FlyRemoteEagerRoute, FlyRemoteLazyRoute, FlyRemoteLoadedComponent, FlyRemoteMatch, FlyRemoteRoute, FlyRemoteRouteEventDetail, FlySearchExpandTrigger, FlySearchInputSize, FlySecureSrcState, FlySelectOption, FlySelectValue, FlySkeletonAnimation, FlySkeletonLayout, FlySkeletonShape, FlySkinTone, FlySort, FlyStandaloneAuthConfig, FlyStrategyObjectiveRef, FlyStrategyObjectiveSearchFn, FlyFileSelection as FlySurveyFileSelection, FlyFormAnswer as FlySurveyFormAnswer, FlyFormAnswerValue as FlySurveyFormAnswerValue, FlyFormDefinition as FlySurveyFormDefinition, FlyFormFieldOptions as FlySurveyFormFieldOptions, FlyFormOption as FlySurveyFormOption, FlyFormQuestion as FlySurveyFormQuestion, FlyFormQuestionType as FlySurveyQuestionType, FlyTenantDefaultCurrencyFetchFn, FlyThemeMode, FlyTooltipPlacement, FlyTreeNavNode, FlyTypeaheadOption, FlyWindowHelpHintEventDetail, FlyWindowHelpPublisher, FlyWindowPageTitleEventDetail, FlyWindowTitlePublisher, FlyosPendingLaunches, FocusRestore, FormBannerKind, GanttDependency, GanttDependencyCreate, GanttDependencyDelete, GanttDependencyType, GanttRow, GanttRowDatesChange, GanttRowIndentChange, GanttRowKind, GanttRowReorder, GanttZoom, IconButtonVariant, LaunchContext, LifecycleRollupItem, LifecycleStep, LoadBundleOptions, LoadRemoteStylesOptions, LookupDescriptor, LookupHandle, LookupRegistration, LookupResult, LookupSearch, MagicBarAction, MagicBarActionKind, MagicBarActionSpec, MagicBarActionView, MagicBarContribution, MagicBarGroup, MagicBarGroupSpec, MagicBarGroupView, MagicBarOwnerRef, MagicBarPublisher, MagicBarRadioMenu, MagicBarRadioMenuSpec, MagicBarRadioMenuView, MagicBarRadioOption, MagicBarSearch, MagicBarSearchSeed, MagicBarSearchSpec, MagicBarSearchView, MagicBarTextParams, MagicBarTone, MagicBarView, MessageBoxButton, MessageBoxDontAskAgainConfig, MessageBoxOptions, MessageBoxOptionsWithAcknowledgement, MockAuthConfig, OpenWindowOptions, OuPrincipal, OuTerm, OverlayHandle, OverviewKpiItem, OverviewKpiTone, OverviewRow, PageHeaderVariant, PresetTerm, ProgressTone, RemoteAppDef, RequestAppLaunchOptions, RoleOuLookupRow, RolePrincipal, RolesTerm, SegmentedOption, SegmentedVariant, ShareOrgChartOption, ShareOuNode, SharePanelLevelOption, SharePermissionEntry, SharePrincipal, SharePrincipalKind, ShareUserResult, StateMessageKind, StepUpChallenge, StepUpReauthHandler, StepUpReauthRequest, TabsVariant, ToastAction, ToastEntry, ToastOptions, ToastVariant, User, UserPrincipal, UsersTerm, WindowBreadcrumb, WindowHelpHint, WindowInstance, WindowState };
|
|
14319
14824
|
//# sourceMappingURL=flyos-design-system.d.ts.map
|