fold-ng 0.12.0 → 0.12.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/CHANGELOG.md CHANGED
@@ -8,6 +8,25 @@ All notable changes to **fold-ng** are documented here. The format follows
8
8
 
9
9
  _Nothing yet._
10
10
 
11
+ ## [0.12.1] - 2026-08-22
12
+
13
+ ### Fixed
14
+
15
+ - **A panel body no longer crushes a child that clips its own overflow.**
16
+ `fold-panel-body` laid its children out as a flex column, where every child
17
+ may shrink and a child whose `overflow` is not `visible` has an automatic
18
+ minimum size of **zero**. `fold-danger-zone` clips its overflow to keep its
19
+ dividers flush with its rounded corners, so in a full panel it was measured
20
+ at **2px** — its two borders — with the destructive action, its heading and
21
+ its explanation all erased. The box reported barely any overflow, so there
22
+ was nothing to scroll to either: the panel looked finished and was not.
23
+
24
+ The body is now a single-column grid with `grid-auto-rows: max-content`:
25
+ rows are sized by their content and the box overflows, which is what a
26
+ scrolling column is for. Every child is protected, not only the ones we
27
+ thought of. `fold-danger-zone` also asks for its content-based minimum back
28
+ explicitly, so it survives a hand-rolled flex column too.
29
+
11
30
  ## [0.12.0] - 2026-08-22
12
31
 
13
32
  ### Added
@@ -1616,7 +1635,8 @@ design-token stylesheet.
1616
1635
  `currentColor`; `prefers-reduced-motion` + `forced-colors` are respected;
1617
1636
  strings localise via inputs / providers (`provideFoldPanelLabels`).
1618
1637
 
1619
- [unreleased]: https://github.com/hugoheynard/fold-ng/compare/v0.12.0...HEAD
1638
+ [unreleased]: https://github.com/hugoheynard/fold-ng/compare/v0.12.1...HEAD
1639
+ [0.12.1]: https://github.com/hugoheynard/fold-ng/releases/tag/v0.12.1
1620
1640
  [0.12.0]: https://github.com/hugoheynard/fold-ng/releases/tag/v0.12.0
1621
1641
  [0.11.1]: https://github.com/hugoheynard/fold-ng/releases/tag/v0.11.1
1622
1642
  [0.11.0]: https://github.com/hugoheynard/fold-ng/releases/tag/v0.11.0
