forty-cdk 0.27.0 → 0.28.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/accordion/README.md +2 -2
- package/aspect-ratio/README.md +1 -1
- package/avatar/README.md +2 -2
- package/breadcrumbs/README.md +2 -0
- package/button/README.md +1 -1
- package/calendar/README.md +11 -4
- package/carousel/README.md +41 -15
- package/checkbox/README.md +2 -2
- package/combobox/README.md +1 -1
- package/context-menu/README.md +3 -2
- package/date-field/README.md +20 -15
- package/date-picker/README.md +3 -1
- package/dialog/README.md +47 -12
- package/disclosure/README.md +2 -2
- package/drag-drop/README.md +41 -1
- package/drawer/README.md +17 -7
- package/dropdown-menu/README.md +2 -2
- package/fesm2022/forty-cdk-avatar.mjs +4 -0
- package/fesm2022/forty-cdk-avatar.mjs.map +1 -1
- package/fesm2022/forty-cdk-breadcrumbs.mjs +8 -4
- package/fesm2022/forty-cdk-breadcrumbs.mjs.map +1 -1
- package/fesm2022/forty-cdk-breakpoints.mjs +4 -1
- package/fesm2022/forty-cdk-breakpoints.mjs.map +1 -1
- package/fesm2022/forty-cdk-calendar.mjs +7 -1
- package/fesm2022/forty-cdk-calendar.mjs.map +1 -1
- package/fesm2022/forty-cdk-carousel.mjs +28 -11
- package/fesm2022/forty-cdk-carousel.mjs.map +1 -1
- package/fesm2022/forty-cdk-combobox.mjs +16 -8
- package/fesm2022/forty-cdk-combobox.mjs.map +1 -1
- package/fesm2022/forty-cdk-context-menu.mjs +61 -15
- package/fesm2022/forty-cdk-context-menu.mjs.map +1 -1
- package/fesm2022/forty-cdk-core-overlay.mjs +172 -100
- package/fesm2022/forty-cdk-core-overlay.mjs.map +1 -1
- package/fesm2022/forty-cdk-core.mjs +149 -8
- package/fesm2022/forty-cdk-core.mjs.map +1 -1
- package/fesm2022/forty-cdk-date-field.mjs +26 -12
- package/fesm2022/forty-cdk-date-field.mjs.map +1 -1
- package/fesm2022/forty-cdk-date-picker.mjs +14 -2
- package/fesm2022/forty-cdk-date-picker.mjs.map +1 -1
- package/fesm2022/forty-cdk-dialog.mjs +142 -8
- package/fesm2022/forty-cdk-dialog.mjs.map +1 -1
- package/fesm2022/forty-cdk-drag-drop.mjs +11 -4
- package/fesm2022/forty-cdk-drag-drop.mjs.map +1 -1
- package/fesm2022/forty-cdk-drawer.mjs +90 -7
- package/fesm2022/forty-cdk-drawer.mjs.map +1 -1
- package/fesm2022/forty-cdk-dropdown-menu.mjs +4 -0
- package/fesm2022/forty-cdk-dropdown-menu.mjs.map +1 -1
- package/fesm2022/forty-cdk-field.mjs +47 -2
- package/fesm2022/forty-cdk-field.mjs.map +1 -1
- package/fesm2022/forty-cdk-hover-card.mjs +11 -6
- package/fesm2022/forty-cdk-hover-card.mjs.map +1 -1
- package/fesm2022/forty-cdk-listbox.mjs +4 -0
- package/fesm2022/forty-cdk-listbox.mjs.map +1 -1
- package/fesm2022/forty-cdk-menu.mjs +4 -0
- package/fesm2022/forty-cdk-menu.mjs.map +1 -1
- package/fesm2022/forty-cdk-menubar.mjs +4 -0
- package/fesm2022/forty-cdk-menubar.mjs.map +1 -1
- package/fesm2022/forty-cdk-navigation-menu.mjs +4 -0
- package/fesm2022/forty-cdk-navigation-menu.mjs.map +1 -1
- package/fesm2022/forty-cdk-number-input.mjs +4 -0
- package/fesm2022/forty-cdk-number-input.mjs.map +1 -1
- package/fesm2022/forty-cdk-pagination.mjs +4 -0
- package/fesm2022/forty-cdk-pagination.mjs.map +1 -1
- package/fesm2022/forty-cdk-popover.mjs +86 -7
- package/fesm2022/forty-cdk-popover.mjs.map +1 -1
- package/fesm2022/forty-cdk-progress.mjs +7 -3
- package/fesm2022/forty-cdk-progress.mjs.map +1 -1
- package/fesm2022/forty-cdk-radio-group.mjs +4 -0
- package/fesm2022/forty-cdk-radio-group.mjs.map +1 -1
- package/fesm2022/forty-cdk-scroll-area.mjs +4 -0
- package/fesm2022/forty-cdk-scroll-area.mjs.map +1 -1
- package/fesm2022/forty-cdk-search.mjs +8 -4
- package/fesm2022/forty-cdk-search.mjs.map +1 -1
- package/fesm2022/forty-cdk-select.mjs +10 -2
- package/fesm2022/forty-cdk-select.mjs.map +1 -1
- package/fesm2022/forty-cdk-slider.mjs +4 -0
- package/fesm2022/forty-cdk-slider.mjs.map +1 -1
- package/fesm2022/forty-cdk-stepper.mjs +4 -0
- package/fesm2022/forty-cdk-stepper.mjs.map +1 -1
- package/fesm2022/forty-cdk-table.mjs +3 -1
- package/fesm2022/forty-cdk-table.mjs.map +1 -1
- package/fesm2022/forty-cdk-tabs.mjs +4 -0
- package/fesm2022/forty-cdk-tabs.mjs.map +1 -1
- package/fesm2022/forty-cdk-time-field.mjs +26 -12
- package/fesm2022/forty-cdk-time-field.mjs.map +1 -1
- package/fesm2022/forty-cdk-time-picker.mjs +10 -2
- package/fesm2022/forty-cdk-time-picker.mjs.map +1 -1
- package/fesm2022/forty-cdk-toast.mjs +76 -21
- package/fesm2022/forty-cdk-toast.mjs.map +1 -1
- package/fesm2022/forty-cdk-toggle.mjs +4 -0
- package/fesm2022/forty-cdk-toggle.mjs.map +1 -1
- package/fesm2022/forty-cdk-toolbar.mjs +4 -0
- package/fesm2022/forty-cdk-toolbar.mjs.map +1 -1
- package/fesm2022/forty-cdk-tooltip.mjs +17 -5
- package/fesm2022/forty-cdk-tooltip.mjs.map +1 -1
- package/fesm2022/forty-cdk-tree.mjs +4 -0
- package/fesm2022/forty-cdk-tree.mjs.map +1 -1
- package/fesm2022/forty-cdk-virtualization.mjs +41 -2
- package/fesm2022/forty-cdk-virtualization.mjs.map +1 -1
- package/field/README.md +24 -2
- package/fieldset/README.md +2 -2
- package/file-upload/README.md +2 -2
- package/hover-card/README.md +19 -3
- package/input/README.md +1 -1
- package/listbox/README.md +2 -2
- package/menu/README.md +2 -2
- package/menubar/README.md +2 -2
- package/meter/README.md +2 -2
- package/navigation-menu/README.md +2 -2
- package/number-input/README.md +1 -1
- package/otp-input/README.md +1 -1
- package/package.json +1 -1
- package/pagination/README.md +1 -1
- package/pane-resizer/README.md +1 -1
- package/popover/README.md +30 -3
- package/progress/README.md +2 -2
- package/radio-group/README.md +1 -1
- package/scroll-area/README.md +2 -2
- package/select/README.md +1 -1
- package/separator/README.md +1 -1
- package/shared/README.md +27 -1
- package/slider/README.md +1 -1
- package/stepper/README.md +2 -2
- package/switch/README.md +1 -1
- package/table/README.md +1 -1
- package/tabs/README.md +2 -2
- package/time-field/README.md +20 -15
- package/toast/README.md +44 -6
- package/toggle/README.md +1 -1
- package/toolbar/README.md +2 -2
- package/tooltip/README.md +19 -3
- package/tree/README.md +4 -2
- package/types/forty-cdk-avatar.d.ts +5 -1
- package/types/forty-cdk-breadcrumbs.d.ts +8 -3
- package/types/forty-cdk-breakpoints.d.ts +4 -1
- package/types/forty-cdk-calendar.d.ts +16 -4
- package/types/forty-cdk-carousel.d.ts +29 -7
- package/types/forty-cdk-combobox.d.ts +13 -6
- package/types/forty-cdk-context-menu.d.ts +30 -4
- package/types/forty-cdk-core-overlay.d.ts +144 -81
- package/types/forty-cdk-core.d.ts +92 -6
- package/types/forty-cdk-date-field.d.ts +34 -12
- package/types/forty-cdk-date-picker.d.ts +13 -2
- package/types/forty-cdk-dialog.d.ts +73 -4
- package/types/forty-cdk-drag-drop.d.ts +14 -7
- package/types/forty-cdk-drawer.d.ts +66 -4
- package/types/forty-cdk-dropdown-menu.d.ts +5 -1
- package/types/forty-cdk-field.d.ts +35 -1
- package/types/forty-cdk-hover-card.d.ts +24 -6
- package/types/forty-cdk-listbox.d.ts +5 -1
- package/types/forty-cdk-menu.d.ts +5 -1
- package/types/forty-cdk-menubar.d.ts +5 -1
- package/types/forty-cdk-navigation-menu.d.ts +5 -1
- package/types/forty-cdk-number-input.d.ts +5 -1
- package/types/forty-cdk-pagination.d.ts +5 -1
- package/types/forty-cdk-popover.d.ts +69 -4
- package/types/forty-cdk-progress.d.ts +7 -2
- package/types/forty-cdk-radio-group.d.ts +5 -1
- package/types/forty-cdk-scroll-area.d.ts +5 -1
- package/types/forty-cdk-search.d.ts +8 -4
- package/types/forty-cdk-select.d.ts +8 -1
- package/types/forty-cdk-shared.d.ts +1 -1
- package/types/forty-cdk-slider.d.ts +5 -1
- package/types/forty-cdk-stepper.d.ts +5 -1
- package/types/forty-cdk-tabs.d.ts +5 -1
- package/types/forty-cdk-time-field.d.ts +33 -11
- package/types/forty-cdk-time-picker.d.ts +8 -1
- package/types/forty-cdk-toast.d.ts +78 -21
- package/types/forty-cdk-toggle.d.ts +5 -1
- package/types/forty-cdk-toolbar.d.ts +5 -1
- package/types/forty-cdk-tooltip.d.ts +30 -6
- package/types/forty-cdk-tree.d.ts +5 -1
- package/types/forty-cdk-virtualization.d.ts +7 -1
- package/virtualization/README.md +6 -1
- package/visually-hidden/README.md +1 -1
package/accordion/README.md
CHANGED
|
@@ -175,7 +175,7 @@ A disabled item cannot be toggled and is skipped by the arrow keys, while stayin
|
|
|
175
175
|
|
|
176
176
|
## Styling
|
|
177
177
|
|
|
178
|
-
forty-cdk ships no styles
|
|
178
|
+
forty-cdk ships no styles: put your own class on each piece and key your CSS off the `data-*` attributes listed under [API](#api), not off the `for*` selectors ([Styling forty-cdk](../../../docs/styling.md) explains why).
|
|
179
179
|
|
|
180
180
|
```css
|
|
181
181
|
.chevron {
|
|
@@ -189,4 +189,4 @@ forty-cdk ships no styles. Add your own class to each piece. The `for*` selector
|
|
|
189
189
|
|
|
190
190
|
## Wrapping in a design system
|
|
191
191
|
|
|
192
|
-
|
|
192
|
+
Subclass the root and re-provide `FOR_ACCORDION_CONTEXT` with `useExisting` pointing at the subclass, since Angular does not inherit a directive's `providers`; [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md) walks the pattern.
|
package/aspect-ratio/README.md
CHANGED
|
@@ -76,7 +76,7 @@ Set `ratio` to `1` to keep a box perfectly square at any width. That is handy fo
|
|
|
76
76
|
|
|
77
77
|
## Styling
|
|
78
78
|
|
|
79
|
-
forty-cdk ships no styles
|
|
79
|
+
forty-cdk ships no styles: put your own class on the host rather than styling the `for*` selector ([Styling forty-cdk](../../../docs/styling.md) explains why). This primitive is purely structural: its only host effect is the native `aspect-ratio` style, so it reflects no `data-*` attributes and writes no CSS custom properties.
|
|
80
80
|
|
|
81
81
|
## Behavior notes
|
|
82
82
|
|
package/avatar/README.md
CHANGED
|
@@ -102,7 +102,7 @@ The directive does not impose a `role`. Pair the avatar with visible name text o
|
|
|
102
102
|
|
|
103
103
|
## Styling
|
|
104
104
|
|
|
105
|
-
forty-cdk ships no styles
|
|
105
|
+
forty-cdk ships no styles: put your own class on each piece and key your CSS off the `data-*` attributes listed under [API](#api), not off the `for*` selectors ([Styling forty-cdk](../../../docs/styling.md) explains why).
|
|
106
106
|
|
|
107
107
|
```css
|
|
108
108
|
.avatar-image:not([data-status='loaded']) {
|
|
@@ -122,4 +122,4 @@ forty-cdk ships no styles. Add your own class to each piece. The `for*` selector
|
|
|
122
122
|
|
|
123
123
|
## Wrapping in a design system
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
Subclass the root and re-provide `FOR_AVATAR_CONTEXT` with `useExisting` pointing at the subclass, since Angular does not inherit a directive's `providers`; [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md) walks the pattern.
|
package/breadcrumbs/README.md
CHANGED
|
@@ -100,6 +100,8 @@ bootstrapApplication(App, {
|
|
|
100
100
|
});
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
+
For a language the app sets or switches after bootstrap, pass `label` as a function and the overrides as a factory, as [Localizing default text](../shared/README.md#localizing-default-text) shows.
|
|
104
|
+
|
|
103
105
|
## API
|
|
104
106
|
|
|
105
107
|
### `ForBreadcrumbs`
|
package/button/README.md
CHANGED
|
@@ -115,7 +115,7 @@ Implements the [WAI-ARIA Button pattern](https://www.w3.org/WAI/ARIA/apg/pattern
|
|
|
115
115
|
|
|
116
116
|
## Styling
|
|
117
117
|
|
|
118
|
-
forty-cdk ships no styles
|
|
118
|
+
forty-cdk ships no styles: put your own class on each piece and key your CSS off the `data-*` attributes listed under [API](#api), not off the `for*` selectors ([Styling forty-cdk](../../../docs/styling.md) explains why).
|
|
119
119
|
|
|
120
120
|
```css
|
|
121
121
|
[forButton][data-disabled] {
|
package/calendar/README.md
CHANGED
|
@@ -220,7 +220,7 @@ Click the heading button to cycle from day → month → year view. Click a mont
|
|
|
220
220
|
| `min` | `input<D \| null>` | Minimum selectable date (inclusive). Earlier dates are unavailable.<br>**Default:** `null` |
|
|
221
221
|
| `max` | `input<D \| null>` | Maximum selectable date (inclusive). Later dates are unavailable.<br>**Default:** `null` |
|
|
222
222
|
| `isDateUnavailable` | `input<(date: D) => boolean>` | Per-date predicate marking a date unavailable (present but not selectable).<br>**Default:** `() => false` |
|
|
223
|
-
| `dateLabel` | `input<CalendarDateLabelFormatter<D>>` | Formats each gridcell's `aria-label` (full accessible date).<br>**Default:** localized full date, outside-month days
|
|
223
|
+
| `dateLabel` | `input<CalendarDateLabelFormatter<D>>` | Formats each gridcell's `aria-label` (full accessible date).<br>**Default:** localized full date, outside-month days through the scope's `outsideMonthLabel` |
|
|
224
224
|
| `disabled` | `input<boolean>` | Disables the whole calendar (no focus movement, no selection). Reflected as `data-disabled`.<br>**Default:** — |
|
|
225
225
|
| `readonly` | `input<boolean>` | Read-only: dates stay focusable, selection is blocked. Reflected as `data-readonly`.<br>**Default:** — |
|
|
226
226
|
| `firstDayOfWeek` | `input<number \| null>` | First column's weekday, **0-6** (`0` = Sunday).<br>**Default:** `null` → the adapter's value (or `provideForCalendarDefaults`) |
|
|
@@ -538,9 +538,16 @@ Auto-disabled when the entire previous / next page would be outside `[min, max]`
|
|
|
538
538
|
import { provideForCalendarDefaults } from 'forty-cdk/calendar';
|
|
539
539
|
|
|
540
540
|
// app config or a component's providers — Monday-first weeks for this scope
|
|
541
|
-
providers: [
|
|
541
|
+
providers: [
|
|
542
|
+
provideForCalendarDefaults({
|
|
543
|
+
firstDayOfWeek: 1,
|
|
544
|
+
outsideMonthLabel: (formattedDate) => `${formattedDate} (fuera del mes)`,
|
|
545
|
+
}),
|
|
546
|
+
];
|
|
542
547
|
```
|
|
543
548
|
|
|
549
|
+
`outsideMonthLabel` builds the `aria-label` of a padding day outside the visible month from its formatted full date (default `"<date> (outside month)"`), so assistive tech can tell it apart from the month on screen. A calendar bound to its own `[dateLabel]` formatter ignores it.
|
|
550
|
+
|
|
544
551
|
## Keyboard
|
|
545
552
|
|
|
546
553
|
LTR (horizontal arrows mirror under `dir="rtl"`):
|
|
@@ -569,7 +576,7 @@ Implements the [WAI-ARIA Grid pattern](https://www.w3.org/WAI/ARIA/apg/patterns/
|
|
|
569
576
|
|
|
570
577
|
## Styling
|
|
571
578
|
|
|
572
|
-
forty-cdk ships no styles
|
|
579
|
+
forty-cdk ships no styles: put your own class on each piece and key your CSS off the `data-*` attributes listed under [Data attributes](#data-attributes), not off the `forCalendar*` selectors ([Styling forty-cdk](../../../docs/styling.md) explains why).
|
|
573
580
|
|
|
574
581
|
```css
|
|
575
582
|
.calendar-cell {
|
|
@@ -615,4 +622,4 @@ export class DatePage {
|
|
|
615
622
|
|
|
616
623
|
## Wrapping in a design system
|
|
617
624
|
|
|
618
|
-
|
|
625
|
+
Subclass the root and re-provide `FOR_CALENDAR_CONTEXT` with `useExisting` pointing at the subclass, since Angular does not inherit a directive's `providers`; [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md) walks the pattern.
|
package/carousel/README.md
CHANGED
|
@@ -74,7 +74,8 @@ import {
|
|
|
74
74
|
|
|
75
75
|
interface Slide {
|
|
76
76
|
readonly id: number;
|
|
77
|
-
readonly
|
|
77
|
+
readonly title: string;
|
|
78
|
+
readonly summary: string;
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
@Component({
|
|
@@ -98,7 +99,7 @@ interface Slide {
|
|
|
98
99
|
loop
|
|
99
100
|
orientation="horizontal"
|
|
100
101
|
align="start"
|
|
101
|
-
ariaLabel="Featured
|
|
102
|
+
ariaLabel="Featured stories"
|
|
102
103
|
>
|
|
103
104
|
<div class="car-controls-row">
|
|
104
105
|
<button forCarouselPrevious class="car-btn" aria-label="Previous slide">
|
|
@@ -131,7 +132,8 @@ interface Slide {
|
|
|
131
132
|
<div forCarouselTrack class="car-track">
|
|
132
133
|
@for (slide of slides; track slide.id; let i = $index) {
|
|
133
134
|
<div forCarouselSlide class="car-slide" [class]="'car-slide--' + (i + 1)">
|
|
134
|
-
<
|
|
135
|
+
<p class="car-slide-title">{{ slide.title }}</p>
|
|
136
|
+
<p class="car-slide-summary">{{ slide.summary }}</p>
|
|
135
137
|
</div>
|
|
136
138
|
}
|
|
137
139
|
</div>
|
|
@@ -151,11 +153,27 @@ interface Slide {
|
|
|
151
153
|
})
|
|
152
154
|
export class CarouselDefaultExample {
|
|
153
155
|
protected readonly slides: readonly Slide[] = [
|
|
154
|
-
{
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
{
|
|
157
|
+
id: 1,
|
|
158
|
+
title: 'The coast road north',
|
|
159
|
+
summary: 'Four days, three ferries and one small car.',
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
id: 2,
|
|
163
|
+
title: 'Markets before dawn',
|
|
164
|
+
summary: 'Where the city buys its fish, flowers and coffee.',
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
id: 3,
|
|
168
|
+
title: 'A week without screens',
|
|
169
|
+
summary: 'What changed, and the one habit that stuck.',
|
|
170
|
+
},
|
|
171
|
+
{ id: 4, title: 'Bread, slowly', summary: 'A starter, a schedule and a forgiving first loaf.' },
|
|
172
|
+
{
|
|
173
|
+
id: 5,
|
|
174
|
+
title: 'Mapping the old river',
|
|
175
|
+
summary: 'Tracing a buried stream through five neighbourhoods.',
|
|
176
|
+
},
|
|
159
177
|
];
|
|
160
178
|
|
|
161
179
|
protected readonly activeIndex = signal(0);
|
|
@@ -339,9 +357,11 @@ captured, so page scrolling on the perpendicular axis is unaffected.
|
|
|
339
357
|
|
|
340
358
|
Each slide's default `aria-label` is the positional `"N of M"` string, each
|
|
341
359
|
indicator's is `"Go to slide N"`, and the rotation control's swaps between
|
|
342
|
-
`"Start automatic slide show"` and `"Stop automatic slide show"`.
|
|
343
|
-
|
|
344
|
-
|
|
360
|
+
`"Start automatic slide show"` and `"Stop automatic slide show"`. The root and
|
|
361
|
+
each slide also carry an `aria-roledescription` (`"carousel"` / `"slide"`), which
|
|
362
|
+
a screen reader speaks in place of the `group` role. Localize them all centrally
|
|
363
|
+
with `provideForCarouselDefaults` instead of setting `ariaLabel` on every slide
|
|
364
|
+
and indicator:
|
|
345
365
|
|
|
346
366
|
<!-- snippet: fragment -->
|
|
347
367
|
|
|
@@ -352,6 +372,8 @@ providers: [
|
|
|
352
372
|
indicatorLabel: (position) => `Ir a la diapositiva ${position}`,
|
|
353
373
|
rotationStartLabel: 'Iniciar la presentación',
|
|
354
374
|
rotationStopLabel: 'Detener la presentación',
|
|
375
|
+
roleDescription: 'carrusel',
|
|
376
|
+
slideRoleDescription: 'diapositiva',
|
|
355
377
|
}),
|
|
356
378
|
];
|
|
357
379
|
```
|
|
@@ -360,7 +382,10 @@ providers: [
|
|
|
360
382
|
merge with the parent scope, so you can localize just the labels and inherit the
|
|
361
383
|
rest of the defaults. A per-element `ariaLabel` on `[forCarouselSlide]` /
|
|
362
384
|
`[forCarouselIndicator]` still takes precedence over the localized default, as do
|
|
363
|
-
`[startLabel]` / `[stopLabel]` on `[forCarouselRotationControl]`.
|
|
385
|
+
`[startLabel]` / `[stopLabel]` on `[forCarouselRotationControl]`. For a language
|
|
386
|
+
the app sets or switches after bootstrap, pass the text keys as functions and the
|
|
387
|
+
overrides as a factory, as
|
|
388
|
+
[Localizing default text](../shared/README.md#localizing-default-text) shows.
|
|
364
389
|
|
|
365
390
|
## Indicators map 1:1 to slides
|
|
366
391
|
|
|
@@ -455,7 +480,8 @@ Implements the [WAI-ARIA Carousel pattern](https://www.w3.org/WAI/ARIA/apg/patte
|
|
|
455
480
|
should describe the carousel's purpose without using the word "carousel" (APG guidance).
|
|
456
481
|
- Each slide carries `role="group"`, `aria-roledescription="slide"`, and
|
|
457
482
|
`aria-label="N of M"` by default. Override per slide with the `ariaLabel` input,
|
|
458
|
-
or localize the default format app-wide with
|
|
483
|
+
or localize the default format and both role descriptions app-wide with
|
|
484
|
+
`provideForCarouselDefaults` (see
|
|
459
485
|
[Localizing the default labels](#localizing-the-default-labels)).
|
|
460
486
|
- Off-view slides receive `aria-hidden="true"` and `inert` to remove them from the
|
|
461
487
|
accessibility tree and focus order.
|
|
@@ -473,7 +499,7 @@ Implements the [WAI-ARIA Carousel pattern](https://www.w3.org/WAI/ARIA/apg/patte
|
|
|
473
499
|
|
|
474
500
|
## Styling
|
|
475
501
|
|
|
476
|
-
forty-cdk ships no styles
|
|
502
|
+
forty-cdk ships no styles: put your own class on each piece rather than styling the `for*` selectors ([Styling forty-cdk](../../../docs/styling.md) explains why). The directive publishes geometry as CSS custom properties on the root element so they cascade to the track. The consumer applies the transform and transition.
|
|
477
503
|
|
|
478
504
|
```css
|
|
479
505
|
[forCarouselViewport] {
|
|
@@ -577,4 +603,4 @@ The example CSS above is LTR-only by default.
|
|
|
577
603
|
|
|
578
604
|
## Wrapping in a design system
|
|
579
605
|
|
|
580
|
-
|
|
606
|
+
Subclass the root and re-provide `FOR_CAROUSEL_CONTEXT` with `useExisting` pointing at the subclass, since Angular does not inherit a directive's `providers`; [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md) walks the pattern.
|
package/checkbox/README.md
CHANGED
|
@@ -188,7 +188,7 @@ Implements the [WAI-ARIA Checkbox pattern](https://www.w3.org/WAI/ARIA/apg/patte
|
|
|
188
188
|
|
|
189
189
|
## Styling
|
|
190
190
|
|
|
191
|
-
forty-cdk ships no styles
|
|
191
|
+
forty-cdk ships no styles: put your own class on each piece and key your CSS off the `data-*` attributes listed under [API](#api), not off the `for*` selectors ([Styling forty-cdk](../../../docs/styling.md) explains why).
|
|
192
192
|
|
|
193
193
|
```css
|
|
194
194
|
.cb-check {
|
|
@@ -213,4 +213,4 @@ forty-cdk ships no styles. Add your own class to each piece. The for\* selectors
|
|
|
213
213
|
|
|
214
214
|
## Wrapping in a design system
|
|
215
215
|
|
|
216
|
-
|
|
216
|
+
[Wrapping form primitives](../../../docs/wrapping-form-primitives.md) documents both supported wrapper patterns: `hostDirectives` with the exported `FOR_CHECKBOX_HOST_DIRECTIVE_INPUTS` / `FOR_CHECKBOX_HOST_DIRECTIVE_OUTPUTS` name tuples, and subclassing.
|
package/combobox/README.md
CHANGED
|
@@ -772,7 +772,7 @@ Implements the [WAI-ARIA Combobox pattern](https://www.w3.org/WAI/ARIA/apg/patte
|
|
|
772
772
|
|
|
773
773
|
## Styling
|
|
774
774
|
|
|
775
|
-
forty-cdk ships no styles
|
|
775
|
+
forty-cdk ships no styles: put your own class on each piece and key your CSS off the `data-*` attributes listed under [Data attributes](#data-attributes), not off the `for*` selectors ([Styling forty-cdk](../../../docs/styling.md) explains why).
|
|
776
776
|
|
|
777
777
|
### CSS custom properties
|
|
778
778
|
|
package/context-menu/README.md
CHANGED
|
@@ -122,7 +122,7 @@ Same vetoable dismiss API as DropdownMenu. Call `preventDefault()` on the emitte
|
|
|
122
122
|
|
|
123
123
|
## Styling
|
|
124
124
|
|
|
125
|
-
forty-cdk ships no styles
|
|
125
|
+
forty-cdk ships no styles: put your own class on each piece and key your CSS off the `data-*` attributes listed under [Data attributes](#data-attributes), not off the `for*` selectors ([Styling forty-cdk](../../../docs/styling.md) explains why).
|
|
126
126
|
|
|
127
127
|
> The menu content (`[forMenuContent]`, from the [`menu/`](../menu/README.md) folder) portals to `document.body`, so it sits outside the trigger's DOM subtree and descendant selectors won't reach it. Style it with **global CSS** or a class on the content element. The content host also exposes the shared positioner custom properties (`--for-floating-anchor-width` / `--for-floating-anchor-height`, `--for-floating-available-width` / `--for-floating-available-height`, `--for-floating-content-transform-origin`); see [Styling floating content](../../../docs/styling-floating-content.md) for the full list and the animation rules.
|
|
128
128
|
|
|
@@ -138,6 +138,7 @@ forty-cdk ships no styles. Add your own class to each piece. The for\* selectors
|
|
|
138
138
|
- **Virtual anchor.** Right-click captures a 0×0 rect at the pointer location. `Shift+F10` and `ContextMenu` snapshot the bounding rect of the focused element (or the trigger if focus is on it directly), so the menu floats off the element under attention. Both forms feed floating-ui's `flip` and `shift` middleware, so corners and screen edges work without special-casing.
|
|
139
139
|
- **Keyboard activators only fire while focus is inside the trigger.** Keyboard events dispatch to the focused element, so `Shift+F10` / `ContextMenu` anywhere outside the trigger goes to the browser default. The trigger is focusable by default (host-bound `tabindex="-1"`), so this works out of the box and focus can return to it programmatically when the menu closes. Your own `tabindex` wins over that default: use `tabindex="0"` if you want the region itself reachable via Tab.
|
|
140
140
|
- **Native menu suppressed.** The trigger calls `event.preventDefault()` on `contextmenu` and on the keyboard activators. Set `disabled` to let the browser's native menu surface for that region.
|
|
141
|
+
- **An open that renders nothing closes again.** When a right-click, `Shift+F10`, the `ContextMenu` key or a long-press opens a menu whose template renders no `[forMenuContent]`, the trigger closes it after the next render with reason `'programmatic'`, and dev mode logs `FORCDK-CONTEXT-MENU-002` once. The native menu cannot come back for that gesture, because it was already suppressed, so bind `[disabled]` to the same condition that renders the content: `[disabled]="!hasActions(col)"` beside `@if (hasActions(col))`.
|
|
141
142
|
- **Touch long-press.** The trigger runs its own long-press timer (a `touch` `pointerdown` held ~500 ms, without lifting or moving past a small tolerance, opens the menu at the touch point). This is required because iOS Safari never fires the `contextmenu` event a long-press synthesizes elsewhere; where the browser does synthesize it (Android, desktop touch emulation) the two paths stay mutually exclusive, so the menu opens exactly once. For the press to survive on iOS, suppress the native callout / text-selection on the trigger with CSS, since otherwise the OS gesture cancels the press:
|
|
142
143
|
|
|
143
144
|
```css
|
|
@@ -201,4 +202,4 @@ Both triggers carry `[menuPositioning]`, a partial `{ side, align, sideOffset, a
|
|
|
201
202
|
|
|
202
203
|
## Wrapping in a design system
|
|
203
204
|
|
|
204
|
-
|
|
205
|
+
Subclass the root and re-provide `FOR_MENU_CONTEXT` with `useExisting` pointing at the subclass, since Angular does not inherit a directive's `providers`; [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md) walks the pattern.
|
package/date-field/README.md
CHANGED
|
@@ -149,17 +149,17 @@ With a time-capable adapter, a `granularity` coarser than `'day'` appends time s
|
|
|
149
149
|
|
|
150
150
|
### `ForDateField`
|
|
151
151
|
|
|
152
|
-
| Property | Type | Description
|
|
153
|
-
| ------------- | ------------------------------------------------ |
|
|
154
|
-
| `value` | `model<D \| null>` | Two-way bindable entered date, or `null` while any segment is empty. The `FormValueControl` backing.<br>**Default:** `null`
|
|
155
|
-
| `minDate` | `input<D \| null>` | Minimum date (inclusive). A composed value below it is clamped up. Named `minDate` (see note below).<br>**Default:** `null`
|
|
156
|
-
| `maxDate` | `input<D \| null>` | Maximum date (inclusive). A composed value above it is clamped down.<br>**Default:** `null`
|
|
157
|
-
| `granularity` | `input<'day' \| 'hour' \| 'minute' \| 'second'>` | Date-time precision. `'day'` is date-only; coarser-than-day appends time segments. See below.<br>**Default:** `'day'`
|
|
158
|
-
| `hourCycle` | `input<12 \| 24 \| null>` | 12/24-hour cycle for the time segments. `null` → locale. 12-hour adds the AM/PM segment.<br>**Default:** `null`
|
|
159
|
-
| `locale` | `input<string \| null>` | BCP 47 locale driving segment order, separators, and month name. `null` → runtime locale.<br>**Default:** `null`
|
|
160
|
-
| `placeholder` | `input<Partial<Record<SegmentType, string>>>` | Per-segment placeholder while empty. Unspecified parts fall back to `dd` / `mm` / `yyyy` / `hh` / `mm` / `ss` / `--`.<br>**Default:** `{}` |
|
|
161
|
-
| `ariaLabel` | `input<string \| null>` | Accessible name for the group. Emits no `aria-label` while `null`.<br>**Default:** `null`
|
|
162
|
-
| `dir` | `input<'ltr' \| 'rtl' \| null>` | Writing direction. `null` resolves the ambient direction; mirrors ArrowLeft / ArrowRight segment navigation.<br>**Default:** `null`
|
|
152
|
+
| Property | Type | Description |
|
|
153
|
+
| ------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
154
|
+
| `value` | `model<D \| null>` | Two-way bindable entered date, or `null` while any segment is empty. The `FormValueControl` backing.<br>**Default:** `null` |
|
|
155
|
+
| `minDate` | `input<D \| null>` | Minimum date (inclusive). A composed value below it is clamped up. Named `minDate` (see note below).<br>**Default:** `null` |
|
|
156
|
+
| `maxDate` | `input<D \| null>` | Maximum date (inclusive). A composed value above it is clamped down.<br>**Default:** `null` |
|
|
157
|
+
| `granularity` | `input<'day' \| 'hour' \| 'minute' \| 'second'>` | Date-time precision. `'day'` is date-only; coarser-than-day appends time segments. See below.<br>**Default:** `'day'` |
|
|
158
|
+
| `hourCycle` | `input<12 \| 24 \| null>` | 12/24-hour cycle for the time segments. `null` → locale. 12-hour adds the AM/PM segment.<br>**Default:** `null` |
|
|
159
|
+
| `locale` | `input<string \| null>` | BCP 47 locale driving segment order, separators, and month name. `null` → runtime locale.<br>**Default:** `null` |
|
|
160
|
+
| `placeholder` | `input<Partial<Record<SegmentType, string>>>` | Per-segment placeholder while empty. Unspecified parts fall back to the scope's `placeholder`, then to `dd` / `mm` / `yyyy` / `hh` / `mm` / `ss` / `--`.<br>**Default:** `{}` |
|
|
161
|
+
| `ariaLabel` | `input<string \| null>` | Accessible name for the group. Emits no `aria-label` while `null`.<br>**Default:** `null` |
|
|
162
|
+
| `dir` | `input<'ltr' \| 'rtl' \| null>` | Writing direction. `null` resolves the ambient direction; mirrors ArrowLeft / ArrowRight segment navigation.<br>**Default:** `null` |
|
|
163
163
|
|
|
164
164
|
Plus the shared `FormUiControl` members from `@angular/forms/signals`: `disabled`, `readonly`, `required`, `invalid`, `name`, `errors`, `touched` (bound automatically by `[formField]`).
|
|
165
165
|
|
|
@@ -207,18 +207,23 @@ On the AM/PM segment, `a` / `p` set the period and ArrowUp / ArrowDown toggle it
|
|
|
207
207
|
```ts
|
|
208
208
|
import { provideForDateFieldDefaults } from 'forty-cdk/date-field';
|
|
209
209
|
|
|
210
|
-
// app config or a component's providers — localize segment labels
|
|
211
|
-
// empty-segment announcement for every nested [forDateField].
|
|
210
|
+
// app config or a component's providers — localize segment labels, the
|
|
211
|
+
// empty-segment announcement and the placeholders for every nested [forDateField].
|
|
212
212
|
providers: [
|
|
213
213
|
provideForDateFieldDefaults({
|
|
214
214
|
emptySegmentText: 'Vacío',
|
|
215
215
|
segmentLabels: { day: 'día', month: 'mes', year: 'año', dayPeriod: 'AM/PM' },
|
|
216
|
+
placeholder: { day: 'dd', month: 'mm', year: 'aaaa' },
|
|
216
217
|
}),
|
|
217
218
|
];
|
|
218
219
|
```
|
|
219
220
|
|
|
220
221
|
`segmentLabels` supplies each segment's default `aria-label`, keyed by part type. Unset keys keep the library default (the part name, and `'AM/PM'` for the `dayPeriod` segment), so overriding a single key never wipes the rest. A segment's own `[ariaLabel]` still wins over the scope default.
|
|
221
222
|
|
|
223
|
+
`placeholder` is the text an empty segment shows, keyed the same way. A field's own `[placeholder]` wins for the parts it names and only those, and a part neither names keeps the letter-repeat default. `provideForDateRangeFieldDefaults` takes the same three keys for `[forDateRangeField]`.
|
|
224
|
+
|
|
225
|
+
For a language the app sets or switches after bootstrap, pass the text keys as functions and the overrides as a factory, as [Localizing default text](../shared/README.md#localizing-default-text) shows.
|
|
226
|
+
|
|
222
227
|
## Range selection — `ForDateRangeField`
|
|
223
228
|
|
|
224
229
|
For a date range use the dedicated `ForDateRangeField` root (selector `[forDateRangeField]`), shipped from this same entry point. It is the keyboard-first, form-capable counterpart to [DateRangePicker](../date-picker/README.md): two labelled `role="group"` endpoints (start / end) nested inside one outer `role="group"`. Each endpoint holds a row of spinbutton segments built on the same machinery as `ForDateField`. It implements `FormValueControl<DateRange<D> | null>`, the **same** contract as `ForDateRangePicker`, so the committed range auto-wires with `[formField]`. The value stays `null` until **both** endpoints are fully entered and ordered (`start <= end`).
|
|
@@ -271,7 +276,7 @@ readonly booking = form(this.model);
|
|
|
271
276
|
| `granularity` | `input<'day' \| 'hour' \| 'minute' \| 'second'>` | Date-time precision shared by both endpoints. `'day'` is date-only; coarser-than-day appends time segments.<br>**Default:** `'day'` |
|
|
272
277
|
| `hourCycle` | `input<12 \| 24 \| null>` | 12/24-hour cycle for the time segments. `null` → locale. 12-hour adds the AM/PM segment.<br>**Default:** `null` |
|
|
273
278
|
| `locale` | `input<string \| null>` | BCP 47 locale driving segment order, separators, and month name. `null` → runtime locale.<br>**Default:** `null` |
|
|
274
|
-
| `placeholder` | `input<Partial<Record<SegmentType, string>>>` | Per-segment placeholder while empty, applied to both endpoints
|
|
279
|
+
| `placeholder` | `input<Partial<Record<SegmentType, string>>>` | Per-segment placeholder while empty, applied to both endpoints. Unspecified parts fall back to the scope's `placeholder`.<br>**Default:** `{}` |
|
|
275
280
|
| `ariaLabel` | `input<string \| null>` | Accessible name for the whole range field group. Emits no `aria-label` while `null`.<br>**Default:** `null` |
|
|
276
281
|
| `dir` | `input<'ltr' \| 'rtl' \| null>` | Writing direction. `null` resolves the ambient direction; mirrors ArrowLeft / ArrowRight segment navigation.<br>**Default:** `null` |
|
|
277
282
|
|
|
@@ -323,7 +328,7 @@ Composes the [WAI-ARIA Spinbutton pattern](https://www.w3.org/WAI/ARIA/apg/patte
|
|
|
323
328
|
|
|
324
329
|
The library is styleless, so style the boolean `data-*` hooks yourself: `[data-highlighted]` (the focused/roving segment), `[data-placeholder]` (empty), `[data-disabled]` and `[data-readonly]` on the segments, and `[data-empty]` / `[data-disabled]` / `[data-readonly]` on the root group.
|
|
325
330
|
|
|
326
|
-
forty-cdk ships no styles
|
|
331
|
+
forty-cdk ships no styles: put your own class on each piece and key your CSS off the `data-*` attributes listed under [Data attributes](#data-attributes), not off the `for*` selectors ([Styling forty-cdk](../../../docs/styling.md) explains why).
|
|
327
332
|
|
|
328
333
|
```css
|
|
329
334
|
.date-field-segment[data-placeholder] {
|
package/date-picker/README.md
CHANGED
|
@@ -288,6 +288,8 @@ Set `granularity` to `'hour'`, `'minute'`, or `'second'` to turn the picker into
|
|
|
288
288
|
|
|
289
289
|
Bind the calendar **and** the time field **one-way** to `picker.value()` (not `[(value)]`). The picker is the single source of truth: when one-way bound to a timed value the calendar preserves the time-of-day on its own selection, and the picker re-grafts the previously entered time as a defensive fallback for the case where the calendar value was null or midnight (reading its own value, which the one-way children never clobber); a time-field edit emits a full date-time the picker mirrors in. A date-time picker never closes on a calendar selection, so the user can go on to set the time.
|
|
290
290
|
|
|
291
|
+
The content is a field boundary. Inside a [`[forField]`](../field/README.md#how-the-control-connects) the time field does not register with the field, which keeps reflecting the picker (its label target, `invalid` state and errors) while the panel is open.
|
|
292
|
+
|
|
291
293
|
```html
|
|
292
294
|
<div
|
|
293
295
|
forDatePicker
|
|
@@ -403,7 +405,7 @@ Implements the [WAI-ARIA Date Picker Dialog pattern](https://www.w3.org/WAI/ARIA
|
|
|
403
405
|
|
|
404
406
|
## Styling
|
|
405
407
|
|
|
406
|
-
forty-cdk ships no styles
|
|
408
|
+
forty-cdk ships no styles: put your own class on each piece and key your CSS off the `data-*` attributes listed under [Data attributes](#data-attributes), not off the `for*` selectors ([Styling forty-cdk](../../../docs/styling.md) explains why).
|
|
407
409
|
|
|
408
410
|
> `[forDatePickerContent]` is portaled to `document.body`, so it lives outside your component's view-encapsulated styles. Style it with **global CSS** (or a class you pass through) rather than component-scoped rules. See [Styling floating content](../../../docs/styling-floating-content.md). In non-modal (anchored) mode the surface also exposes the shared positioner custom properties (`--for-floating-anchor-width` / `--for-floating-anchor-height`, `--for-floating-available-width` / `--for-floating-available-height`, `--for-floating-content-transform-origin`); that same guide tabulates the full set.
|
|
409
411
|
|
package/dialog/README.md
CHANGED
|
@@ -168,9 +168,10 @@ Open a component imperatively and await its result. The manager mounts it under
|
|
|
168
168
|
| `focusOutside` | `OutputEmitterRef<VetoableNativeEvent<FocusEvent>>` | Output. Focus moves outside the dialog.<br>**Default:** — |
|
|
169
169
|
| `interactOutside` | `OutputEmitterRef<VetoableNativeEvent<PointerEvent \| FocusEvent>>` | Output. Composite: fires alongside both of the above (and shares their veto state).<br>**Default:** — |
|
|
170
170
|
|
|
171
|
-
| Data attribute | Values
|
|
172
|
-
| -------------- |
|
|
173
|
-
| `data-state` | `open` (always: the host is only mounted while open, so it is never `closed`)
|
|
171
|
+
| Data attribute | Values |
|
|
172
|
+
| -------------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
173
|
+
| `data-state` | `open` (always: the host is only mounted while open, so it is never `closed`) |
|
|
174
|
+
| `data-depth` | `0` for the first mounted dialog, one above the deepest dialog still mounted otherwise. Fixed for the dialog's lifetime |
|
|
174
175
|
|
|
175
176
|
### Inputs — focus callbacks
|
|
176
177
|
|
|
@@ -194,6 +195,7 @@ The auto-focus pair is bound as **function references** (input callbacks), not a
|
|
|
194
195
|
| -------------------------- | ---------------------------------------------------------------------------------------- |
|
|
195
196
|
| `data-state` | `open` (always, since it is mounted alongside the dialog) |
|
|
196
197
|
| `data-for-dialog-backdrop` | present (stable marker; portaled alongside the dialog, so use it to select the backdrop) |
|
|
198
|
+
| `data-depth` | its dialog's `data-depth` |
|
|
197
199
|
|
|
198
200
|
### `ForDialogClose`
|
|
199
201
|
|
|
@@ -201,6 +203,20 @@ The auto-focus pair is bound as **function references** (input callbacks), not a
|
|
|
201
203
|
| -------------- | --------------------------------------------------------- |
|
|
202
204
|
| `data-state` | `open` (always, since it is mounted alongside the dialog) |
|
|
203
205
|
|
|
206
|
+
### `ForDialogInitialFocus`
|
|
207
|
+
|
|
208
|
+
`[forDialogInitialFocus]` marks the element that receives focus when the enclosing dialog opens, in place of the one `initialFocus` picks. It takes no inputs, and it works inside a component opened with `ForDialogManager.open()` as well, since the marker lives in the content rather than in the caller. When the marked element is missing, disabled or hidden at mount, focus falls back to `initialFocus`; a vetoed `autoFocusOnOpen` still skips the move. Mark one element per dialog: a second marker warns in dev mode and only the newest is used.
|
|
209
|
+
|
|
210
|
+
```html
|
|
211
|
+
<div forDialog (dismiss)="open.set(false)">
|
|
212
|
+
<h2 forDialogTitle>Delete view</h2>
|
|
213
|
+
<button forDialogClose aria-label="Close">×</button>
|
|
214
|
+
<p>This cannot be undone.</p>
|
|
215
|
+
<button forDialogClose forDialogInitialFocus>Cancel</button>
|
|
216
|
+
<button (click)="deleteView()">Delete</button>
|
|
217
|
+
</div>
|
|
218
|
+
```
|
|
219
|
+
|
|
204
220
|
## Programmatic API
|
|
205
221
|
|
|
206
222
|
```ts
|
|
@@ -284,12 +300,12 @@ this.dialogs.open(ConfirmDialog, {
|
|
|
284
300
|
|
|
285
301
|
Set them once for a scope with `provideForDialogDefaults({ animateEnter, animateLeave })`; a per-`open()` value always wins over the scope default.
|
|
286
302
|
|
|
287
|
-
| Symbol | Description
|
|
288
|
-
| ----------------------- |
|
|
289
|
-
| `ForDialogManager` | Injectable. `open(component, config?)` returns a `ForDialogRef<R>`.
|
|
290
|
-
| `ForDialogRef<R>` | `close(result?)`, `closed: Promise<{ reason: ForDialogCloseReason; result: R \| undefined }>`, `result: Signal<R \| undefined>`, `isClosed: Signal<boolean>`.
|
|
291
|
-
| `FOR_DIALOG_DATA` | Token for the `data` payload. Inject in the opened component.
|
|
292
|
-
| `injectDialogData<T>()` | Typed accessor for `FOR_DIALOG_DATA`. Returns `T \| null` (`null` when `open()` got no `data`).
|
|
303
|
+
| Symbol | Description |
|
|
304
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
305
|
+
| `ForDialogManager` | Injectable. `open(component, config?)` returns a `ForDialogRef<R>`. `closeAll(result?)` closes every open dialog, topmost first, with reason `'programmatic'`; exit animations still play and focus ends where the bottom dialog returns it. `openCount` is a `Signal<number>` of the dialogs still open, counting a closed one until its exit animation finishes. |
|
|
306
|
+
| `ForDialogRef<R>` | `close(result?)`, `closed: Promise<{ reason: ForDialogCloseReason; result: R \| undefined }>`, `result: Signal<R \| undefined>`, `isClosed: Signal<boolean>`. |
|
|
307
|
+
| `FOR_DIALOG_DATA` | Token for the `data` payload. Inject in the opened component. |
|
|
308
|
+
| `injectDialogData<T>()` | Typed accessor for `FOR_DIALOG_DATA`. Returns `T \| null` (`null` when `open()` got no `data`). |
|
|
293
309
|
|
|
294
310
|
### `ForDialogOpenConfig`
|
|
295
311
|
|
|
@@ -326,14 +342,15 @@ The four dismiss callbacks mirror the declarative `(escapeKeyDown)` / `(pointerD
|
|
|
326
342
|
|
|
327
343
|
Implements the [WAI-ARIA Modal Dialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/).
|
|
328
344
|
|
|
329
|
-
- Always provide an accessible name: render a `[forDialogTitle]` (sets `aria-labelledby`) or pass `ariaLabel`.
|
|
345
|
+
- Always provide an accessible name: render a `[forDialogTitle]` (sets `aria-labelledby`) or pass `ariaLabel`. A dialog that mounts with neither logs a dev-mode warning (`FORCDK-CORE-011`) after its first render, because a WCAG-tagged audit does not report the missing name.
|
|
346
|
+
- Initial focus follows the APG guidance by default (the first focusable element). When the step is hard to undo, or focusing the first control would scroll the start of the content out of view, mark the least destructive action or a static heading carrying `tabindex="-1"` with [`[forDialogInitialFocus]`](#fordialoginitialfocus).
|
|
330
347
|
- `[forDialogDescription]` is optional. Use it for non-title supporting copy (the question of a confirm, the rationale of an alert).
|
|
331
348
|
- `alert: true` interrupts assistive tech aggressively, so use it only for genuine alerts (lost connection, unsaved changes warning), not for general confirms.
|
|
332
349
|
- Don't put interactive overlays (popovers, menus) outside the focus trap while a modal dialog is open, because they won't be reachable. For a non-modal floating surface anchored to a trigger, use `[forPopover]` instead.
|
|
333
350
|
|
|
334
351
|
## Styling
|
|
335
352
|
|
|
336
|
-
forty-cdk ships no styles
|
|
353
|
+
forty-cdk ships no styles: put your own class on each piece and key your CSS off the `data-*` attributes listed under [API](#api), not off the `for*` selectors ([Styling forty-cdk](../../../docs/styling.md) explains why).
|
|
337
354
|
|
|
338
355
|
> **This dialog portals to `document.body`.** CSS scoped to ancestors of `[forDialog]` (or `[forDialogBackdrop]`) will not apply once the surface is moved to the body. Style it with **global CSS** or a class. Declaratively you write the surface yourself, so add the class directly (`<div forDialog class="my-dialog">`); for programmatically opened instances pass `class` / `classList` on the `ForDialogManager.open()` config. They land on the same `[forDialog]` host that carries `data-state` / `role` / `aria-modal`, merged and never clobbering them.
|
|
339
356
|
|
|
@@ -355,6 +372,24 @@ forty-cdk ships no styles. Add your own class to each piece. The `for*` selector
|
|
|
355
372
|
}
|
|
356
373
|
```
|
|
357
374
|
|
|
375
|
+
**Stacked dialogs.** Each surface and its backdrop publish their stacking position as `data-depth` and `--for-dialog-depth` (`0` for the first dialog, `1` above it, …), shared by declarative and managed dialogs. One rule then covers every level, with each backdrop one step below its own dialog and above every dialog underneath it:
|
|
376
|
+
|
|
377
|
+
```css
|
|
378
|
+
.my-dialog {
|
|
379
|
+
z-index: calc(1010 + var(--for-dialog-depth) * 10);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.my-backdrop {
|
|
383
|
+
z-index: calc(1009 + var(--for-dialog-depth) * 10);
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### CSS custom properties
|
|
388
|
+
|
|
389
|
+
| Property | Meaning |
|
|
390
|
+
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
391
|
+
| `--for-dialog-depth` | Written on `[forDialog]` and `[forDialogBackdrop]`. The dialog's stacking position as a unitless integer, `0` for the first mounted dialog. Fixed for the dialog's lifetime, so a level is never reused. |
|
|
392
|
+
|
|
358
393
|
## Behavior notes
|
|
359
394
|
|
|
360
395
|
- **The `(dismiss)` contract: the consumer owns unmount.** `(dismiss)` reports the dialog's **intent** to be unmounted; it does not flip the consumer's signal. The consumer must call `open.set(false)` (or equivalent) inside the handler. If the handler is omitted or does not update the signal, Escape, backdrop-click, and outside-pointer-down all emit `(dismiss)` but the dialog stays mounted.
|
|
@@ -471,4 +506,4 @@ Pass `[container]` to portal the dialog surface into a specific element instead
|
|
|
471
506
|
|
|
472
507
|
## Wrapping in a design system
|
|
473
508
|
|
|
474
|
-
|
|
509
|
+
Subclass the root and re-provide `FOR_DIALOG_CONTEXT` with `useExisting` pointing at the subclass, since Angular does not inherit a directive's `providers`; [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md) walks the pattern.
|
package/disclosure/README.md
CHANGED
|
@@ -120,7 +120,7 @@ Implements the [WAI-ARIA Disclosure pattern](https://www.w3.org/WAI/ARIA/apg/pat
|
|
|
120
120
|
|
|
121
121
|
## Styling
|
|
122
122
|
|
|
123
|
-
forty-cdk ships no styles
|
|
123
|
+
forty-cdk ships no styles: put your own class on each piece and key your CSS off the `data-*` attributes listed under [API](#api), not off the `for*` selectors ([Styling forty-cdk](../../../docs/styling.md) explains why).
|
|
124
124
|
|
|
125
125
|
```css
|
|
126
126
|
.dis-trigger .chevron {
|
|
@@ -133,4 +133,4 @@ forty-cdk ships no styles. Add your own class to each piece. The `for*` selector
|
|
|
133
133
|
|
|
134
134
|
## Wrapping in a design system
|
|
135
135
|
|
|
136
|
-
|
|
136
|
+
Subclass the root and re-provide `FOR_DISCLOSURE_CONTEXT` with `useExisting` pointing at the subclass, since Angular does not inherit a directive's `providers`; [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md) walks the pattern.
|
package/drag-drop/README.md
CHANGED
|
@@ -178,6 +178,23 @@ Arrow direction follows the list's `orientation` and respects RTL via `dir`. In
|
|
|
178
178
|
|
|
179
179
|
Keyboard lifting, stepping, dropping, and cancellation are announced via ARIA live regions. Override the default messages at any injector scope via `provideForDragDropDefaults` (see Announcement customisation below). Free-drag is pointer-only. There is no WAI-ARIA pattern for "reposition an element", so `[forFreeDrag]` owns no role or ARIA state; the consumer is responsible for keeping the moved element fully usable at its default position.
|
|
180
180
|
|
|
181
|
+
### Role description
|
|
182
|
+
|
|
183
|
+
Each `[forDraggable]` that can be lifted carries `aria-roledescription`, `"sortable"` by default.
|
|
184
|
+
An item that cannot be lifted, through `[dragDisabled]` or a disabled `[forDropList]`, emits none.
|
|
185
|
+
A screen reader that honors the attribute speaks it in place of the element's role name, so
|
|
186
|
+
change it, or turn it off with an empty string, through `itemRoleDescription` at any injector
|
|
187
|
+
scope:
|
|
188
|
+
|
|
189
|
+
<!-- snippet: fragment -->
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
providers: [provideForDragDropDefaults({ itemRoleDescription: 'movable item' })];
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
`[forTableColumnReorder]` turns it off for its header cells, which keep the `columnheader` role
|
|
196
|
+
name and leave "sortable" to `aria-sort`.
|
|
197
|
+
|
|
181
198
|
### Focus after a keyboard drop
|
|
182
199
|
|
|
183
200
|
Applying the move in `(dragDrop)` destroys or re-inserts the lifted element, which would otherwise
|
|
@@ -244,6 +261,29 @@ unaffected.
|
|
|
244
261
|
</li>
|
|
245
262
|
```
|
|
246
263
|
|
|
264
|
+
### Nested controls
|
|
265
|
+
|
|
266
|
+
A control inside a draggable item keeps its press from starting a drag by calling
|
|
267
|
+
`preventDefault()` on its own `pointerdown`. The item stands down on the first pointer move, so
|
|
268
|
+
the press stays with the control; lifting with the keyboard is unaffected.
|
|
269
|
+
|
|
270
|
+
```html
|
|
271
|
+
<li forDraggable [dragData]="item">
|
|
272
|
+
{{ item.label }}
|
|
273
|
+
<button type="button" (pointerdown)="$event.preventDefault()" (click)="remove(item)">
|
|
274
|
+
Remove
|
|
275
|
+
</button>
|
|
276
|
+
</li>
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
- The check lives in the pointer session every drag surface shares, so it holds for
|
|
280
|
+
`[forDraggable]`, `[forFreeDrag]`, `[forListboxReorder]`, `[forTableRowReorder]`,
|
|
281
|
+
`[forTreeNodeDrag]` and `[forVirtualReorder]` alike.
|
|
282
|
+
- A nested control that runs a drag of its own still starts it: the item around it is what
|
|
283
|
+
stands down. That is how a `[forTableColumnResizer]` resizes inside a reorderable header cell.
|
|
284
|
+
- A canceled `pointerdown` suppresses the compatibility mouse events of that press (`mousedown`,
|
|
285
|
+
`mouseup`), so the control must not rely on them. `click` still fires.
|
|
286
|
+
|
|
247
287
|
### Custom preview & placeholder
|
|
248
288
|
|
|
249
289
|
Place `<ng-template forDragPreview>` and/or `<ng-template forDragPlaceholder>` as direct
|
|
@@ -591,4 +631,4 @@ append gap counts).
|
|
|
591
631
|
|
|
592
632
|
## Wrapping in a design system
|
|
593
633
|
|
|
594
|
-
|
|
634
|
+
Subclass the root and re-provide `FOR_DROP_LIST_CONTEXT` with `useExisting` pointing at the subclass, since Angular does not inherit a directive's `providers`; [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md) walks the pattern.
|