@akcelik/strct 0.29.0 → 0.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akcelik/strct",
3
- "version": "0.29.0",
3
+ "version": "0.31.1",
4
4
  "description": "UIStruct — a standalone Angular component library with a tokenised, multi-palette theme system, built for datacenter / infrastructure management UIs.",
5
5
  "author": "Serkan Akcelik <serkan.akcelik@gmail.com>",
6
6
  "license": "MIT",
@@ -32,7 +32,8 @@
32
32
  "@angular/common": "^21.2.0",
33
33
  "@angular/core": "^21.2.0",
34
34
  "@angular/forms": "^21.2.0",
35
- "@angular/platform-browser": "^21.2.0"
35
+ "@angular/platform-browser": "^21.2.0",
36
+ "@angular/router": "^21.2.0"
36
37
  },
37
38
  "dependencies": {
38
39
  "tslib": "^2.3.0"
@@ -247,6 +247,22 @@ interface StrctRailItem {
247
247
  /** Badge colour (defaults to `accent`). When collapsed it renders as a dot. */
248
248
  badgeStatus?: StrctRailStatus;
249
249
  disabled?: boolean;
250
+ /** `'bottom'` pins the item to the foot of the rail (e.g. Administration). */
251
+ placement?: 'top' | 'bottom';
252
+ /**
253
+ * Render as a real router link (`<a routerLink>`): middle-click, ⌘/Ctrl-click
254
+ * and "open in new tab" work; `(select)` still fires on plain activation.
255
+ * When neither `routerLink` nor `href` is set the item stays a `<button>`.
256
+ */
257
+ routerLink?: string | unknown[];
258
+ /** Render as a plain `<a href>` (external or non-router destinations). */
259
+ href?: string;
260
+ /** Small trailing status dot with no text (e.g. "unsaved changes"). */
261
+ dot?: boolean;
262
+ /** Dot tone; defaults to `accent`. */
263
+ dotStatus?: StrctRailStatus;
264
+ /** Muted trailing icon (e.g. "restart required"), before any badge / dot. */
265
+ trailingIcon?: string;
250
266
  }
251
267
  /**
252
268
  * Collapsible, data-driven primary navigation rail for an application shell.
@@ -269,7 +285,16 @@ declare class StrctRail {
269
285
  readonly ariaLabel: _angular_core.InputSignal<string>;
270
286
  /** Emitted when an item is chosen. */
271
287
  readonly select: _angular_core.OutputEmitterRef<StrctRailItem>;
272
- protected pick(item: StrctRailItem): void;
288
+ protected readonly topItems: _angular_core.Signal<StrctRailItem[]>;
289
+ protected readonly bottomItems: _angular_core.Signal<StrctRailItem[]>;
290
+ /** Enabled item with a router destination → renders as `<a routerLink>`. */
291
+ protected isRouted(item: StrctRailItem): boolean;
292
+ /**
293
+ * Active state of a router-link item: an explicit `activeId` is authoritative;
294
+ * without one, the router's own active state drives it.
295
+ */
296
+ protected isActive(item: StrctRailItem, routerActive: boolean): boolean;
297
+ protected pick(item: StrctRailItem, event?: MouseEvent): void;
273
298
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<StrctRail, never>;
274
299
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<StrctRail, "strct-rail", never, { "items": { "alias": "items"; "required": true; "isSignal": true; }; "activeId": { "alias": "activeId"; "required": false; "isSignal": true; }; "collapsed": { "alias": "collapsed"; "required": false; "isSignal": true; }; "collapsible": { "alias": "collapsible"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "activeId": "activeIdChange"; "collapsed": "collapsedChange"; "select": "select"; }, never, never, true, never>;
275
300
  }
@@ -1111,6 +1136,16 @@ interface StrctMenuLink {
1111
1136
  /** Optional leading icon name. */
1112
1137
  icon?: string;
1113
1138
  disabled?: boolean;
1139
+ /** Trailing count/label chip (e.g. a deviation count). */
1140
+ badge?: string | number;
1141
+ /** Badge tone; defaults to `accent` (shared vocabulary with {@link StrctRailItem}). */
1142
+ badgeStatus?: StrctRailStatus;
1143
+ /** Small trailing status dot with no text (e.g. "unsaved changes"). */
1144
+ dot?: boolean;
1145
+ /** Dot tone; defaults to `accent`. */
1146
+ dotStatus?: StrctRailStatus;
1147
+ /** Muted trailing icon (e.g. "restart required"), before any badge / dot. */
1148
+ trailingIcon?: string;
1114
1149
  }
1115
1150
  /** A category (level 1) that groups {@link StrctMenuLink} items (level 2). */
1116
1151
  interface StrctMenuSection {
@@ -2014,6 +2049,26 @@ interface StrctDatagridColumn {
2014
2049
  /** Allow the user to resize this column by dragging its right edge.
2015
2050
  * Defaults to the global {@link StrctDatagrid#resizable} setting. */
2016
2051
  resizable?: boolean;
2052
+ /**
2053
+ * Freeze this column against horizontal scroll. Mark **leading** columns
2054
+ * (utility columns freeze automatically alongside). Give every sticky column
2055
+ * except the last an explicit px `width` so offsets stay exact.
2056
+ */
2057
+ sticky?: boolean;
2058
+ }
2059
+ type SortDir = 'asc' | 'desc';
2060
+ /** What the grid wants loaded in server-side (`lazy`) mode. */
2061
+ interface StrctDatagridLazyState {
2062
+ /** 1-based page. */
2063
+ page: number;
2064
+ pageSize: number;
2065
+ sortKey: string | null;
2066
+ sortDir: SortDir;
2067
+ }
2068
+ /** Persistable user column preferences (widths from resize, hidden from the chooser). */
2069
+ interface StrctDatagridColumnState {
2070
+ widths?: Record<string, number>;
2071
+ hidden?: string[];
2017
2072
  }
2018
2073
  /**
2019
2074
  * Marks the expandable-row detail template. The row is the template's implicit
@@ -2106,6 +2161,34 @@ declare class StrctDatagrid {
2106
2161
  refresh: string;
2107
2162
  actions: string;
2108
2163
  }>;
2164
+ /**
2165
+ * Virtual scrolling for large data sets: only the rows inside the viewport
2166
+ * (plus a small overscan) are in the DOM — 20k+ rows stay smooth. The scroll
2167
+ * area gets `viewportHeight` and a sticky header. Assumes uniform
2168
+ * `rowHeight`; combine with `expandable` is unsupported.
2169
+ */
2170
+ readonly virtual: _angular_core.InputSignalWithTransform<boolean, unknown>;
2171
+ /** Scroll viewport height in px (virtual mode). */
2172
+ readonly viewportHeight: _angular_core.InputSignal<number>;
2173
+ /** Uniform row height in px (virtual mode; tune when `compact`). */
2174
+ readonly rowHeight: _angular_core.InputSignal<number>;
2175
+ /**
2176
+ * Server-side mode: the grid never sorts or slices `rows` itself — it shows
2177
+ * them as given and emits `(lazyLoad)` with `{ page, pageSize, sortKey,
2178
+ * sortDir }` whenever the user pages or sorts (and once on init). Provide
2179
+ * `total` so the pager and count reflect the full server-side set.
2180
+ */
2181
+ readonly lazy: _angular_core.InputSignalWithTransform<boolean, unknown>;
2182
+ /** Total row count on the server (lazy mode). */
2183
+ readonly total: _angular_core.InputSignal<number | null>;
2184
+ /**
2185
+ * Persist the user's column widths + hidden columns under this key in
2186
+ * localStorage (`strct-dg:<key>`), restoring them on init. For full control
2187
+ * use the two-way `columnState` instead (both may be combined).
2188
+ */
2189
+ readonly stateKey: _angular_core.InputSignal<string | null>;
2190
+ /** User column preferences (two-way): widths from resize, hidden from the chooser. */
2191
+ readonly columnState: _angular_core.ModelSignal<StrctDatagridColumnState | null>;
2109
2192
  /** Emitted when the selection changes. */
2110
2193
  readonly selectionChange: _angular_core.OutputEmitterRef<StrctRow[]>;
2111
2194
  /** Emitted when the refresh button is clicked. */
@@ -2115,6 +2198,8 @@ declare class StrctDatagrid {
2115
2198
  row: StrctRow;
2116
2199
  item: StrctMenuItem;
2117
2200
  }>;
2201
+ /** Server-side data request (lazy mode): load this page / sort and set `rows`. */
2202
+ readonly lazyLoad: _angular_core.OutputEmitterRef<StrctDatagridLazyState>;
2118
2203
  private readonly menu;
2119
2204
  protected readonly detailDef: _angular_core.Signal<StrctRowDetailDef | undefined>;
2120
2205
  protected readonly actionBarDef: _angular_core.Signal<StrctDatagridActionBar | undefined>;
@@ -2147,13 +2232,49 @@ declare class StrctDatagrid {
2147
2232
  protected readonly visibleColumns: _angular_core.Signal<StrctDatagridColumn[]>;
2148
2233
  protected readonly sorted: _angular_core.Signal<StrctRow[]>;
2149
2234
  protected readonly paged: _angular_core.Signal<StrctRow[]>;
2235
+ /** Full count for the pager / footer (server total in lazy mode). */
2236
+ protected readonly totalCount: _angular_core.Signal<number>;
2237
+ private readonly scrollTop;
2238
+ protected onScroll(event: Event): void;
2239
+ /** Visible index window incl. overscan (virtual mode). */
2240
+ private readonly vRange;
2241
+ /** The rows actually rendered: the virtual window, or the current page. */
2242
+ protected readonly renderRows: _angular_core.Signal<StrctRow[]>;
2243
+ protected readonly topPad: _angular_core.Signal<number>;
2244
+ protected readonly bottomPad: _angular_core.Signal<number>;
2245
+ protected readonly stickyActive: _angular_core.Signal<boolean>;
2246
+ /** Total width of the frozen utility columns (detail / expand / select). */
2247
+ private readonly utilityWidth;
2248
+ /** Left offset of a frozen utility column, or null when sticky is off. */
2249
+ protected utilLeft(which: 'detail' | 'expand' | 'sel'): number | null;
2250
+ /** Effective px width of a column (resize override → declared px → fallback). */
2251
+ private colPx;
2252
+ /** key → left px for sticky data columns. */
2253
+ private readonly stickyOffsets;
2254
+ protected stickyLeft(key: string): number | null;
2255
+ protected isSticky(col: StrctDatagridColumn): boolean;
2256
+ /** The last frozen column carries the edge shadow. */
2257
+ protected readonly lastStickyKey: _angular_core.Signal<string | null>;
2150
2258
  protected readonly allPageSelected: _angular_core.Signal<boolean>;
2151
2259
  protected readonly somePageSelected: _angular_core.Signal<boolean>;
2152
2260
  /** Resolve a row's stable identity (defaults to the row object itself). */
2153
2261
  private idOf;
2154
2262
  protected rowKey(row: StrctRow): unknown;
2155
2263
  protected cellTemplate(key: string): TemplateRef<StrctCellContext> | null;
2264
+ /** Last emitted lazy request (dedupe key). */
2265
+ private lastLazyKey;
2266
+ /** Last serialized column state pushed outward (loop guard). */
2267
+ private lastStateKey;
2156
2268
  constructor();
2269
+ private readPersistedState;
2270
+ private applyColumnState;
2271
+ /**
2272
+ * The grid as CSV: header labels + every non-hidden column, all rows in the
2273
+ * current order (client mode: the full sorted set, not just the page).
2274
+ */
2275
+ toCSV(): string;
2276
+ /** Download the grid as a CSV file. */
2277
+ downloadCSV(filename?: string): void;
2157
2278
  protected colspan(): number;
2158
2279
  /** Toggle the detail pane for a row (triggered by its » button, not the row,
2159
2280
  * so row cells remain selectable for copy). */
@@ -2177,7 +2298,7 @@ declare class StrctDatagrid {
2177
2298
  private commitSelection;
2178
2299
  private compare;
2179
2300
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<StrctDatagrid, never>;
2180
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<StrctDatagrid, "strct-datagrid", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "rows": { "alias": "rows"; "required": true; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "expandable": { "alias": "expandable"; "required": false; "isSignal": true; }; "detailPane": { "alias": "detailPane"; "required": false; "isSignal": true; }; "compact": { "alias": "compact"; "required": false; "isSignal": true; }; "singleLine": { "alias": "singleLine"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "resizable": { "alias": "resizable"; "required": false; "isSignal": true; }; "columnChooser": { "alias": "columnChooser"; "required": false; "isSignal": true; }; "sync": { "alias": "sync"; "required": false; "isSignal": true; }; "footerActionsDisabled": { "alias": "footerActionsDisabled"; "required": false; "isSignal": true; }; "rowId": { "alias": "rowId"; "required": false; "isSignal": true; }; "rowActions": { "alias": "rowActions"; "required": false; "isSignal": true; }; "initialSelection": { "alias": "initialSelection"; "required": false; "isSignal": true; }; "labels": { "alias": "labels"; "required": false; "isSignal": true; }; }, { "selectionChange": "selectionChange"; "syncChange": "syncChange"; "rowAction": "rowAction"; }, ["detailDef", "actionBarDef", "cellDefs"], ["[strctDatagridActionBar]"], true, never>;
2301
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StrctDatagrid, "strct-datagrid", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "rows": { "alias": "rows"; "required": true; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "expandable": { "alias": "expandable"; "required": false; "isSignal": true; }; "detailPane": { "alias": "detailPane"; "required": false; "isSignal": true; }; "compact": { "alias": "compact"; "required": false; "isSignal": true; }; "singleLine": { "alias": "singleLine"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "resizable": { "alias": "resizable"; "required": false; "isSignal": true; }; "columnChooser": { "alias": "columnChooser"; "required": false; "isSignal": true; }; "sync": { "alias": "sync"; "required": false; "isSignal": true; }; "footerActionsDisabled": { "alias": "footerActionsDisabled"; "required": false; "isSignal": true; }; "rowId": { "alias": "rowId"; "required": false; "isSignal": true; }; "rowActions": { "alias": "rowActions"; "required": false; "isSignal": true; }; "initialSelection": { "alias": "initialSelection"; "required": false; "isSignal": true; }; "labels": { "alias": "labels"; "required": false; "isSignal": true; }; "virtual": { "alias": "virtual"; "required": false; "isSignal": true; }; "viewportHeight": { "alias": "viewportHeight"; "required": false; "isSignal": true; }; "rowHeight": { "alias": "rowHeight"; "required": false; "isSignal": true; }; "lazy": { "alias": "lazy"; "required": false; "isSignal": true; }; "total": { "alias": "total"; "required": false; "isSignal": true; }; "stateKey": { "alias": "stateKey"; "required": false; "isSignal": true; }; "columnState": { "alias": "columnState"; "required": false; "isSignal": true; }; }, { "columnState": "columnStateChange"; "selectionChange": "selectionChange"; "syncChange": "syncChange"; "rowAction": "rowAction"; "lazyLoad": "lazyLoad"; }, ["detailDef", "actionBarDef", "cellDefs"], ["[strctDatagridActionBar]"], true, never>;
2181
2302
  }
2182
2303
 
2183
2304
  /** Timeline node state colors. */
@@ -2915,4 +3036,4 @@ declare class StrctEmptyState {
2915
3036
  }
2916
3037
 
2917
3038
  export { STRCT_ICONS, STRCT_ICON_GROUPS, STRCT_MASKS, STRCT_PALETTES, STRCT_RAW_ICONS, StrctAccordion, StrctAccordionPanel, StrctAlert, StrctAvatar, StrctBadge, StrctBreadcrumb, StrctBreadcrumbItem, StrctButton, StrctButtonGroup, StrctCard, StrctCardBlock, StrctCardFooter, StrctCardHeader, StrctCascadeHost, StrctCascadeNode, StrctCascadeSelect, StrctCellDef, StrctCellStatus, StrctChart, StrctCheckbox, StrctChips, StrctColorPicker, StrctCombobox, StrctCommandPalette, StrctContextMenu, StrctContextMenuTrigger, StrctDatagrid, StrctDatagridActionBar, StrctDatepicker, StrctDesc, StrctDescriptionList, StrctDivider, StrctDonut, StrctDrawer, StrctDrawerFooter, StrctDropdown, StrctDropdownDivider, StrctDropdownItem, StrctEmptyState, StrctField, StrctFile, StrctFlow, StrctFooter, StrctGauge, StrctHeader, StrctHero, StrctIcon, StrctInput, StrctInputMask, StrctInputOtp, StrctKbd, StrctKnob, StrctLogin, StrctMenuPanel, StrctMenuService, StrctMetricTile, StrctModal, StrctNav, StrctNavItem, StrctOverlay, StrctPagination, StrctPassword, StrctProgress, StrctRadio, StrctRadioGroup, StrctRail, StrctRange, StrctRating, StrctRowDetailDef, StrctSectionMenu, StrctSegmented, StrctShell, StrctShellService, StrctSignpost, StrctSkeleton, StrctSparkline, StrctSpeedDial, StrctSpinner, StrctStack, StrctStackItem, StrctStep, StrctSubmenu, StrctTab, StrctTable, StrctTabs, StrctTag, StrctThemeService, StrctThemeSwitcher, StrctTimeline, StrctTimelineItem, StrctToastOutlet, StrctToastService, StrctToggle, StrctTooltip, StrctTree, StrctTreeNode, StrctVerticalNav, StrctWizard, registerStrctIcon, strctValidationIcon, strctValidationTone };
2918
- export type { StrctAlertType, StrctAvatarSize, StrctAvatarStatus, StrctBadgeStatus, StrctButtonSize, StrctButtonVariant, StrctCascadeOption, StrctCellContext, StrctChartAnnotation, StrctChartCurve, StrctChartSeries, StrctChartStatus, StrctChartThreshold, StrctChartType, StrctColumn, StrctCommandItem, StrctDatagridColumn, StrctDatagridLabels, StrctDescAlign, StrctDescItem, StrctDonutSegment, StrctDrawerSide, StrctDrawerSize, StrctEmptyVariant, StrctFlowDirection, StrctFlowNode, StrctFlowOrientation, StrctIconBadge, StrctKnobStatus, StrctMenuItem, StrctMenuLink, StrctMenuOpenOptions, StrctMenuSection, StrctMetricStatus, StrctModalSize, StrctMode, StrctOption, StrctOverlayPlacement, StrctPalette, StrctPaletteInfo, StrctProgressStatus, StrctRailItem, StrctRailStatus, StrctRow, StrctRowId, StrctSegmentedOption, StrctSegmentedSize, StrctSignpostPosition, StrctSpeedDialDirection, StrctSpinnerSize, StrctStatus, StrctTagStatus, StrctThresholds, StrctTimelineState, StrctToast, StrctToastOptions, StrctToastType, StrctTooltipPosition, StrctTreeMenuEvent, StrctTreeNodeData, StrctTreeNodeMenuFn, StrctValidationState, StrctValidationStatus };
3039
+ export type { StrctAlertType, StrctAvatarSize, StrctAvatarStatus, StrctBadgeStatus, StrctButtonSize, StrctButtonVariant, StrctCascadeOption, StrctCellContext, StrctChartAnnotation, StrctChartCurve, StrctChartSeries, StrctChartStatus, StrctChartThreshold, StrctChartType, StrctColumn, StrctCommandItem, StrctDatagridColumn, StrctDatagridColumnState, StrctDatagridLabels, StrctDatagridLazyState, StrctDescAlign, StrctDescItem, StrctDonutSegment, StrctDrawerSide, StrctDrawerSize, StrctEmptyVariant, StrctFlowDirection, StrctFlowNode, StrctFlowOrientation, StrctIconBadge, StrctKnobStatus, StrctMenuItem, StrctMenuLink, StrctMenuOpenOptions, StrctMenuSection, StrctMetricStatus, StrctModalSize, StrctMode, StrctOption, StrctOverlayPlacement, StrctPalette, StrctPaletteInfo, StrctProgressStatus, StrctRailItem, StrctRailStatus, StrctRow, StrctRowId, StrctSegmentedOption, StrctSegmentedSize, StrctSignpostPosition, StrctSpeedDialDirection, StrctSpinnerSize, StrctStatus, StrctTagStatus, StrctThresholds, StrctTimelineState, StrctToast, StrctToastOptions, StrctToastType, StrctTooltipPosition, StrctTreeMenuEvent, StrctTreeNodeData, StrctTreeNodeMenuFn, StrctValidationState, StrctValidationStatus };