@@ -3296,7 +3296,7 @@ class FoldDangerZoneComponent {
3296
3296
  /** Stable id the host's `aria-labelledby` points at. */
3297
3297
  titleId = this.ids.next("fold-danger-zone");
3298
3298
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldDangerZoneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3299
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldDangerZoneComponent, isStandalone: true, selector: "fold-danger-zone", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null }, confirmPhrase: { classPropertyName: "confirmPhrase", publicName: "confirmPhrase", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, intent: { classPropertyName: "intent", publicName: "intent", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { confirmed: "confirmed" }, host: { attributes: { "role": "group" }, properties: { "attr.data-appearance": "appearance()", "attr.aria-labelledby": "titleId" } }, ngImport: i0, template: "<div class=\"dz-head\">\n <fold-icon name=\"warning\" size=\"sm\" class=\"dz-icon\" aria-hidden=\"true\" />\n <h3 class=\"dz-title\" [id]=\"titleId\">{{ title() }}</h3>\n</div>\n\n<div class=\"dz-body\">\n <ng-content />\n</div>\n\n@if (actionLabel(); as label) {\n <div class=\"dz-actions\">\n <fold-inline-confirm\n [match]=\"confirmPhrase() ?? ''\"\n [message]=\"message() ?? ''\"\n [intent]=\"intent()\"\n (confirmed)=\"confirmed.emit($event)\"\n >\n <button foldButton emphasis=\"solid\" [intent]=\"intent()\">\n {{ label }}\n </button>\n </fold-inline-confirm>\n </div>\n}\n", styles: [":host{display:block;border:1px solid var(--fold-color-alert-border);border-radius:var(--fold-radius-md, 10px);overflow:hidden}:host([data-appearance=filled]){background:var(--fold-color-alert-surface)}:host([data-appearance=section]){background:var(--fold-color-surface-card)}.dz-head{display:flex;align-items:center;gap:.5rem;padding:var(--fold-space-lg) var(--fold-space-lg) var(--fold-space-sm);color:var(--fold-color-alert-text)}.dz-icon{flex:none}.dz-title{margin:0;font-size:var(--fold-text-md, 1rem);font-weight:600}.dz-body{padding:0 var(--fold-space-lg) var(--fold-space-md);color:var(--fold-color-text-secondary);font-size:var(--fold-text-sm, .875rem);line-height:1.5}.dz-body:empty{display:none}.dz-body :first-child{margin-top:0}.dz-body :last-child{margin-bottom:0}.dz-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--fold-space-sm);padding:var(--fold-space-md) var(--fold-space-lg)}:host([data-appearance=section]) .dz-actions{border-top:1px solid var(--fold-color-border-subtle);background:var(--fold-color-surface-sunken)}@media(forced-colors:active){:host{border-color:CanvasText}:host([data-appearance=section]) .dz-actions{border-top-color:CanvasText}}\n"], dependencies: [{ kind: "component", type: FoldIconComponent, selector: "fold-icon", inputs: ["name", "size", "tone", "title"] }, { kind: "component", type: FoldButtonComponent, selector: "button[foldButton], a[foldButton]", inputs: ["emphasis", "intent", "size", "shape", "block", "icon", "iconTrailing", "type", "disabled", "loading"] }, { kind: "component", type: FoldInlineConfirmComponent, selector: "fold-inline-confirm", inputs: ["intent", "message", "match", "password", "placeholder", "loading", "size", "confirmIcon", "cancelIcon", "keepOpenOnConfirm", "labels", "open"], outputs: ["confirmed", "cancelled", "openChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3299
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldDangerZoneComponent, isStandalone: true, selector: "fold-danger-zone", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, actionLabel: { classPropertyName: "actionLabel", publicName: "actionLabel", isSignal: true, isRequired: false, transformFunction: null }, confirmPhrase: { classPropertyName: "confirmPhrase", publicName: "confirmPhrase", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, intent: { classPropertyName: "intent", publicName: "intent", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { confirmed: "confirmed" }, host: { attributes: { "role": "group" }, properties: { "attr.data-appearance": "appearance()", "attr.aria-labelledby": "titleId" } }, ngImport: i0, template: "<div class=\"dz-head\">\n <fold-icon name=\"warning\" size=\"sm\" class=\"dz-icon\" aria-hidden=\"true\" />\n <h3 class=\"dz-title\" [id]=\"titleId\">{{ title() }}</h3>\n</div>\n\n<div class=\"dz-body\">\n <ng-content />\n</div>\n\n@if (actionLabel(); as label) {\n <div class=\"dz-actions\">\n <fold-inline-confirm\n [match]=\"confirmPhrase() ?? ''\"\n [message]=\"message() ?? ''\"\n [intent]=\"intent()\"\n (confirmed)=\"confirmed.emit($event)\"\n >\n <button foldButton emphasis=\"solid\" [intent]=\"intent()\">\n {{ label }}\n </button>\n </fold-inline-confirm>\n </div>\n}\n", styles: [":host{display:block;border:1px solid var(--fold-color-alert-border);border-radius:var(--fold-radius-md, 10px);overflow:hidden;min-height:min-content}:host([data-appearance=filled]){background:var(--fold-color-alert-surface)}:host([data-appearance=section]){background:var(--fold-color-surface-card)}.dz-head{display:flex;align-items:center;gap:.5rem;padding:var(--fold-space-lg) var(--fold-space-lg) var(--fold-space-sm);color:var(--fold-color-alert-text)}.dz-icon{flex:none}.dz-title{margin:0;font-size:var(--fold-text-md, 1rem);font-weight:600}.dz-body{padding:0 var(--fold-space-lg) var(--fold-space-md);color:var(--fold-color-text-secondary);font-size:var(--fold-text-sm, .875rem);line-height:1.5}.dz-body:empty{display:none}.dz-body :first-child{margin-top:0}.dz-body :last-child{margin-bottom:0}.dz-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--fold-space-sm);padding:var(--fold-space-md) var(--fold-space-lg)}:host([data-appearance=section]) .dz-actions{border-top:1px solid var(--fold-color-border-subtle);background:var(--fold-color-surface-sunken)}@media(forced-colors:active){:host{border-color:CanvasText}:host([data-appearance=section]) .dz-actions{border-top-color:CanvasText}}\n"], dependencies: [{ kind: "component", type: FoldIconComponent, selector: "fold-icon", inputs: ["name", "size", "tone", "title"] }, { kind: "component", type: FoldButtonComponent, selector: "button[foldButton], a[foldButton]", inputs: ["emphasis", "intent", "size", "shape", "block", "icon", "iconTrailing", "type", "disabled", "loading"] }, { kind: "component", type: FoldInlineConfirmComponent, selector: "fold-inline-confirm", inputs: ["intent", "message", "match", "password", "placeholder", "loading", "size", "confirmIcon", "cancelIcon", "keepOpenOnConfirm", "labels", "open"], outputs: ["confirmed", "cancelled", "openChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3300
3300
  }
3301
3301
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldDangerZoneComponent, decorators: [{
3302
3302
  type: Component,
@@ -3304,7 +3304,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
3304
3304
  role: "group",
3305
3305
  "[attr.data-appearance]": "appearance()",
3306
3306
  "[attr.aria-labelledby]": "titleId",
3307
- }, template: "<div class=\"dz-head\">\n <fold-icon name=\"warning\" size=\"sm\" class=\"dz-icon\" aria-hidden=\"true\" />\n <h3 class=\"dz-title\" [id]=\"titleId\">{{ title() }}</h3>\n</div>\n\n<div class=\"dz-body\">\n <ng-content />\n</div>\n\n@if (actionLabel(); as label) {\n <div class=\"dz-actions\">\n <fold-inline-confirm\n [match]=\"confirmPhrase() ?? ''\"\n [message]=\"message() ?? ''\"\n [intent]=\"intent()\"\n (confirmed)=\"confirmed.emit($event)\"\n >\n <button foldButton emphasis=\"solid\" [intent]=\"intent()\">\n {{ label }}\n </button>\n </fold-inline-confirm>\n </div>\n}\n", styles: [":host{display:block;border:1px solid var(--fold-color-alert-border);border-radius:var(--fold-radius-md, 10px);overflow:hidden}:host([data-appearance=filled]){background:var(--fold-color-alert-surface)}:host([data-appearance=section]){background:var(--fold-color-surface-card)}.dz-head{display:flex;align-items:center;gap:.5rem;padding:var(--fold-space-lg) var(--fold-space-lg) var(--fold-space-sm);color:var(--fold-color-alert-text)}.dz-icon{flex:none}.dz-title{margin:0;font-size:var(--fold-text-md, 1rem);font-weight:600}.dz-body{padding:0 var(--fold-space-lg) var(--fold-space-md);color:var(--fold-color-text-secondary);font-size:var(--fold-text-sm, .875rem);line-height:1.5}.dz-body:empty{display:none}.dz-body :first-child{margin-top:0}.dz-body :last-child{margin-bottom:0}.dz-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--fold-space-sm);padding:var(--fold-space-md) var(--fold-space-lg)}:host([data-appearance=section]) .dz-actions{border-top:1px solid var(--fold-color-border-subtle);background:var(--fold-color-surface-sunken)}@media(forced-colors:active){:host{border-color:CanvasText}:host([data-appearance=section]) .dz-actions{border-top-color:CanvasText}}\n"] }]
3307
+ }, template: "<div class=\"dz-head\">\n <fold-icon name=\"warning\" size=\"sm\" class=\"dz-icon\" aria-hidden=\"true\" />\n <h3 class=\"dz-title\" [id]=\"titleId\">{{ title() }}</h3>\n</div>\n\n<div class=\"dz-body\">\n <ng-content />\n</div>\n\n@if (actionLabel(); as label) {\n <div class=\"dz-actions\">\n <fold-inline-confirm\n [match]=\"confirmPhrase() ?? ''\"\n [message]=\"message() ?? ''\"\n [intent]=\"intent()\"\n (confirmed)=\"confirmed.emit($event)\"\n >\n <button foldButton emphasis=\"solid\" [intent]=\"intent()\">\n {{ label }}\n </button>\n </fold-inline-confirm>\n </div>\n}\n", styles: [":host{display:block;border:1px solid var(--fold-color-alert-border);border-radius:var(--fold-radius-md, 10px);overflow:hidden;min-height:min-content}:host([data-appearance=filled]){background:var(--fold-color-alert-surface)}:host([data-appearance=section]){background:var(--fold-color-surface-card)}.dz-head{display:flex;align-items:center;gap:.5rem;padding:var(--fold-space-lg) var(--fold-space-lg) var(--fold-space-sm);color:var(--fold-color-alert-text)}.dz-icon{flex:none}.dz-title{margin:0;font-size:var(--fold-text-md, 1rem);font-weight:600}.dz-body{padding:0 var(--fold-space-lg) var(--fold-space-md);color:var(--fold-color-text-secondary);font-size:var(--fold-text-sm, .875rem);line-height:1.5}.dz-body:empty{display:none}.dz-body :first-child{margin-top:0}.dz-body :last-child{margin-bottom:0}.dz-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--fold-space-sm);padding:var(--fold-space-md) var(--fold-space-lg)}:host([data-appearance=section]) .dz-actions{border-top:1px solid var(--fold-color-border-subtle);background:var(--fold-color-surface-sunken)}@media(forced-colors:active){:host{border-color:CanvasText}:host([data-appearance=section]) .dz-actions{border-top-color:CanvasText}}\n"] }]
3308
3308
  }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], actionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionLabel", required: false }] }], confirmPhrase: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmPhrase", required: false }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }], intent: [{ type: i0.Input, args: [{ isSignal: true, alias: "intent", required: false }] }], confirmed: [{ type: i0.Output, args: ["confirmed"] }] } });
