@frame-kit/ui-ng-patterns 0.0.2 → 0.0.3

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.
@@ -148,6 +148,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
148
148
  * <fk-field-group>…</fk-field-group>
149
149
  * <fk-field-group>…</fk-field-group>
150
150
  * </fk-columns>
151
+ *
152
+ * By default columns grow to fill the row (`1fr`). Set `maxColumnWidth` to cap
153
+ * how wide a column may get — past that, columns stay that width and the extra
154
+ * space is left empty (columns aligned to the start) rather than stretching.
151
155
  */
152
156
  class ColumnsComponent {
153
157
  // ===== INPUTS =====
@@ -156,6 +160,13 @@ class ColumnsComponent {
156
160
  * columns. This is the single knob that controls when columns wrap/stack.
157
161
  */
158
162
  minColumnWidth = input('16rem', ...(ngDevMode ? [{ debugName: "minColumnWidth" }] : /* istanbul ignore next */ []));
163
+ /**
164
+ * Optional cap on how wide a column may grow. Unset (default), columns fill
165
+ * the row (`1fr`); when set (e.g. `'22rem'`), columns size between
166
+ * `minColumnWidth` and this value and don't stretch past it — leftover space
167
+ * stays empty, columns aligned to the start.
168
+ */
169
+ maxColumnWidth = input(null, ...(ngDevMode ? [{ debugName: "maxColumnWidth" }] : /* istanbul ignore next */ []));
159
170
  /** Gap between side-by-side columns and between wrapped rows. */
160
171
  gutter = input('var(--fk-rhythm-4, 1rem)', ...(ngDevMode ? [{ debugName: "gutter" }] : /* istanbul ignore next */ []));
161
172
  // ===== BASE PROPS =====
@@ -176,16 +187,20 @@ class ColumnsComponent {
176
187
  get hostMin() {
177
188
  return this.minColumnWidth();
178
189
  }
190
+ // Null leaves the property unset, so the SCSS falls back to `1fr` (fill).
191
+ get hostMax() {
192
+ return this.maxColumnWidth();
193
+ }
179
194
  get hostGutter() {
180
195
  return this.gutter();
181
196
  }
182
197
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ColumnsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
183
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: ColumnsComponent, isStandalone: true, selector: "fk-columns", inputs: { minColumnWidth: { classPropertyName: "minColumnWidth", publicName: "minColumnWidth", isSignal: true, isRequired: false, transformFunction: null }, gutter: { classPropertyName: "gutter", publicName: "gutter", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass", "attr.id": "this.hostId", "attr.aria-label": "this.hostAriaLabel", "style.--fk-columns-min": "this.hostMin", "style.--fk-columns-gutter": "this.hostGutter" } }, ngImport: i0, template: "<ng-content />\n", styles: [":host{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(var(--fk-columns-min, 16rem),100%),1fr));gap:var(--fk-columns-gutter, var(--fk-rhythm-4, 1rem));align-items:start}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
198
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: ColumnsComponent, isStandalone: true, selector: "fk-columns", inputs: { minColumnWidth: { classPropertyName: "minColumnWidth", publicName: "minColumnWidth", isSignal: true, isRequired: false, transformFunction: null }, maxColumnWidth: { classPropertyName: "maxColumnWidth", publicName: "maxColumnWidth", isSignal: true, isRequired: false, transformFunction: null }, gutter: { classPropertyName: "gutter", publicName: "gutter", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass", "attr.id": "this.hostId", "attr.aria-label": "this.hostAriaLabel", "style.--fk-columns-min": "this.hostMin", "style.--fk-columns-max": "this.hostMax", "style.--fk-columns-gutter": "this.hostGutter" } }, ngImport: i0, template: "<ng-content />\n", styles: [":host{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(var(--fk-columns-min, 16rem),100%),var(--fk-columns-max, 1fr)));gap:var(--fk-columns-gutter, var(--fk-rhythm-4, 1rem));align-items:start;justify-content:start}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
184
199
  }
185
200
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ColumnsComponent, decorators: [{
186
201
  type: Component,
187
- args: [{ selector: 'fk-columns', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content />\n", styles: [":host{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(var(--fk-columns-min, 16rem),100%),1fr));gap:var(--fk-columns-gutter, var(--fk-rhythm-4, 1rem));align-items:start}\n"] }]
188
- }], propDecorators: { minColumnWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minColumnWidth", required: false }] }], gutter: [{ type: i0.Input, args: [{ isSignal: true, alias: "gutter", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hostClass: [{
202
+ args: [{ selector: 'fk-columns', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content />\n", styles: [":host{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(var(--fk-columns-min, 16rem),100%),var(--fk-columns-max, 1fr)));gap:var(--fk-columns-gutter, var(--fk-rhythm-4, 1rem));align-items:start;justify-content:start}\n"] }]
203
+ }], propDecorators: { minColumnWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minColumnWidth", required: false }] }], maxColumnWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxColumnWidth", required: false }] }], gutter: [{ type: i0.Input, args: [{ isSignal: true, alias: "gutter", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hostClass: [{
189
204
  type: HostBinding,
190
205
  args: ['class']
191
206
  }], hostId: [{
@@ -197,6 +212,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
197
212
  }], hostMin: [{
198
213
  type: HostBinding,
199
214
  args: ['style.--fk-columns-min']
215
+ }], hostMax: [{
216
+ type: HostBinding,
217
+ args: ['style.--fk-columns-max']
200
218
  }], hostGutter: [{
201
219
  type: HostBinding,
202
220
  args: ['style.--fk-columns-gutter']
@@ -1 +1 @@
1
- {"version":3,"file":"frame-kit-ui-ng-patterns-dashboard.mjs","sources":["../../../../packages/ui-ng-patterns/dashboard/page-header/page-header.component.ts","../../../../packages/ui-ng-patterns/dashboard/page-header/page-header.component.html","../../../../packages/ui-ng-patterns/dashboard/table-empty-state/table-empty-state.component.ts","../../../../packages/ui-ng-patterns/dashboard/table-empty-state/table-empty-state.component.html","../../../../packages/ui-ng-patterns/dashboard/content-split-layout/content-split-layout.component.ts","../../../../packages/ui-ng-patterns/dashboard/content-split-layout/content-split-layout.component.html","../../../../packages/ui-ng-patterns/dashboard/columns/columns.component.ts","../../../../packages/ui-ng-patterns/dashboard/columns/columns.component.html","../../../../packages/ui-ng-patterns/dashboard/detail-panel/detail-panel.component.ts","../../../../packages/ui-ng-patterns/dashboard/detail-panel/detail-panel.component.html","../../../../packages/ui-ng-patterns/dashboard/frame-kit-ui-ng-patterns-dashboard.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n input,\n ViewEncapsulation,\n} from '@angular/core';\n\nimport type { HeadlineLevel } from '@frame-kit/ui-ng/core/headline';\nimport { HeadlineComponent } from '@frame-kit/ui-ng/core/headline';\nimport { TextComponent } from '@frame-kit/ui-ng/core/text';\n\n/**\n * Page-level dashboard header: title + optional description on the left, up to\n * ~3 actions on the right.\n *\n * When the header's own width gets tight, the actions drop below the text and\n * go full-width (mobile-style). The break is driven by a CSS container query on\n * the host, so it responds to the content region's width — not the viewport,\n * which means it behaves correctly inside a narrow panel.\n *\n * Project actions by tagging each button with `pageHeaderActions`:\n *\n * <fk-page-header title=\"Users\" description=\"...\">\n * <fk-button pageHeaderActions variant=\"outline\" size=\"sm\">Import</fk-button>\n * <fk-button pageHeaderActions variant=\"primary\" size=\"sm\">Create user</fk-button>\n * </fk-page-header>\n *\n * Tagging each button (rather than wrapping them in a div) makes every button a\n * direct flex child, so full-width stacking falls out of `align-items: stretch`\n * with no `::ng-deep` reach-in.\n *\n * The title row has two projected slots — `[pageHeaderLeading]` before the\n * title and `[pageHeaderTrailing]` after it. Project a plain `fk-icon` for a\n * decorative mark, or a `button` for a clickable one (the consumer owns the\n * interaction, focus ring, and aria-label):\n *\n * <fk-page-header title=\"Permissions\">\n * <fk-icon pageHeaderLeading name=\"key-outline\" />\n * <button pageHeaderTrailing type=\"button\" aria-label=\"Docs\" (click)=\"openDocs()\">\n * <fk-icon name=\"view-api\" />\n * </button>\n * </fk-page-header>\n */\n@Component({\n selector: 'fk-page-header',\n standalone: true,\n imports: [HeadlineComponent, TextComponent],\n // Emulated (not None) so `:host` works — `:host { display: block }` is what\n // keeps the custom element from defaulting to `display: inline` and\n // collapsing to min-content under the container query below.\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './page-header.component.html',\n styleUrl: './page-header.component.scss',\n})\nexport class PageHeaderComponent {\n readonly title = input.required<string>();\n readonly description = input<string | null>(null);\n readonly headingLevel = input<HeadlineLevel>(1);\n}\n","<header class=\"fk-page-header\">\n <div class=\"fk-page-header__text\">\n <div class=\"fk-page-header__title-row\">\n <ng-content select=\"[pageHeaderLeading]\" />\n\n <fk-headline [level]=\"headingLevel()\">{{ title() }}</fk-headline>\n\n <ng-content select=\"[pageHeaderTrailing]\" />\n </div>\n\n @if (description()) {\n <fk-text class=\"fk-page-header__description\" tone=\"muted\">{{\n description()\n }}</fk-text>\n }\n </div>\n\n <div class=\"fk-page-header__actions\">\n <ng-content select=\"[pageHeaderActions]\" />\n </div>\n</header>\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n ViewEncapsulation,\n} from '@angular/core';\n\nimport { IconComponent } from '@frame-kit/ui-ng/core/icon';\n\n/**\n * Empty-state panel for dashboard tables and lists: a centered icon, a title,\n * an optional description, and a projected actions slot (typically one primary\n * fk-button). Bordered-card styling, meant to stand in for a table body when\n * there are no rows.\n *\n * The action row flips from a horizontal row to a centered vertical stack on\n * narrow widths, driven by a container query on the host — so it reacts to the\n * empty-state's own width (e.g. inside a split column) rather than the viewport.\n *\n * <fk-table-empty-state\n * icon=\"globe\"\n * title=\"No webhooks configured\"\n * description=\"Add a webhook to receive events.\"\n * >\n * <fk-button variant=\"primary\" size=\"sm\">Add webhook</fk-button>\n * </fk-table-empty-state>\n *\n * The actions slot is an open `ng-content`, so project as many actions as the\n * design needs (one primary is the norm; two reads cleanly).\n */\n@Component({\n selector: 'fk-table-empty-state',\n standalone: true,\n imports: [IconComponent],\n // Emulated (default) so `:host` works — the host is the bordered flex card\n // and establishes the container-query context the actions break against.\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './table-empty-state.component.html',\n styleUrl: './table-empty-state.component.scss',\n})\nexport class TableEmptyStateComponent {\n // ===== INPUTS =====\n readonly icon = input<string | null>(null);\n readonly title = input.required<string>();\n readonly description = input<string | null>(null);\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== COMPUTED =====\n readonly classes = computed(() =>\n ['fk-table-empty-state', this.className()].filter(Boolean).join(' '),\n );\n\n @HostBinding('class')\n get hostClass(): string {\n return this.classes();\n }\n\n @HostBinding('attr.id')\n get hostId(): string | null {\n return this.id();\n }\n\n @HostBinding('attr.aria-label')\n get hostAriaLabel(): string | null {\n return this.ariaLabel();\n }\n}\n","@if (icon()) {\n <div class=\"fk-table-empty-state__icon\">\n <fk-icon [name]=\"icon()!\" size=\"lg\" />\n </div>\n}\n\n<h3 class=\"fk-table-empty-state__title\">{{ title() }}</h3>\n\n@if (description()) {\n <p class=\"fk-table-empty-state__description\">{{ description() }}</p>\n}\n\n<div class=\"fk-table-empty-state__actions\">\n <ng-content />\n</div>\n","import {\n ChangeDetectionStrategy,\n Component,\n HostBinding,\n input,\n} from '@angular/core';\n\n/**\n * Two-column split layout with container-query responsive stacking.\n *\n * Projects content into `[start]` (grows to fill) and `[end]` (content-sized or\n * fixed width). Below 700px container width, columns stack vertically.\n *\n * A standalone layout primitive for custom dashboard rows.\n */\n@Component({\n selector: 'fk-content-split-layout',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './content-split-layout.component.html',\n styleUrl: './content-split-layout.component.scss',\n})\nexport class ContentSplitLayoutComponent {\n readonly endWidth = input<string | null>(null);\n readonly gap = input<string>('var(--fk-rhythm-4, 1rem)');\n\n @HostBinding('class')\n readonly hostClass = 'fk-content-split-layout';\n}\n","<div\n class=\"fk-content-split-layout__row\"\n [style.--fk-content-split-gap]=\"gap()\"\n>\n <div class=\"fk-content-split-layout__start\">\n <ng-content select=\"[start]\" />\n </div>\n\n <div\n class=\"fk-content-split-layout__end\"\n [class.fk-content-split-layout__end--fixed]=\"endWidth()\"\n [style.--fk-content-split-end-width]=\"endWidth()\"\n >\n <ng-content select=\"[end]\" />\n </div>\n</div>\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n} from '@angular/core';\n\n/**\n * Responsive column layout for dashboard content. Lays projected children out\n * in equal-width columns that wrap — and ultimately collapse to a single\n * stacked column — based on the layout's *own* available width, never the\n * viewport. So it reacts correctly when the dashboard content region is\n * squeezed (sidenav open, a drawer pushed in, a split pane) while the viewport\n * still reports \"desktop\".\n *\n * Implemented with an intrinsic CSS grid — `repeat(auto-fit, minmax(min, 1fr))`\n * — so there is no container query, no JS, and no viewport breakpoint to keep\n * in sync. `minColumnWidth` is the smallest a column may shrink to before the\n * grid drops a column; empty tracks collapse, so N children never produce more\n * than N columns. Spacing on both axes is a single `gutter` gap, so wrapped\n * rows and side-by-side columns separate consistently with no edge artifacts.\n *\n * <fk-columns minColumnWidth=\"18rem\">\n * <fk-field-group>…</fk-field-group>\n * <fk-field-group>…</fk-field-group>\n * </fk-columns>\n */\n@Component({\n selector: 'fk-columns',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './columns.component.html',\n styleUrl: './columns.component.scss',\n})\nexport class ColumnsComponent {\n // ===== INPUTS =====\n /**\n * The smallest width a column may shrink to before the grid drops to fewer\n * columns. This is the single knob that controls when columns wrap/stack.\n */\n readonly minColumnWidth = input<string>('16rem');\n /** Gap between side-by-side columns and between wrapped rows. */\n readonly gutter = input<string>('var(--fk-rhythm-4, 1rem)');\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== COMPUTED =====\n readonly classes = computed(() =>\n ['fk-columns', this.className()].filter(Boolean).join(' '),\n );\n\n @HostBinding('class')\n get hostClass(): string {\n return this.classes();\n }\n\n @HostBinding('attr.id')\n get hostId(): string | null {\n return this.id();\n }\n\n @HostBinding('attr.aria-label')\n get hostAriaLabel(): string | null {\n return this.ariaLabel();\n }\n\n @HostBinding('style.--fk-columns-min')\n get hostMin(): string {\n return this.minColumnWidth();\n }\n\n @HostBinding('style.--fk-columns-gutter')\n get hostGutter(): string {\n return this.gutter();\n }\n}\n","<ng-content />\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n} from '@angular/core';\n\n/**\n * Padded container for an expanded dashboard detail region — typically the body\n * of a data-table row expansion, holding an `fk-columns` of form controls.\n *\n * The `disabled` input greys the panel and makes its entire subtree `inert`\n * (non-interactive, unfocusable, hidden from assistive technology) — for\n * controls gated behind a feature toggle that must not be editable until the\n * feature is enabled.\n *\n * <fk-detail-panel [disabled]=\"!feature.enabled\">\n * <fk-columns>…</fk-columns>\n * </fk-detail-panel>\n */\n@Component({\n selector: 'fk-detail-panel',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './detail-panel.component.html',\n styleUrl: './detail-panel.component.scss',\n})\nexport class DetailPanelComponent {\n // ===== INPUTS =====\n /**\n * Greys the panel and makes its content inert (locked) — for feature-gated\n * controls that should not be editable until the feature is enabled.\n */\n readonly disabled = input<boolean>(false);\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== COMPUTED =====\n readonly classes = computed(() =>\n [\n 'fk-detail-panel',\n this.disabled() ? 'fk-detail-panel--disabled' : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' '),\n );\n\n @HostBinding('class')\n get hostClass(): string {\n return this.classes();\n }\n\n @HostBinding('attr.id')\n get hostId(): string | null {\n return this.id();\n }\n\n @HostBinding('attr.aria-label')\n get hostAriaLabel(): string | null {\n return this.ariaLabel();\n }\n\n /**\n * Lock the whole subtree when disabled. `inert` blocks pointer interaction,\n * focus, and assistive-tech access in one attribute — stronger and more\n * correct than `pointer-events: none`, which only blocks the mouse.\n */\n @HostBinding('attr.inert')\n get hostInert(): '' | null {\n return this.disabled() ? '' : null;\n }\n}\n","<ng-content />\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"frame-kit-ui-ng-patterns-dashboard.mjs","sources":["../../../../packages/ui-ng-patterns/dashboard/page-header/page-header.component.ts","../../../../packages/ui-ng-patterns/dashboard/page-header/page-header.component.html","../../../../packages/ui-ng-patterns/dashboard/table-empty-state/table-empty-state.component.ts","../../../../packages/ui-ng-patterns/dashboard/table-empty-state/table-empty-state.component.html","../../../../packages/ui-ng-patterns/dashboard/content-split-layout/content-split-layout.component.ts","../../../../packages/ui-ng-patterns/dashboard/content-split-layout/content-split-layout.component.html","../../../../packages/ui-ng-patterns/dashboard/columns/columns.component.ts","../../../../packages/ui-ng-patterns/dashboard/columns/columns.component.html","../../../../packages/ui-ng-patterns/dashboard/detail-panel/detail-panel.component.ts","../../../../packages/ui-ng-patterns/dashboard/detail-panel/detail-panel.component.html","../../../../packages/ui-ng-patterns/dashboard/frame-kit-ui-ng-patterns-dashboard.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n input,\n ViewEncapsulation,\n} from '@angular/core';\n\nimport type { HeadlineLevel } from '@frame-kit/ui-ng/core/headline';\nimport { HeadlineComponent } from '@frame-kit/ui-ng/core/headline';\nimport { TextComponent } from '@frame-kit/ui-ng/core/text';\n\n/**\n * Page-level dashboard header: title + optional description on the left, up to\n * ~3 actions on the right.\n *\n * When the header's own width gets tight, the actions drop below the text and\n * go full-width (mobile-style). The break is driven by a CSS container query on\n * the host, so it responds to the content region's width — not the viewport,\n * which means it behaves correctly inside a narrow panel.\n *\n * Project actions by tagging each button with `pageHeaderActions`:\n *\n * <fk-page-header title=\"Users\" description=\"...\">\n * <fk-button pageHeaderActions variant=\"outline\" size=\"sm\">Import</fk-button>\n * <fk-button pageHeaderActions variant=\"primary\" size=\"sm\">Create user</fk-button>\n * </fk-page-header>\n *\n * Tagging each button (rather than wrapping them in a div) makes every button a\n * direct flex child, so full-width stacking falls out of `align-items: stretch`\n * with no `::ng-deep` reach-in.\n *\n * The title row has two projected slots — `[pageHeaderLeading]` before the\n * title and `[pageHeaderTrailing]` after it. Project a plain `fk-icon` for a\n * decorative mark, or a `button` for a clickable one (the consumer owns the\n * interaction, focus ring, and aria-label):\n *\n * <fk-page-header title=\"Permissions\">\n * <fk-icon pageHeaderLeading name=\"key-outline\" />\n * <button pageHeaderTrailing type=\"button\" aria-label=\"Docs\" (click)=\"openDocs()\">\n * <fk-icon name=\"view-api\" />\n * </button>\n * </fk-page-header>\n */\n@Component({\n selector: 'fk-page-header',\n standalone: true,\n imports: [HeadlineComponent, TextComponent],\n // Emulated (not None) so `:host` works — `:host { display: block }` is what\n // keeps the custom element from defaulting to `display: inline` and\n // collapsing to min-content under the container query below.\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './page-header.component.html',\n styleUrl: './page-header.component.scss',\n})\nexport class PageHeaderComponent {\n readonly title = input.required<string>();\n readonly description = input<string | null>(null);\n readonly headingLevel = input<HeadlineLevel>(1);\n}\n","<header class=\"fk-page-header\">\n <div class=\"fk-page-header__text\">\n <div class=\"fk-page-header__title-row\">\n <ng-content select=\"[pageHeaderLeading]\" />\n\n <fk-headline [level]=\"headingLevel()\">{{ title() }}</fk-headline>\n\n <ng-content select=\"[pageHeaderTrailing]\" />\n </div>\n\n @if (description()) {\n <fk-text class=\"fk-page-header__description\" tone=\"muted\">{{\n description()\n }}</fk-text>\n }\n </div>\n\n <div class=\"fk-page-header__actions\">\n <ng-content select=\"[pageHeaderActions]\" />\n </div>\n</header>\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n ViewEncapsulation,\n} from '@angular/core';\n\nimport { IconComponent } from '@frame-kit/ui-ng/core/icon';\n\n/**\n * Empty-state panel for dashboard tables and lists: a centered icon, a title,\n * an optional description, and a projected actions slot (typically one primary\n * fk-button). Bordered-card styling, meant to stand in for a table body when\n * there are no rows.\n *\n * The action row flips from a horizontal row to a centered vertical stack on\n * narrow widths, driven by a container query on the host — so it reacts to the\n * empty-state's own width (e.g. inside a split column) rather than the viewport.\n *\n * <fk-table-empty-state\n * icon=\"globe\"\n * title=\"No webhooks configured\"\n * description=\"Add a webhook to receive events.\"\n * >\n * <fk-button variant=\"primary\" size=\"sm\">Add webhook</fk-button>\n * </fk-table-empty-state>\n *\n * The actions slot is an open `ng-content`, so project as many actions as the\n * design needs (one primary is the norm; two reads cleanly).\n */\n@Component({\n selector: 'fk-table-empty-state',\n standalone: true,\n imports: [IconComponent],\n // Emulated (default) so `:host` works — the host is the bordered flex card\n // and establishes the container-query context the actions break against.\n encapsulation: ViewEncapsulation.Emulated,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './table-empty-state.component.html',\n styleUrl: './table-empty-state.component.scss',\n})\nexport class TableEmptyStateComponent {\n // ===== INPUTS =====\n readonly icon = input<string | null>(null);\n readonly title = input.required<string>();\n readonly description = input<string | null>(null);\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== COMPUTED =====\n readonly classes = computed(() =>\n ['fk-table-empty-state', this.className()].filter(Boolean).join(' '),\n );\n\n @HostBinding('class')\n get hostClass(): string {\n return this.classes();\n }\n\n @HostBinding('attr.id')\n get hostId(): string | null {\n return this.id();\n }\n\n @HostBinding('attr.aria-label')\n get hostAriaLabel(): string | null {\n return this.ariaLabel();\n }\n}\n","@if (icon()) {\n <div class=\"fk-table-empty-state__icon\">\n <fk-icon [name]=\"icon()!\" size=\"lg\" />\n </div>\n}\n\n<h3 class=\"fk-table-empty-state__title\">{{ title() }}</h3>\n\n@if (description()) {\n <p class=\"fk-table-empty-state__description\">{{ description() }}</p>\n}\n\n<div class=\"fk-table-empty-state__actions\">\n <ng-content />\n</div>\n","import {\n ChangeDetectionStrategy,\n Component,\n HostBinding,\n input,\n} from '@angular/core';\n\n/**\n * Two-column split layout with container-query responsive stacking.\n *\n * Projects content into `[start]` (grows to fill) and `[end]` (content-sized or\n * fixed width). Below 700px container width, columns stack vertically.\n *\n * A standalone layout primitive for custom dashboard rows.\n */\n@Component({\n selector: 'fk-content-split-layout',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './content-split-layout.component.html',\n styleUrl: './content-split-layout.component.scss',\n})\nexport class ContentSplitLayoutComponent {\n readonly endWidth = input<string | null>(null);\n readonly gap = input<string>('var(--fk-rhythm-4, 1rem)');\n\n @HostBinding('class')\n readonly hostClass = 'fk-content-split-layout';\n}\n","<div\n class=\"fk-content-split-layout__row\"\n [style.--fk-content-split-gap]=\"gap()\"\n>\n <div class=\"fk-content-split-layout__start\">\n <ng-content select=\"[start]\" />\n </div>\n\n <div\n class=\"fk-content-split-layout__end\"\n [class.fk-content-split-layout__end--fixed]=\"endWidth()\"\n [style.--fk-content-split-end-width]=\"endWidth()\"\n >\n <ng-content select=\"[end]\" />\n </div>\n</div>\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n} from '@angular/core';\n\n/**\n * Responsive column layout for dashboard content. Lays projected children out\n * in equal-width columns that wrap — and ultimately collapse to a single\n * stacked column — based on the layout's *own* available width, never the\n * viewport. So it reacts correctly when the dashboard content region is\n * squeezed (sidenav open, a drawer pushed in, a split pane) while the viewport\n * still reports \"desktop\".\n *\n * Implemented with an intrinsic CSS grid — `repeat(auto-fit, minmax(min, 1fr))`\n * — so there is no container query, no JS, and no viewport breakpoint to keep\n * in sync. `minColumnWidth` is the smallest a column may shrink to before the\n * grid drops a column; empty tracks collapse, so N children never produce more\n * than N columns. Spacing on both axes is a single `gutter` gap, so wrapped\n * rows and side-by-side columns separate consistently with no edge artifacts.\n *\n * <fk-columns minColumnWidth=\"18rem\">\n * <fk-field-group>…</fk-field-group>\n * <fk-field-group>…</fk-field-group>\n * </fk-columns>\n *\n * By default columns grow to fill the row (`1fr`). Set `maxColumnWidth` to cap\n * how wide a column may get — past that, columns stay that width and the extra\n * space is left empty (columns aligned to the start) rather than stretching.\n */\n@Component({\n selector: 'fk-columns',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './columns.component.html',\n styleUrl: './columns.component.scss',\n})\nexport class ColumnsComponent {\n // ===== INPUTS =====\n /**\n * The smallest width a column may shrink to before the grid drops to fewer\n * columns. This is the single knob that controls when columns wrap/stack.\n */\n readonly minColumnWidth = input<string>('16rem');\n /**\n * Optional cap on how wide a column may grow. Unset (default), columns fill\n * the row (`1fr`); when set (e.g. `'22rem'`), columns size between\n * `minColumnWidth` and this value and don't stretch past it — leftover space\n * stays empty, columns aligned to the start.\n */\n readonly maxColumnWidth = input<string | null>(null);\n /** Gap between side-by-side columns and between wrapped rows. */\n readonly gutter = input<string>('var(--fk-rhythm-4, 1rem)');\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== COMPUTED =====\n readonly classes = computed(() =>\n ['fk-columns', this.className()].filter(Boolean).join(' '),\n );\n\n @HostBinding('class')\n get hostClass(): string {\n return this.classes();\n }\n\n @HostBinding('attr.id')\n get hostId(): string | null {\n return this.id();\n }\n\n @HostBinding('attr.aria-label')\n get hostAriaLabel(): string | null {\n return this.ariaLabel();\n }\n\n @HostBinding('style.--fk-columns-min')\n get hostMin(): string {\n return this.minColumnWidth();\n }\n\n // Null leaves the property unset, so the SCSS falls back to `1fr` (fill).\n @HostBinding('style.--fk-columns-max')\n get hostMax(): string | null {\n return this.maxColumnWidth();\n }\n\n @HostBinding('style.--fk-columns-gutter')\n get hostGutter(): string {\n return this.gutter();\n }\n}\n","<ng-content />\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n} from '@angular/core';\n\n/**\n * Padded container for an expanded dashboard detail region — typically the body\n * of a data-table row expansion, holding an `fk-columns` of form controls.\n *\n * The `disabled` input greys the panel and makes its entire subtree `inert`\n * (non-interactive, unfocusable, hidden from assistive technology) — for\n * controls gated behind a feature toggle that must not be editable until the\n * feature is enabled.\n *\n * <fk-detail-panel [disabled]=\"!feature.enabled\">\n * <fk-columns>…</fk-columns>\n * </fk-detail-panel>\n */\n@Component({\n selector: 'fk-detail-panel',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './detail-panel.component.html',\n styleUrl: './detail-panel.component.scss',\n})\nexport class DetailPanelComponent {\n // ===== INPUTS =====\n /**\n * Greys the panel and makes its content inert (locked) — for feature-gated\n * controls that should not be editable until the feature is enabled.\n */\n readonly disabled = input<boolean>(false);\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== COMPUTED =====\n readonly classes = computed(() =>\n [\n 'fk-detail-panel',\n this.disabled() ? 'fk-detail-panel--disabled' : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' '),\n );\n\n @HostBinding('class')\n get hostClass(): string {\n return this.classes();\n }\n\n @HostBinding('attr.id')\n get hostId(): string | null {\n return this.id();\n }\n\n @HostBinding('attr.aria-label')\n get hostAriaLabel(): string | null {\n return this.ariaLabel();\n }\n\n /**\n * Lock the whole subtree when disabled. `inert` blocks pointer interaction,\n * focus, and assistive-tech access in one attribute — stronger and more\n * correct than `pointer-events: none`, which only blocks the mouse.\n */\n @HostBinding('attr.inert')\n get hostInert(): '' | null {\n return this.disabled() ? '' : null;\n }\n}\n","<ng-content />\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frame-kit/ui-ng-patterns",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Opinionated, dashboard-ready Angular component patterns composed from @frame-kit/ui-ng.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -112,6 +112,10 @@ declare class ContentSplitLayoutComponent {
112
112
  * <fk-field-group>…</fk-field-group>
113
113
  * <fk-field-group>…</fk-field-group>
114
114
  * </fk-columns>
115
+ *
116
+ * By default columns grow to fill the row (`1fr`). Set `maxColumnWidth` to cap
117
+ * how wide a column may get — past that, columns stay that width and the extra
118
+ * space is left empty (columns aligned to the start) rather than stretching.
115
119
  */
116
120
  declare class ColumnsComponent {
117
121
  /**
@@ -119,6 +123,13 @@ declare class ColumnsComponent {
119
123
  * columns. This is the single knob that controls when columns wrap/stack.
120
124
  */
121
125
  readonly minColumnWidth: _angular_core.InputSignal<string>;
126
+ /**
127
+ * Optional cap on how wide a column may grow. Unset (default), columns fill
128
+ * the row (`1fr`); when set (e.g. `'22rem'`), columns size between
129
+ * `minColumnWidth` and this value and don't stretch past it — leftover space
130
+ * stays empty, columns aligned to the start.
131
+ */
132
+ readonly maxColumnWidth: _angular_core.InputSignal<string | null>;
122
133
  /** Gap between side-by-side columns and between wrapped rows. */
123
134
  readonly gutter: _angular_core.InputSignal<string>;
124
135
  readonly className: _angular_core.InputSignal<string>;
@@ -129,9 +140,10 @@ declare class ColumnsComponent {
129
140
  get hostId(): string | null;
130
141
  get hostAriaLabel(): string | null;
131
142
  get hostMin(): string;
143
+ get hostMax(): string | null;
132
144
  get hostGutter(): string;
133
145
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ColumnsComponent, never>;
134
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<ColumnsComponent, "fk-columns", never, { "minColumnWidth": { "alias": "minColumnWidth"; "required": false; "isSignal": true; }; "gutter": { "alias": "gutter"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
146
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ColumnsComponent, "fk-columns", never, { "minColumnWidth": { "alias": "minColumnWidth"; "required": false; "isSignal": true; }; "maxColumnWidth": { "alias": "maxColumnWidth"; "required": false; "isSignal": true; }; "gutter": { "alias": "gutter"; "required": false; "isSignal": true; }; "className": { "alias": "className"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
135
147
  }
136
148
 
137
149
  /**