3309
3309
 
3310
3310
  /**
@@ -12451,7 +12451,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
12451
12451
  * failure this component prevents.
12452
12452
  *
12453
12453
  * It also lays its children out in a column with the standard gap, so a panel
12454
- * stops setting a margin on every field.
12454
+ * stops setting a margin on every field. That column is a **grid**, not a flex
12455
+ * column, for a reason worth stating: in a flex column every child may shrink,
12456
+ * and a child whose `overflow` is not `visible` has an automatic minimum size
12457
+ * of **zero** — it is crushed to its borders rather than allowed to overflow.
12458
+ * A `fold-danger-zone` (rounded corners, so `overflow: hidden`) measured 2px in
12459
+ * a full panel: a destructive-action block erased, with almost no overflow left
12460
+ * to scroll to either. `grid-auto-rows: max-content` sizes each row to its
12461
+ * content and lets the box overflow, which is what a scrolling column is for.
12455
12462
  *
12456
12463
  * ```html
12457
12464
  * <fold-panel-header title="Réglage" />
@@ -12469,11 +12476,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
12469
12476
  */
12470
12477
  class FoldPanelBodyComponent {
12471
12478
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldPanelBodyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12472
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.8", type: FoldPanelBodyComponent, isStandalone: true, selector: "fold-panel-body", ngImport: i0, template: "<ng-content />", isInline: true, styles: [":host{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--fold-space-md);min-height:0;overflow-y:auto;padding:var(--fold-space-lg)}@container (max-width: 640px){:host{padding:var(--fold-space-md)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
12479
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.8", type: FoldPanelBodyComponent, isStandalone: true, selector: "fold-panel-body", ngImport: i0, template: "<ng-content />", isInline: true, styles: [":host{display:grid;grid-template-columns:minmax(0,1fr);grid-auto-rows:max-content;align-content:start;flex:1 1 auto;gap:var(--fold-space-md);min-height:0;overflow-y:auto;padding:var(--fold-space-lg)}@container (max-width: 640px){:host{padding:var(--fold-space-md)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
12473
12480
  }
12474
12481
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldPanelBodyComponent, decorators: [{
12475
12482
  type: Component,
12476
- args: [{ selector: "fold-panel-body", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content />", styles: [":host{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--fold-space-md);min-height:0;overflow-y:auto;padding:var(--fold-space-lg)}@container (max-width: 640px){:host{padding:var(--fold-space-md)}}\n"] }]
12483
+ args: [{ selector: "fold-panel-body", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content />", styles: [":host{display:grid;grid-template-columns:minmax(0,1fr);grid-auto-rows:max-content;align-content:start;flex:1 1 auto;gap:var(--fold-space-md);min-height:0;overflow-y:auto;padding:var(--fold-space-lg)}@container (max-width: 640px){:host{padding:var(--fold-space-md)}}\n"] }]
12477
12484
  }] });
12478
12485
 
12479
12486
  /**