forty-cdk 0.14.0 → 0.16.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/README.md +2 -2
- package/accordion/README.md +5 -1
- package/aspect-ratio/README.md +1 -1
- package/avatar/README.md +5 -1
- package/button/README.md +1 -1
- package/calendar/README.md +5 -1
- package/carousel/README.md +59 -29
- package/checkbox/README.md +9 -6
- package/combobox/README.md +25 -18
- package/context-menu/README.md +9 -5
- package/date-field/README.md +13 -13
- package/date-picker/README.md +6 -6
- package/date-range-field/README.md +13 -13
- package/dialog/README.md +10 -6
- package/disclosure/README.md +5 -1
- package/drag-drop/README.md +73 -14
- package/drawer/README.md +38 -31
- package/dropdown-menu/README.md +9 -5
- package/fesm2022/forty-cdk-accordion.mjs +4 -3
- package/fesm2022/forty-cdk-accordion.mjs.map +1 -1
- package/fesm2022/forty-cdk-button.mjs +9 -43
- package/fesm2022/forty-cdk-button.mjs.map +1 -1
- package/fesm2022/forty-cdk-calendar.mjs +10 -8
- package/fesm2022/forty-cdk-calendar.mjs.map +1 -1
- package/fesm2022/forty-cdk-carousel.mjs +101 -41
- package/fesm2022/forty-cdk-carousel.mjs.map +1 -1
- package/fesm2022/forty-cdk-checkbox.mjs +34 -8
- package/fesm2022/forty-cdk-checkbox.mjs.map +1 -1
- package/fesm2022/forty-cdk-combobox.mjs +100 -174
- package/fesm2022/forty-cdk-combobox.mjs.map +1 -1
- package/fesm2022/forty-cdk-context-menu.mjs +2 -2
- package/fesm2022/forty-cdk-context-menu.mjs.map +1 -1
- package/fesm2022/forty-cdk-core.mjs +2319 -3012
- package/fesm2022/forty-cdk-core.mjs.map +1 -1
- package/fesm2022/forty-cdk-date-field.mjs.map +1 -1
- package/fesm2022/forty-cdk-date-picker.mjs +8 -7
- package/fesm2022/forty-cdk-date-picker.mjs.map +1 -1
- package/fesm2022/forty-cdk-dialog.mjs +8 -6
- package/fesm2022/forty-cdk-dialog.mjs.map +1 -1
- package/fesm2022/forty-cdk-disclosure.mjs +4 -3
- package/fesm2022/forty-cdk-disclosure.mjs.map +1 -1
- package/fesm2022/forty-cdk-drag-drop.mjs +439 -60
- package/fesm2022/forty-cdk-drag-drop.mjs.map +1 -1
- package/fesm2022/forty-cdk-drawer.mjs +454 -97
- package/fesm2022/forty-cdk-drawer.mjs.map +1 -1
- package/fesm2022/forty-cdk-dropdown-menu.mjs +7 -6
- package/fesm2022/forty-cdk-dropdown-menu.mjs.map +1 -1
- package/fesm2022/forty-cdk-fieldset.mjs +0 -1
- package/fesm2022/forty-cdk-fieldset.mjs.map +1 -1
- package/fesm2022/forty-cdk-file-upload.mjs +4 -3
- package/fesm2022/forty-cdk-file-upload.mjs.map +1 -1
- package/fesm2022/forty-cdk-hover-card.mjs +4 -4
- package/fesm2022/forty-cdk-hover-card.mjs.map +1 -1
- package/fesm2022/forty-cdk-listbox.mjs +26 -18
- package/fesm2022/forty-cdk-listbox.mjs.map +1 -1
- package/fesm2022/forty-cdk-menu.mjs +28 -19
- package/fesm2022/forty-cdk-menu.mjs.map +1 -1
- package/fesm2022/forty-cdk-menubar.mjs +142 -58
- package/fesm2022/forty-cdk-menubar.mjs.map +1 -1
- package/fesm2022/forty-cdk-navigation-menu.mjs +28 -29
- package/fesm2022/forty-cdk-navigation-menu.mjs.map +1 -1
- package/fesm2022/forty-cdk-number-input.mjs +209 -5
- package/fesm2022/forty-cdk-number-input.mjs.map +1 -1
- package/fesm2022/forty-cdk-otp-input.mjs +14 -14
- package/fesm2022/forty-cdk-otp-input.mjs.map +1 -1
- package/fesm2022/forty-cdk-pagination.mjs +10 -7
- package/fesm2022/forty-cdk-pagination.mjs.map +1 -1
- package/fesm2022/forty-cdk-pane-resizer.mjs +46 -14
- package/fesm2022/forty-cdk-pane-resizer.mjs.map +1 -1
- package/fesm2022/forty-cdk-popover.mjs +12 -10
- package/fesm2022/forty-cdk-popover.mjs.map +1 -1
- package/fesm2022/forty-cdk-radio-group.mjs +4 -3
- package/fesm2022/forty-cdk-radio-group.mjs.map +1 -1
- package/fesm2022/forty-cdk-scroll-area.mjs +407 -105
- package/fesm2022/forty-cdk-scroll-area.mjs.map +1 -1
- package/fesm2022/forty-cdk-search.mjs +5 -4
- package/fesm2022/forty-cdk-search.mjs.map +1 -1
- package/fesm2022/forty-cdk-select.mjs +107 -94
- package/fesm2022/forty-cdk-select.mjs.map +1 -1
- package/fesm2022/forty-cdk-shared.mjs +6 -0
- package/fesm2022/forty-cdk-shared.mjs.map +1 -0
- package/fesm2022/forty-cdk-slider.mjs +26 -28
- package/fesm2022/forty-cdk-slider.mjs.map +1 -1
- package/fesm2022/forty-cdk-stepper.mjs +13 -9
- package/fesm2022/forty-cdk-stepper.mjs.map +1 -1
- package/fesm2022/forty-cdk-switch.mjs +33 -7
- package/fesm2022/forty-cdk-switch.mjs.map +1 -1
- package/fesm2022/forty-cdk-table.mjs +272 -123
- package/fesm2022/forty-cdk-table.mjs.map +1 -1
- package/fesm2022/forty-cdk-tabs.mjs +4 -3
- package/fesm2022/forty-cdk-tabs.mjs.map +1 -1
- package/fesm2022/forty-cdk-time-field.mjs.map +1 -1
- package/fesm2022/forty-cdk-time-picker.mjs +7 -6
- package/fesm2022/forty-cdk-time-picker.mjs.map +1 -1
- package/fesm2022/forty-cdk-toast.mjs +32 -23
- package/fesm2022/forty-cdk-toast.mjs.map +1 -1
- package/fesm2022/forty-cdk-toggle.mjs +7 -5
- package/fesm2022/forty-cdk-toggle.mjs.map +1 -1
- package/fesm2022/forty-cdk-toolbar.mjs +8 -5
- package/fesm2022/forty-cdk-toolbar.mjs.map +1 -1
- package/fesm2022/forty-cdk-tooltip.mjs +4 -4
- package/fesm2022/forty-cdk-tooltip.mjs.map +1 -1
- package/fesm2022/forty-cdk-tree.mjs +149 -3
- package/fesm2022/forty-cdk-tree.mjs.map +1 -1
- package/fesm2022/forty-cdk-virtualization.mjs +28 -15
- package/fesm2022/forty-cdk-virtualization.mjs.map +1 -1
- package/fesm2022/forty-cdk-visually-hidden.mjs +6 -0
- package/fesm2022/forty-cdk-visually-hidden.mjs.map +1 -0
- package/field/README.md +5 -1
- package/fieldset/README.md +5 -1
- package/file-upload/README.md +5 -1
- package/hover-card/README.md +10 -6
- package/input/README.md +2 -2
- package/internationalized-date/README.md +23 -23
- package/listbox/README.md +13 -13
- package/menu/README.md +10 -6
- package/menubar/README.md +24 -6
- package/meter/README.md +5 -1
- package/navigation-menu/README.md +8 -4
- package/number-input/README.md +2 -2
- package/otp-input/README.md +6 -6
- package/package.json +9 -1
- package/pagination/README.md +4 -0
- package/pane-resizer/README.md +29 -27
- package/popover/README.md +10 -6
- package/progress/README.md +5 -1
- package/radio-group/README.md +2 -2
- package/scroll-area/README.md +77 -9
- package/search/README.md +1 -1
- package/select/README.md +24 -25
- package/separator/README.md +1 -1
- package/shared/README.md +99 -0
- package/signal-forms/README.md +2 -2
- package/slider/README.md +22 -23
- package/stepper/README.md +6 -2
- package/switch/README.md +9 -7
- package/table/README.md +45 -956
- package/tabs/README.md +5 -1
- package/time-field/README.md +2 -2
- package/time-picker/README.md +2 -2
- package/time-range-field/README.md +2 -2
- package/toast/README.md +7 -3
- package/toggle/README.md +2 -2
- package/toolbar/README.md +5 -1
- package/tooltip/README.md +8 -4
- package/tree/README.md +5 -1
- package/types/forty-cdk-accordion.d.ts +1 -1
- package/types/forty-cdk-breakpoints.d.ts +1 -1
- package/types/forty-cdk-button.d.ts +1 -1
- package/types/forty-cdk-calendar.d.ts +3 -1
- package/types/forty-cdk-carousel.d.ts +75 -18
- package/types/forty-cdk-checkbox.d.ts +20 -4
- package/types/forty-cdk-combobox.d.ts +160 -72
- package/types/forty-cdk-context-menu.d.ts +2 -3
- package/types/forty-cdk-core.d.ts +637 -1009
- package/types/forty-cdk-date-field.d.ts +0 -1
- package/types/forty-cdk-date-picker.d.ts +7 -9
- package/types/forty-cdk-date-range-field.d.ts +0 -1
- package/types/forty-cdk-dialog.d.ts +4 -3
- package/types/forty-cdk-disclosure.d.ts +1 -0
- package/types/forty-cdk-drag-drop.d.ts +47 -20
- package/types/forty-cdk-drawer.d.ts +88 -55
- package/types/forty-cdk-dropdown-menu.d.ts +3 -3
- package/types/forty-cdk-fieldset.d.ts +0 -1
- package/types/forty-cdk-file-upload.d.ts +1 -0
- package/types/forty-cdk-hover-card.d.ts +5 -6
- package/types/forty-cdk-internationalized-date.d.ts +0 -1
- package/types/forty-cdk-listbox.d.ts +10 -10
- package/types/forty-cdk-menu.d.ts +14 -5
- package/types/forty-cdk-menubar.d.ts +98 -14
- package/types/forty-cdk-navigation-menu.d.ts +10 -10
- package/types/forty-cdk-number-input.d.ts +3 -1
- package/types/forty-cdk-otp-input.d.ts +7 -7
- package/types/forty-cdk-pagination.d.ts +3 -1
- package/types/forty-cdk-pane-resizer.d.ts +13 -6
- package/types/forty-cdk-popover.d.ts +8 -7
- package/types/forty-cdk-radio-group.d.ts +1 -1
- package/types/forty-cdk-scroll-area.d.ts +158 -14
- package/types/forty-cdk-search.d.ts +15 -14
- package/types/forty-cdk-select.d.ts +81 -59
- package/types/forty-cdk-shared.d.ts +1 -0
- package/types/forty-cdk-slider.d.ts +24 -24
- package/types/forty-cdk-stepper.d.ts +8 -5
- package/types/forty-cdk-switch.d.ts +23 -7
- package/types/forty-cdk-table.d.ts +44 -233
- package/types/forty-cdk-tabs.d.ts +1 -1
- package/types/forty-cdk-time-field.d.ts +0 -1
- package/types/forty-cdk-time-picker.d.ts +5 -5
- package/types/forty-cdk-time-range-field.d.ts +0 -1
- package/types/forty-cdk-toast.d.ts +12 -7
- package/types/forty-cdk-toggle.d.ts +2 -1
- package/types/forty-cdk-toolbar.d.ts +5 -3
- package/types/forty-cdk-tooltip.d.ts +5 -6
- package/types/forty-cdk-tree.d.ts +1 -1
- package/types/forty-cdk-visually-hidden.d.ts +1 -0
- package/virtualization/README.md +4 -0
- package/visually-hidden/README.md +78 -0
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ Optional — install only if you use the matching entry point / primitives:
|
|
|
36
36
|
|
|
37
37
|
## Primitives
|
|
38
38
|
|
|
39
|
-
Every primitive ships as its own **secondary entry point** — import `ForDialog` from `forty-cdk/dialog`, `ForAccordion` from `forty-cdk/accordion`, and so on — backed by the shared `forty-cdk/core` entry point. Each lives in its own folder under `projects/forty-cdk/` with its own `README.md` documenting its anatomy, API, keyboard interaction and styling hooks. The `@internationalized/date` adapters live in a dedicated `forty-cdk/internationalized-date` entry point so that optional peer stays truly optional. The main `forty-cdk` barrel is **intentionally empty** (it exports no symbols)
|
|
39
|
+
Every primitive ships as its own **secondary entry point** — import `ForDialog` from `forty-cdk/dialog`, `ForAccordion` from `forty-cdk/accordion`, and so on — backed by the shared `forty-cdk/core` entry point. Each lives in its own folder under `projects/forty-cdk/` with its own `README.md` documenting its anatomy, API, keyboard interaction and styling hooks. The `@internationalized/date` adapters live in a dedicated `forty-cdk/internationalized-date` entry point so that optional peer stays truly optional. The cross-primitive contract types a primitive's public API references — `WritingDirection`, `VetoableEvent`, `DateAdapter`, `FloatingSide`, … — are published by [`forty-cdk/shared`](shared); the main `forty-cdk` barrel is **intentionally empty** (it exports no symbols), so always import primitives from the specific `forty-cdk/<primitive>` entry point. Standalone directives plus `"sideEffects": false` mean your bundle only ever includes the primitives you import.
|
|
40
40
|
|
|
41
41
|
The tables below group the primitives by purpose. The link on each name opens that primitive's README — the canonical reference for which HTML element each directive belongs on, its inputs / outputs, `data-*` attributes and keyboard map.
|
|
42
42
|
|
|
@@ -98,7 +98,7 @@ The tables below group the primitives by purpose. The link on each name opens th
|
|
|
98
98
|
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
|
|
99
99
|
| [Calendar](calendar) | A single-date calendar grid (APG Grid) over a pluggable date adapter, with roving-tabindex navigation. |
|
|
100
100
|
| [Date Field](date-field) | A segmented date (and optional time) input — each part a spinbutton with locale-driven order and clamping. |
|
|
101
|
-
| [Date Picker](date-picker) | A trigger that opens a floating calendar to pick a date, composing Calendar inside a
|
|
101
|
+
| [Date Picker](date-picker) | A trigger that opens a floating calendar to pick a date, composing Calendar inside a dismissible popover. |
|
|
102
102
|
| [Date Range Field](date-range-field) | Two labelled spinbutton endpoints (start / end) sharing locale, granularity and bounds. |
|
|
103
103
|
| [Time Field](time-field) | A segmented time-of-day input with 12 / 24-hour cycles, optional seconds and min / max clamping. |
|
|
104
104
|
| [Time Picker](time-picker) | A trigger that opens a floating listbox of generated time slots over a pluggable date adapter. |
|
package/accordion/README.md
CHANGED
|
@@ -120,7 +120,7 @@ export class DemoFaq {
|
|
|
120
120
|
|
|
121
121
|
## Styling
|
|
122
122
|
|
|
123
|
-
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](
|
|
123
|
+
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../docs/styling.md)). Key your CSS off the reflected `data-*` attributes listed per piece in the [API](#api) section.
|
|
124
124
|
|
|
125
125
|
```css
|
|
126
126
|
.trigger-chevron {
|
|
@@ -131,3 +131,7 @@ forty-cdk ships no styles. Add your own class to each piece — the `for*` selec
|
|
|
131
131
|
transform: rotate(180deg);
|
|
132
132
|
}
|
|
133
133
|
```
|
|
134
|
+
|
|
135
|
+
## Wrapping in a design system
|
|
136
|
+
|
|
137
|
+
Subclassing the root is the supported pattern; the subclass must re-provide `FOR_ACCORDION_CONTEXT` because Angular does not inherit a directive's `providers`, and every projected piece resolves its context through it. See [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md).
|
package/aspect-ratio/README.md
CHANGED
|
@@ -87,7 +87,7 @@ export class DemoAspectRatio {}
|
|
|
87
87
|
|
|
88
88
|
## Styling
|
|
89
89
|
|
|
90
|
-
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](
|
|
90
|
+
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../docs/styling.md)). 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. Style the host through your own class on `[forAspectRatio]`.
|
|
91
91
|
|
|
92
92
|
## Behavior notes
|
|
93
93
|
|
package/avatar/README.md
CHANGED
|
@@ -98,7 +98,7 @@ The directive does not impose a `role`. Pair the avatar with visible name text o
|
|
|
98
98
|
|
|
99
99
|
## Styling
|
|
100
100
|
|
|
101
|
-
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](
|
|
101
|
+
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../docs/styling.md)). Key your CSS off the reflected `data-*` attributes listed per piece in the [API](#api) section.
|
|
102
102
|
|
|
103
103
|
```css
|
|
104
104
|
.avatar-image:not([data-status='loaded']) {
|
|
@@ -115,3 +115,7 @@ forty-cdk ships no styles. Add your own class to each piece — the `for*` selec
|
|
|
115
115
|
- **Multiple images per avatar are not supported.** Each `[forAvatar]` expects exactly one `[forAvatarImage]`. If you need cascading sources (CDN → fallback URL → fallback content), swap `src` on a single image.
|
|
116
116
|
- **`alt` is consumer territory.** Because `<img>` is the host element, the consumer keeps full control of `alt` — set `""` for purely decorative avatars next to a name, or describe the person if the avatar stands alone.
|
|
117
117
|
- **The image stays in the DOM.** Hide it via CSS `[data-status="loading"], [data-status="error"] { display: none }` if your consumer-side styling needs it gone. The fallback uses `@if`, so it only mounts when needed.
|
|
118
|
+
|
|
119
|
+
## Wrapping in a design system
|
|
120
|
+
|
|
121
|
+
Subclassing the root is the supported pattern; the subclass must re-provide `FOR_AVATAR_CONTEXT` because Angular does not inherit a directive's `providers`, and every projected piece resolves its context through it. See [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md).
|
package/button/README.md
CHANGED
|
@@ -81,7 +81,7 @@ Implements the [WAI-ARIA Button pattern](https://www.w3.org/WAI/ARIA/apg/pattern
|
|
|
81
81
|
|
|
82
82
|
## Styling
|
|
83
83
|
|
|
84
|
-
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](
|
|
84
|
+
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../docs/styling.md)). Key your CSS off the reflected `data-*` attributes listed per piece in the [API](#api) section.
|
|
85
85
|
|
|
86
86
|
```css
|
|
87
87
|
[forButton][data-disabled] {
|
package/calendar/README.md
CHANGED
|
@@ -438,7 +438,7 @@ Implements the [WAI-ARIA Grid pattern](https://www.w3.org/WAI/ARIA/apg/patterns/
|
|
|
438
438
|
|
|
439
439
|
## Styling
|
|
440
440
|
|
|
441
|
-
forty-cdk ships no styles. Add your own class to each piece — the `forCalendar*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](
|
|
441
|
+
forty-cdk ships no styles. Add your own class to each piece — the `forCalendar*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../docs/styling.md)). Key your CSS off the reflected `data-*` attributes listed under [Data attributes](#data-attributes).
|
|
442
442
|
|
|
443
443
|
```css
|
|
444
444
|
.calendar-cell {
|
|
@@ -481,3 +481,7 @@ export class DatePage {
|
|
|
481
481
|
}
|
|
482
482
|
}
|
|
483
483
|
```
|
|
484
|
+
|
|
485
|
+
## Wrapping in a design system
|
|
486
|
+
|
|
487
|
+
Subclassing the root is the supported pattern; the subclass must re-provide `FOR_CALENDAR_CONTEXT` because Angular does not inherit a directive's `providers`, and every projected piece resolves its context through it. See [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md).
|
package/carousel/README.md
CHANGED
|
@@ -110,6 +110,11 @@ the defaults with `startLabel` / `stopLabel` inputs:
|
|
|
110
110
|
<button forCarouselRotationControl startLabel="Play slideshow" stopLabel="Pause slideshow"></button>
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
+
Both defaults come from the scope's `rotationStartLabel` / `rotationStopLabel`
|
|
114
|
+
(see [Localizing the default labels](#localizing-the-default-labels)); set either
|
|
115
|
+
input to `null` when the button carries a visible text label and you don't want
|
|
116
|
+
an `aria-label` overriding it.
|
|
117
|
+
|
|
113
118
|
**Programmatic control** via `exportAs`:
|
|
114
119
|
|
|
115
120
|
```html
|
|
@@ -141,17 +146,22 @@ don't use it.
|
|
|
141
146
|
|
|
142
147
|
### CSS contract
|
|
143
148
|
|
|
144
|
-
The directive publishes `--for-carousel-
|
|
145
|
-
|
|
146
|
-
|
|
149
|
+
The directive publishes the live displacement as `--for-carousel-swipe-movement-x`
|
|
150
|
+
(horizontal carousels) or `--for-carousel-swipe-movement-y` (vertical), a raw px
|
|
151
|
+
value on the viewport host; only the primary-axis property is written. Compose it
|
|
152
|
+
with `--for-carousel-offset` on the track transform:
|
|
147
153
|
|
|
148
154
|
```css
|
|
149
155
|
[forCarouselTrack] {
|
|
150
|
-
transform: translateX(
|
|
156
|
+
transform: translateX(
|
|
157
|
+
calc(var(--for-carousel-offset) + var(--for-carousel-swipe-movement-x, 0px))
|
|
158
|
+
);
|
|
151
159
|
transition: transform 300ms ease;
|
|
152
160
|
}
|
|
153
161
|
[forCarousel][data-orientation='vertical'] [forCarouselTrack] {
|
|
154
|
-
transform: translateY(
|
|
162
|
+
transform: translateY(
|
|
163
|
+
calc(var(--for-carousel-offset) + var(--for-carousel-swipe-movement-y, 0px))
|
|
164
|
+
);
|
|
155
165
|
}
|
|
156
166
|
/* Kill the settle transition while the finger is down so the track follows 1:1 */
|
|
157
167
|
[forCarouselViewport][data-dragging] [forCarouselTrack] {
|
|
@@ -164,20 +174,22 @@ transform:
|
|
|
164
174
|
|
|
165
175
|
### RTL
|
|
166
176
|
|
|
167
|
-
`--for-carousel-
|
|
168
|
-
it **without** the `-1` factor the consumer may apply to
|
|
169
|
-
in RTL:
|
|
177
|
+
`--for-carousel-swipe-movement-x` is always the **physical** finger displacement,
|
|
178
|
+
so compose it **without** the `-1` factor the consumer may apply to
|
|
179
|
+
`--for-carousel-offset` in RTL:
|
|
170
180
|
|
|
171
181
|
```css
|
|
172
182
|
[dir='rtl'] [forCarouselTrack] {
|
|
173
|
-
transform: translateX(
|
|
183
|
+
transform: translateX(
|
|
184
|
+
calc(-1 * var(--for-carousel-offset) + var(--for-carousel-swipe-movement-x, 0px))
|
|
185
|
+
);
|
|
174
186
|
}
|
|
175
187
|
```
|
|
176
188
|
|
|
177
189
|
### Reduced motion
|
|
178
190
|
|
|
179
191
|
Under `prefers-reduced-motion: reduce` the directive does **not** publish
|
|
180
|
-
`--for-carousel-
|
|
192
|
+
`--for-carousel-swipe-movement-x` / `-y` (no live track motion). The gesture still snaps
|
|
181
193
|
`activeIndex` on release — only the continuous live offset is suppressed.
|
|
182
194
|
|
|
183
195
|
### Cross-axis / touch
|
|
@@ -189,16 +201,19 @@ captured, so page scrolling on the perpendicular axis is unaffected.
|
|
|
189
201
|
|
|
190
202
|
## Localizing the default labels
|
|
191
203
|
|
|
192
|
-
Each slide's default `aria-label` is the positional `"N of M"` string,
|
|
193
|
-
indicator's is `"Go to slide N"
|
|
194
|
-
`
|
|
195
|
-
|
|
204
|
+
Each slide's default `aria-label` is the positional `"N of M"` string, each
|
|
205
|
+
indicator's is `"Go to slide N"`, and the rotation control's swaps between
|
|
206
|
+
`"Start automatic slide show"` and `"Stop automatic slide show"`. Localize them
|
|
207
|
+
all centrally with `provideForCarouselDefaults` instead of setting `ariaLabel` on
|
|
208
|
+
every slide and indicator:
|
|
196
209
|
|
|
197
210
|
```ts
|
|
198
211
|
providers: [
|
|
199
212
|
provideForCarouselDefaults({
|
|
200
213
|
slideLabel: (position, total) => `Diapositiva ${position} de ${total}`,
|
|
201
214
|
indicatorLabel: (position) => `Ir a la diapositiva ${position}`,
|
|
215
|
+
rotationStartLabel: 'Iniciar la presentación',
|
|
216
|
+
rotationStopLabel: 'Detener la presentación',
|
|
202
217
|
}),
|
|
203
218
|
];
|
|
204
219
|
```
|
|
@@ -206,7 +221,8 @@ providers: [
|
|
|
206
221
|
`position` is the 1-based slide index and `total` is the slide count. Overrides
|
|
207
222
|
merge with the parent scope, so you can localize just the labels and inherit the
|
|
208
223
|
rest of the defaults. A per-element `ariaLabel` on `[forCarouselSlide]` /
|
|
209
|
-
`[forCarouselIndicator]` still takes precedence over the localized default
|
|
224
|
+
`[forCarouselIndicator]` still takes precedence over the localized default, as do
|
|
225
|
+
`[startLabel]` / `[stopLabel]` on `[forCarouselRotationControl]`.
|
|
210
226
|
|
|
211
227
|
## API
|
|
212
228
|
|
|
@@ -229,8 +245,8 @@ All inputs are on `[forCarousel]` unless noted.
|
|
|
229
245
|
| `ariaLabel` (on `[forCarouselIndicators]`) | `string \| null` | Label for the picker group.<br>**Default:** `null` |
|
|
230
246
|
| `ariaLabel` (on `[forCarouselSlide]`) | `string \| null` | Override the positional "N of M" label.<br>**Default:** `null` |
|
|
231
247
|
| `disabled` (on `[forCarouselIndicator]`) | `boolean` | Disable this indicator.<br>**Default:** `false` |
|
|
232
|
-
| `startLabel` (on `[forCarouselRotationControl]`) | `string`
|
|
233
|
-
| `stopLabel` (on `[forCarouselRotationControl]`) | `string`
|
|
248
|
+
| `startLabel` (on `[forCarouselRotationControl]`) | `string \| null` | Accessible name while rotation is stopped.<br>**Default:** scope `rotationStartLabel` (`'Start automatic slide show'`) |
|
|
249
|
+
| `stopLabel` (on `[forCarouselRotationControl]`) | `string \| null` | Accessible name while rotation is playing.<br>**Default:** scope `rotationStopLabel` (`'Stop automatic slide show'`) |
|
|
234
250
|
|
|
235
251
|
Reflected on the `[forCarousel]` host:
|
|
236
252
|
|
|
@@ -298,8 +314,10 @@ Implements the [WAI-ARIA Carousel pattern](https://www.w3.org/WAI/ARIA/apg/patte
|
|
|
298
314
|
accessibility tree and focus order.
|
|
299
315
|
- The indicator group should be labelled (e.g. `ariaLabel="Choose slide to display"`).
|
|
300
316
|
- The current indicator is marked with `aria-current="true"`.
|
|
301
|
-
- Prev/next buttons use native `disabled`
|
|
302
|
-
|
|
317
|
+
- Prev/next buttons never use the native `disabled` attribute. At a boundary without `loop`
|
|
318
|
+
they reflect `aria-disabled="true"` + `data-disabled` and ignore activation, so a keyboard
|
|
319
|
+
user who reaches the last slide keeps focus on the button instead of being dropped to
|
|
320
|
+
`<body>`. Style the boundary state off `[data-disabled]`, never `:disabled`.
|
|
303
321
|
- The viewport carries `aria-live` and `aria-atomic="false"`. While the carousel is actively
|
|
304
322
|
auto-rotating, `aria-live` is `"off"` so advancing slides do not bombard the screen reader.
|
|
305
323
|
When stopped or paused, it is `"polite"` so manual navigation announces. The per-slide
|
|
@@ -308,7 +326,7 @@ Implements the [WAI-ARIA Carousel pattern](https://www.w3.org/WAI/ARIA/apg/patte
|
|
|
308
326
|
|
|
309
327
|
## Styling
|
|
310
328
|
|
|
311
|
-
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](
|
|
329
|
+
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../docs/styling.md)). 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.
|
|
312
330
|
|
|
313
331
|
```css
|
|
314
332
|
[forCarouselViewport] {
|
|
@@ -338,15 +356,16 @@ forty-cdk ships no styles. Add your own class to each piece — the `for*` selec
|
|
|
338
356
|
The following properties are set on the `[forCarousel]` host and cascade to
|
|
339
357
|
children, unless noted otherwise:
|
|
340
358
|
|
|
341
|
-
| Property
|
|
342
|
-
|
|
|
343
|
-
| `--for-carousel-offset`
|
|
344
|
-
| `--for-carousel-active-index`
|
|
345
|
-
| `--for-carousel-slide-count`
|
|
346
|
-
| `--for-carousel-slides-per-view`
|
|
347
|
-
| `--for-carousel-viewport-width`
|
|
348
|
-
| `--for-carousel-viewport-height`
|
|
349
|
-
| `--for-carousel-
|
|
359
|
+
| Property | Host | Value | Notes |
|
|
360
|
+
| --------------------------------- | ----------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
361
|
+
| `--for-carousel-offset` | `[forCarousel]` | e.g. `-100%` | Pure arithmetic from `activeIndex`, `slidesPerView`, `align`. |
|
|
362
|
+
| `--for-carousel-active-index` | `[forCarousel]` | integer | Current `activeIndex`. |
|
|
363
|
+
| `--for-carousel-slide-count` | `[forCarousel]` | integer | Total registered slides. |
|
|
364
|
+
| `--for-carousel-slides-per-view` | `[forCarousel]` | integer | From the `slidesPerView` input. |
|
|
365
|
+
| `--for-carousel-viewport-width` | `[forCarousel]` | e.g. `640px` | Measured via `ResizeObserver`. Absent on the server and before first measurement. |
|
|
366
|
+
| `--for-carousel-viewport-height` | `[forCarousel]` | e.g. `400px` | Same as above, for the block axis. |
|
|
367
|
+
| `--for-carousel-swipe-movement-x` | `[forCarouselViewport]` | e.g. `-128px` | Live px displacement along the primary axis during a swipe. Only the axis matching `orientation` is written; the other is absent, as is both at rest and under `prefers-reduced-motion: reduce`. |
|
|
368
|
+
| `--for-carousel-swipe-movement-y` | `[forCarouselViewport]` | e.g. `-128px` | Live px displacement along the primary axis during a swipe. Only the axis matching `orientation` is written; the other is absent, as is both at rest and under `prefers-reduced-motion: reduce`. |
|
|
350
369
|
|
|
351
370
|
### Autoplay styling hooks
|
|
352
371
|
|
|
@@ -365,6 +384,13 @@ children, unless noted otherwise:
|
|
|
365
384
|
| `data-rotating` | On `[forCarousel]` — actively rotating right now |
|
|
366
385
|
| `data-autoplay` | On `[forCarousel]` — the `autoplay` input is `true` |
|
|
367
386
|
|
|
387
|
+
### Boundary styling hooks
|
|
388
|
+
|
|
389
|
+
| Attribute | When present |
|
|
390
|
+
| --------------- | --------------------------------------------------------- |
|
|
391
|
+
| `data-disabled` | On `[forCarouselPrevious]` — at index 0 without `loop` |
|
|
392
|
+
| `data-disabled` | On `[forCarouselNext]` — at the last index without `loop` |
|
|
393
|
+
|
|
368
394
|
### Drag styling hooks
|
|
369
395
|
|
|
370
396
|
| Attribute | Host | When present |
|
|
@@ -397,3 +423,7 @@ in RTL is the consumer's CSS concern. For example, to flip the translate sign in
|
|
|
397
423
|
```
|
|
398
424
|
|
|
399
425
|
The example CSS above is LTR-only by default.
|
|
426
|
+
|
|
427
|
+
## Wrapping in a design system
|
|
428
|
+
|
|
429
|
+
Subclassing the root is the supported pattern; the subclass must re-provide `FOR_CAROUSEL_CONTEXT` because Angular does not inherit a directive's `providers`, and every projected piece resolves its context through it. See [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md).
|
package/checkbox/README.md
CHANGED
|
@@ -136,23 +136,26 @@ Optional styling slot inside a `[forCheckbox]`. Mirrors the parent's `data-state
|
|
|
136
136
|
|
|
137
137
|
## Keyboard
|
|
138
138
|
|
|
139
|
-
| Key | Action
|
|
140
|
-
| ------- |
|
|
141
|
-
| `Space` | Toggle the checkbox. The only key APG mandates.
|
|
142
|
-
| `Enter` | Also toggles —
|
|
139
|
+
| Key | Action |
|
|
140
|
+
| ------- | ----------------------------------------------------------- |
|
|
141
|
+
| `Space` | Toggle the checkbox. The only key APG mandates. |
|
|
142
|
+
| `Enter` | Also toggles — a documented superset, not an APG violation. |
|
|
143
143
|
|
|
144
144
|
Activating an indeterminate checkbox clears `indeterminate` and toggles `checked` (matches native `<input type="checkbox">`).
|
|
145
145
|
|
|
146
|
+
Both keys work on any host element. On a `<button>` they come from native button behavior; on any other host (`<div>`, `<span>`, or a `hostDirectives` wrapper's own host) the directive adds `tabindex="0"` and synthesizes the same activation, so a styled-from-scratch checkbox is never announced as a checkbox it is impossible to operate. `Space` keydown always blocks page scrolling; the toggle fires on its keyup.
|
|
147
|
+
|
|
146
148
|
## Accessibility
|
|
147
149
|
|
|
148
150
|
Implements the [WAI-ARIA Checkbox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/).
|
|
149
151
|
|
|
150
152
|
- **Provide an accessible name.** Wrap the button in a `<label>`, or set `aria-labelledby` / `aria-label`. Without one, the control is announced as just "checkbox" with no purpose.
|
|
153
|
+
- **Any host element works.** A `<button>` is the recommended host (the directive forces `type="button"` through a host binding, so it never submits a surrounding form even if you write `type="submit"` yourself), but a non-button host gets `tabindex="0"` and synthesized `Space` / `Enter` activation, so it is keyboard-operable too. A non-button host gets no `type` attribute at all — `type` is not valid on a `<div>` / `<span>`, and there is no form submission to protect against.
|
|
151
154
|
- **`role="checkbox"`** with `aria-checked="mixed"` is the canonical tri-state contract. Some legacy screen readers handle "mixed" differently — test with your target SRs.
|
|
152
155
|
|
|
153
156
|
## Styling
|
|
154
157
|
|
|
155
|
-
forty-cdk ships no styles. Add your own class to each piece — the for\* selectors are the behavior API, not a styling contract (see [Styling forty-cdk](
|
|
158
|
+
forty-cdk ships no styles. Add your own class to each piece — the for\* selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../docs/styling.md)). Key your CSS off the reflected data-\* attributes listed per piece in the [API](#api) section.
|
|
156
159
|
|
|
157
160
|
```css
|
|
158
161
|
.checkbox-indicator[data-state='unchecked'] {
|
|
@@ -166,4 +169,4 @@ forty-cdk ships no styles. Add your own class to each piece — the for\* select
|
|
|
166
169
|
|
|
167
170
|
## Wrapping in a design system
|
|
168
171
|
|
|
169
|
-
Both supported wrapper patterns — `hostDirectives` with the exported `FOR_CHECKBOX_HOST_DIRECTIVE_INPUTS` / `FOR_CHECKBOX_HOST_DIRECTIVE_OUTPUTS` name tuples, and subclassing — are documented in [Wrapping form primitives](
|
|
172
|
+
Both supported wrapper patterns — `hostDirectives` with the exported `FOR_CHECKBOX_HOST_DIRECTIVE_INPUTS` / `FOR_CHECKBOX_HOST_DIRECTIVE_OUTPUTS` name tuples, and subclassing — are documented in [Wrapping form primitives](../../../docs/wrapping-form-primitives.md).
|
package/combobox/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
An editable input paired with a filterable listbox popup, supporting single or multi selection with chips.
|
|
4
4
|
|
|
5
|
-
> New to overlays in forty-cdk? [Your first overlay](
|
|
5
|
+
> New to overlays in forty-cdk? [Your first overlay](../../../docs/your-first-overlay.md) walks a Popover from empty markup to styled-and-animated and explains the `@if` / open-state model and the portal → global CSS rule.
|
|
6
6
|
|
|
7
7
|
Headless: `role="combobox"` on the input, `role="listbox"` on the surface, `role="option"` on items, plus `aria-activedescendant` so DOM focus stays in the input. Implements the `FormValueControl<readonly T[]>` interface from `@angular/forms/signals`.
|
|
8
8
|
|
|
@@ -232,7 +232,7 @@ runtime. This is the "editable + list" shape (no `[forComboboxTrigger]` needed).
|
|
|
232
232
|
<input forComboboxInput placeholder="Search…" />
|
|
233
233
|
@if (combobox.open()) {
|
|
234
234
|
<div forComboboxContent>
|
|
235
|
-
<button forComboboxAction (
|
|
235
|
+
<button forComboboxAction (activate)="createNew(query())">Create "{{ query() }}"</button>
|
|
236
236
|
<div forComboboxList>
|
|
237
237
|
@for (it of filtered; track it.id) {
|
|
238
238
|
<div forComboboxOption [value]="it.id" [label]="it.label">{{ it.label }}</div>
|
|
@@ -247,7 +247,7 @@ An action:
|
|
|
247
247
|
|
|
248
248
|
- **never touches `value` / `options()`.** It registers in a collection separate
|
|
249
249
|
from options, so `options()`, `aria-setsize`, and `aria-posinset` are
|
|
250
|
-
unaffected and activation emits `(
|
|
250
|
+
unaffected and activation emits `(activate)` instead of mutating `[(value)]`. The
|
|
251
251
|
consumer decides what happens and whether to close the popup afterwards.
|
|
252
252
|
- **is `role="button"`, not `role="option"`.** Assistive tech announces it as an
|
|
253
253
|
action, not as one of N choices.
|
|
@@ -270,7 +270,7 @@ a bottom-pinned option cannot guarantee under infinite scroll.
|
|
|
270
270
|
Because focus is trapped in the input↔actions ring while open, **Escape** (or an
|
|
271
271
|
outside pointer) is how you leave: Escape from an action closes the popup and
|
|
272
272
|
returns focus to the input (editable anatomy) or the `[forComboboxTrigger]`
|
|
273
|
-
(picker anatomy). Activation is **click / Enter / Space** and routes to `(
|
|
273
|
+
(picker anatomy). Activation is **click / Enter / Space** and routes to `(activate)`
|
|
274
274
|
only. With no action registered, Tab keeps its default "close and let Tab flow on"
|
|
275
275
|
behaviour, so existing comboboxes are unchanged.
|
|
276
276
|
|
|
@@ -283,11 +283,12 @@ outside-focus dismissal checks, exactly like the input.
|
|
|
283
283
|
| Member | Type | Notes |
|
|
284
284
|
| ------------ | -------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
285
285
|
| `[disabled]` | `boolean` | Drops the action out of the focus ring (`tabindex` removed), reflects `aria-disabled`, ignores activation. |
|
|
286
|
-
| `(
|
|
286
|
+
| `(activate)` | `output<void>` | Fired on click / Enter / Space. Never mutates `[(value)]`. |
|
|
287
287
|
|
|
288
|
-
`[forComboboxAction]` host-binds `role="button"`, `type="button"
|
|
289
|
-
|
|
290
|
-
`
|
|
288
|
+
`[forComboboxAction]` host-binds `role="button"`, `type="button"` (on a native
|
|
289
|
+
`<button>` host only — any other element gets no `type`), a primitive-managed
|
|
290
|
+
`tabindex`, `aria-disabled` (when disabled), and reflects `data-highlighted`
|
|
291
|
+
while it holds DOM focus + `data-disabled` when disabled.
|
|
291
292
|
|
|
292
293
|
> **Out of scope (v1):** grouped action clusters / multiple action zones,
|
|
293
294
|
> submenu-style nested actions, and actions that mutate `value` (use a plain
|
|
@@ -380,7 +381,13 @@ Chips are intentionally **out of the Tab cycle** — Tab from outside lands on t
|
|
|
380
381
|
|
|
381
382
|
In RTL the chip cluster lays out right-to-left, so **ArrowRight** moves to the visually-next chip (DOM-previous) and **ArrowLeft** moves to the visually-previous one (DOM-next, hopping to the input at the leftmost visual edge).
|
|
382
383
|
|
|
383
|
-
`[forComboboxChipRemove]` is a click-only target (also out of Tab cycle) with auto-generated `aria-label="Remove <chip label>"`.
|
|
384
|
+
`[forComboboxChipRemove]` is a click-only target (also out of Tab cycle) with auto-generated `aria-label="Remove <chip label>"`. The name is computed per chip, so the piece takes no `[ariaLabel]` input and ignores a static `aria-label` attribute — localize it centrally by overriding the scope's builder:
|
|
385
|
+
|
|
386
|
+
```ts
|
|
387
|
+
@Component({
|
|
388
|
+
providers: [provideForComboboxDefaults({ chipRemoveLabel: (label) => `Quitar ${label}` })],
|
|
389
|
+
})
|
|
390
|
+
```
|
|
384
391
|
|
|
385
392
|
### Multi-mode Backspace heuristic
|
|
386
393
|
|
|
@@ -440,11 +447,11 @@ Real apps usually have richer option models — `{ id, label, ... }` — where t
|
|
|
440
447
|
|
|
441
448
|
Three inputs configure the object behaviour. Defaults make string mode work unchanged:
|
|
442
449
|
|
|
443
|
-
| Input
|
|
444
|
-
|
|
|
445
|
-
| `[
|
|
446
|
-
| `[itemToStringLabel]`
|
|
447
|
-
| `[itemToFormValue]`
|
|
450
|
+
| Input | Default | Purpose |
|
|
451
|
+
| --------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- |
|
|
452
|
+
| `[compareWith]` | `(a, b) => a === b` | How two items compare. Override for object values so selection / removal locate by id (or any stable key). |
|
|
453
|
+
| `[itemToStringLabel]` | `(item) => String(item)` | Render an item as a string. Drives `commitOnSelect` writes into the input and the chip-label fallback. |
|
|
454
|
+
| `[itemToFormValue]` | `(item) => typeof item === 'string' ? item : JSON.stringify(item)` | Serialize an item for the hidden input. Override to emit a per-item id (or any wire format your backend wants). |
|
|
448
455
|
|
|
449
456
|
```html
|
|
450
457
|
@let q = query().toLowerCase(); @let filtered = cities().filter((c) =>
|
|
@@ -455,7 +462,7 @@ c.name.toLowerCase().includes(q));
|
|
|
455
462
|
[(query)]="query"
|
|
456
463
|
[(value)]="value"
|
|
457
464
|
[(open)]="open"
|
|
458
|
-
[
|
|
465
|
+
[compareWith]="byId"
|
|
459
466
|
[itemToStringLabel]="toName"
|
|
460
467
|
name="city"
|
|
461
468
|
[itemToFormValue]="toId"
|
|
@@ -617,7 +624,7 @@ Implements the [WAI-ARIA Combobox pattern](https://www.w3.org/WAI/ARIA/apg/patte
|
|
|
617
624
|
|
|
618
625
|
## Styling
|
|
619
626
|
|
|
620
|
-
forty-cdk ships no styles. Add your own class to each piece — the for\* selectors are the behavior API, not a styling contract (see [Styling forty-cdk](
|
|
627
|
+
forty-cdk ships no styles. Add your own class to each piece — the for\* selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../docs/styling.md)). Key your CSS off the reflected data-\* attributes listed under [Data attributes](#data-attributes).
|
|
621
628
|
|
|
622
629
|
### CSS custom properties
|
|
623
630
|
|
|
@@ -631,7 +638,7 @@ forty-cdk ships no styles. Add your own class to each piece — the for\* select
|
|
|
631
638
|
| `--for-available-height` | px | Space available along the block axis — clamp with `max-height`. |
|
|
632
639
|
| `--for-content-transform-origin` | `<origin>` keywords | `transform-origin` matching the resolved side / align, so a `scale` enter animation pivots from the input. |
|
|
633
640
|
|
|
634
|
-
> `[forComboboxContent]` 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) and the shared positioner properties above. See [Styling floating content](
|
|
641
|
+
> `[forComboboxContent]` 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) and the shared positioner properties above. See [Styling floating content](../../../docs/styling-floating-content.md) for the full positioner-variable list and the portal styling rules.
|
|
635
642
|
|
|
636
643
|
```css
|
|
637
644
|
.option[data-highlighted] {
|
|
@@ -645,4 +652,4 @@ forty-cdk ships no styles. Add your own class to each piece — the for\* select
|
|
|
645
652
|
|
|
646
653
|
## Wrapping in a design system
|
|
647
654
|
|
|
648
|
-
Both supported wrapper patterns — `hostDirectives` with the exported `FOR_COMBOBOX_HOST_DIRECTIVE_INPUTS` / `FOR_COMBOBOX_HOST_DIRECTIVE_OUTPUTS` name tuples, and subclassing — are documented in [Wrapping form primitives](
|
|
655
|
+
Both supported wrapper patterns — `hostDirectives` with the exported `FOR_COMBOBOX_HOST_DIRECTIVE_INPUTS` / `FOR_COMBOBOX_HOST_DIRECTIVE_OUTPUTS` name tuples, and subclassing — are documented in [Wrapping form primitives](../../../docs/wrapping-form-primitives.md).
|
package/context-menu/README.md
CHANGED
|
@@ -4,7 +4,7 @@ A menu opened by right-click or long-press, anchored to the pointer position.
|
|
|
4
4
|
|
|
5
5
|
Opened via the `contextmenu` event (right-click, long-press on touch) and via the keyboard activators `Shift+F10` and the dedicated `ContextMenu` key. The native browser context menu is suppressed. Pointer activations anchor the menu at the cursor; keyboard activations anchor it at the bounding rect of the focused element so screen-reader / keyboard-only users get the menu next to whatever they're working on. Floating-ui's virtual element handles either case — placement, flip, and shift middleware still apply, so the menu is repositioned to stay on-screen automatically.
|
|
6
6
|
|
|
7
|
-
> New to overlays in forty-cdk? [Your first overlay](
|
|
7
|
+
> New to overlays in forty-cdk? [Your first overlay](../../../docs/your-first-overlay.md) walks a Popover from empty markup to styled-and-animated and explains the `@if` / open-state model and the portal → global CSS rule.
|
|
8
8
|
|
|
9
9
|
## Anatomy
|
|
10
10
|
|
|
@@ -113,7 +113,7 @@ Angular resolves `ng-template` DI at the template's **declaration** site, not wh
|
|
|
113
113
|
| `dismissible` | `input<boolean>` | When `false`, Escape and outside interactions don't close.<br>**Default:** `true` |
|
|
114
114
|
| `returnFocus` | `input<boolean>` | When `true`, focus returns to the trigger element on close.<br>**Default:** `true` |
|
|
115
115
|
| `ariaLabel` | `input<string \| null>` | Accessible name reflected as `aria-label` on `[forMenuContent]`. The root's only name hook for a context menu — the right-click region is never used as an `aria-labelledby` target.<br>**Default:** `null` |
|
|
116
|
-
| `escapeKeyDown` | `output<VetoableNativeEvent<KeyboardEvent>>` | Output. Escape pressed while the menu is the topmost
|
|
116
|
+
| `escapeKeyDown` | `output<VetoableNativeEvent<KeyboardEvent>>` | Output. Escape pressed while the menu is the topmost dismissible layer.<br>**Default:** — |
|
|
117
117
|
| `pointerDownOutside` | `output<VetoableNativeEvent<PointerEvent>>` | Output. Pointer-down on a target outside content + trigger.<br>**Default:** — |
|
|
118
118
|
| `focusOutside` | `output<VetoableNativeEvent<FocusEvent>>` | Output. Focus moves outside content + trigger.<br>**Default:** — |
|
|
119
119
|
| `interactOutside` | `output<VetoableNativeEvent<PointerEvent \| FocusEvent>>` | Output. Composite — fires alongside the two above (and shares their veto state).<br>**Default:** — |
|
|
@@ -122,7 +122,7 @@ Angular resolves `ng-template` DI at the template's **declaration** site, not wh
|
|
|
122
122
|
|
|
123
123
|
Same vetoable dismiss API as DropdownMenu. Call `preventDefault()` on the emitted veto to suppress the directive's default action; the original DOM event, when present, is on `.event`.
|
|
124
124
|
|
|
125
|
-
`(autoFocusOnOpen)` / `(autoFocusOnClose)` are output-shape because ContextMenu always routes close transitions through `[(open)]` (via the implicit `openChange` emitter). See [
|
|
125
|
+
`(autoFocusOnOpen)` / `(autoFocusOnClose)` are output-shape because ContextMenu always routes close transitions through `[(open)]` (via the implicit `openChange` emitter). See [Conventions › Auto-focus hook shape](../../../.claude/rules/conventions.md#auto-focus-hook-shape) for why Dialog uses callback-shape inputs instead.
|
|
126
126
|
|
|
127
127
|
### Data attributes
|
|
128
128
|
|
|
@@ -141,9 +141,9 @@ Same vetoable dismiss API as DropdownMenu. Call `preventDefault()` on the emitte
|
|
|
141
141
|
|
|
142
142
|
## Styling
|
|
143
143
|
|
|
144
|
-
forty-cdk ships no styles. Add your own class to each piece — the for\* selectors are the behavior API, not a styling contract (see [Styling forty-cdk](
|
|
144
|
+
forty-cdk ships no styles. Add your own class to each piece — the for\* selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../docs/styling.md)). Key your CSS off the reflected data-\* attributes listed under [Data attributes](#data-attributes).
|
|
145
145
|
|
|
146
|
-
> The menu content (`[forMenuContent]`, from the [`menu/`](../menu/README.md) folder) portals to `document.body`, so it sits outside the trigger's DOM subtree — 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-anchor-width` / `--for-anchor-height`, `--for-available-width` / `--for-available-height`, `--for-content-transform-origin`); see [Styling floating content](
|
|
146
|
+
> The menu content (`[forMenuContent]`, from the [`menu/`](../menu/README.md) folder) portals to `document.body`, so it sits outside the trigger's DOM subtree — 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-anchor-width` / `--for-anchor-height`, `--for-available-width` / `--for-available-height`, `--for-content-transform-origin`); see [Styling floating content](../../../docs/styling-floating-content.md) for the full list and the animation rules.
|
|
147
147
|
|
|
148
148
|
```css
|
|
149
149
|
.context-menu-trigger[data-state='open'] {
|
|
@@ -167,3 +167,7 @@ forty-cdk ships no styles. Add your own class to each piece — the for\* select
|
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
- **Mount equals open.** Same convention as the rest of the library — wrap `[forMenuContent]` in `@if (open())` and use `animate.enter` / `animate.leave` for transitions.
|
|
170
|
+
|
|
171
|
+
## Wrapping in a design system
|
|
172
|
+
|
|
173
|
+
Subclassing the root is the supported pattern; the subclass must re-provide `FOR_MENU_CONTEXT` because Angular does not inherit a directive's `providers`, and every projected piece resolves its context through it. See [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md).
|
package/date-field/README.md
CHANGED
|
@@ -118,17 +118,17 @@ export class DobFormField {
|
|
|
118
118
|
|
|
119
119
|
### `ForDateField`
|
|
120
120
|
|
|
121
|
-
| Property | Type
|
|
122
|
-
| ------------- |
|
|
123
|
-
| `value` | `model<D \| null>`
|
|
124
|
-
| `minDate` | `input<D \| null>`
|
|
125
|
-
| `maxDate` | `input<D \| null>`
|
|
126
|
-
| `granularity` | `input<'day' \| 'hour' \| 'minute' \| 'second'>`
|
|
127
|
-
| `hourCycle` | `input<12 \| 24 \| null>`
|
|
128
|
-
| `locale` | `input<string \| null>`
|
|
129
|
-
| `placeholder` | `input<Partial<Record<
|
|
130
|
-
| `ariaLabel` | `input<string \| null>`
|
|
131
|
-
| `dir` | `input<'ltr' \| 'rtl' \| null>`
|
|
121
|
+
| Property | Type | Description |
|
|
122
|
+
| ------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
123
|
+
| `value` | `model<D \| null>` | Two-way bindable entered date, or `null` while any segment is empty. The `FormValueControl` backing.<br>**Default:** `null` |
|
|
124
|
+
| `minDate` | `input<D \| null>` | Minimum date (inclusive). A composed value below it is clamped up. Named `minDate` — see note below.<br>**Default:** `null` |
|
|
125
|
+
| `maxDate` | `input<D \| null>` | Maximum date (inclusive). A composed value above it is clamped down.<br>**Default:** `null` |
|
|
126
|
+
| `granularity` | `input<'day' \| 'hour' \| 'minute' \| 'second'>` | Date-time precision. `'day'` is date-only; coarser-than-day appends time segments. See below.<br>**Default:** `'day'` |
|
|
127
|
+
| `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` |
|
|
128
|
+
| `locale` | `input<string \| null>` | BCP 47 locale driving segment order, separators, and month name. `null` → runtime locale.<br>**Default:** `null` |
|
|
129
|
+
| `placeholder` | `input<Partial<Record<SegmentType, string>>>` | Per-segment placeholder while empty. Unspecified parts fall back to `dd` / `mm` / `yyyy` / `hh` / `mm` / `ss` / `--`.<br>**Default:** `{}` |
|
|
130
|
+
| `ariaLabel` | `input<string \| null>` | Accessible name for the group. Emits no `aria-label` while `null`.<br>**Default:** `null` |
|
|
131
|
+
| `dir` | `input<'ltr' \| 'rtl' \| null>` | Writing direction. `null` resolves the ambient direction; mirrors ArrowLeft / ArrowRight segment navigation.<br>**Default:** `null` |
|
|
132
132
|
|
|
133
133
|
Plus the shared `FormUiControl` members from `@angular/forms/signals`: `disabled`, `readonly`, `required`, `invalid`, `name`, `errors`, `touched` (bound automatically by `[formField]`).
|
|
134
134
|
|
|
@@ -216,7 +216,7 @@ Composes the [WAI-ARIA Spinbutton pattern](https://www.w3.org/WAI/ARIA/apg/patte
|
|
|
216
216
|
|
|
217
217
|
## Styling
|
|
218
218
|
|
|
219
|
-
forty-cdk ships no styles. Add your own class to each piece — the for\* selectors are the behavior API, not a styling contract (see [Styling forty-cdk](
|
|
219
|
+
forty-cdk ships no styles. Add your own class to each piece — the for\* selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../docs/styling.md)). Key your CSS off the reflected data-\* attributes listed under [Data attributes](#data-attributes).
|
|
220
220
|
|
|
221
221
|
```css
|
|
222
222
|
.date-field-segment[data-placeholder] {
|
|
@@ -233,4 +233,4 @@ forty-cdk ships no styles. Add your own class to each piece — the for\* select
|
|
|
233
233
|
|
|
234
234
|
## Wrapping in a design system
|
|
235
235
|
|
|
236
|
-
Both supported wrapper patterns — `hostDirectives` with the exported `FOR_DATE_FIELD_HOST_DIRECTIVE_INPUTS` / `FOR_DATE_FIELD_HOST_DIRECTIVE_OUTPUTS` name tuples, and subclassing — are documented in [Wrapping form primitives](
|
|
236
|
+
Both supported wrapper patterns — `hostDirectives` with the exported `FOR_DATE_FIELD_HOST_DIRECTIVE_INPUTS` / `FOR_DATE_FIELD_HOST_DIRECTIVE_OUTPUTS` name tuples, and subclassing — are documented in [Wrapping form primitives](../../../docs/wrapping-form-primitives.md).
|
package/date-picker/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# DatePicker
|
|
2
2
|
|
|
3
|
-
A trigger that opens a floating calendar to pick a date, composing ForCalendar inside a
|
|
3
|
+
A trigger that opens a floating calendar to pick a date, composing ForCalendar inside a dismissible popover with min / max bounds and per-date availability.
|
|
4
4
|
|
|
5
5
|
Reinterpreted idiomatically for modern Angular: a focusable trigger that opens a floating surface wrapping a projected [`ForCalendar`](../calendar/README.md).
|
|
6
6
|
|
|
7
|
-
`ForDatePicker` is the root **and** the form value — it implements `FormValueControl<D | null>` from `@angular/forms/signals`, so it auto-wires with `[formField]`. The trigger is the focusable control that carries `name` / `disabled` / `invalid`; selection state flows root → projected calendar via `[(value)]`. The library reuses its existing overlay stack (trigger-anchored Popover positioning,
|
|
7
|
+
`ForDatePicker` is the root **and** the form value — it implements `FormValueControl<D | null>` from `@angular/forms/signals`, so it auto-wires with `[formField]`. The trigger is the focusable control that carries `name` / `disabled` / `invalid`; selection state flows root → projected calendar via `[(value)]`. The library reuses its existing overlay stack (trigger-anchored Popover positioning, dismissible layer, return-focus) rather than re-implementing positioning, dismissal, or focus return — and the modal opt-in routes through the shared modal shell (focus trap + inert background + scroll lock).
|
|
8
8
|
|
|
9
9
|
## Date adapter
|
|
10
10
|
|
|
@@ -318,7 +318,7 @@ readonly booking = form(this.model, (p) => required(p.stay));
|
|
|
318
318
|
- **Native submission.** When `name` is set, two hidden inputs `<name>-start` / `<name>-end` mirror the committed endpoints as ISO `YYYY-MM-DD` for native `<form>` posts.
|
|
319
319
|
- **Bounds naming.** `minDate` / `maxDate` (not `min` / `max`) for the same reason as `ForDatePicker` — and additionally because `FormUiControl.min` / `max` are typed `NonNullable<TValue>` (the range object itself), which is meaningless as a bound.
|
|
320
320
|
|
|
321
|
-
Defaults are configured with `provideForDateRangePickerDefaults` (`sideOffset` / `collisionPadding`), and both wrapper patterns work via the exported `FOR_DATE_RANGE_PICKER_HOST_DIRECTIVE_INPUTS` / `FOR_DATE_RANGE_PICKER_HOST_DIRECTIVE_OUTPUTS` tuples — see [Wrapping form primitives](
|
|
321
|
+
Defaults are configured with `provideForDateRangePickerDefaults` (`sideOffset` / `collisionPadding`), and both wrapper patterns work via the exported `FOR_DATE_RANGE_PICKER_HOST_DIRECTIVE_INPUTS` / `FOR_DATE_RANGE_PICKER_HOST_DIRECTIVE_OUTPUTS` tuples — see [Wrapping form primitives](../../../docs/wrapping-form-primitives.md).
|
|
322
322
|
|
|
323
323
|
## Keyboard
|
|
324
324
|
|
|
@@ -341,9 +341,9 @@ Implements the [WAI-ARIA Date Picker Dialog pattern](https://www.w3.org/WAI/ARIA
|
|
|
341
341
|
|
|
342
342
|
## Styling
|
|
343
343
|
|
|
344
|
-
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](
|
|
344
|
+
forty-cdk ships no styles. Add your own class to each piece — the `for*` selectors are the behavior API, not a styling contract (see [Styling forty-cdk](../../../docs/styling.md)). Key your CSS off the reflected `data-*` attributes listed under [Data attributes](#data-attributes).
|
|
345
345
|
|
|
346
|
-
> `[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](
|
|
346
|
+
> `[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-anchor-width` / `--for-anchor-height`, `--for-available-width` / `--for-available-height`, `--for-content-transform-origin`); that same guide tabulates the full set.
|
|
347
347
|
|
|
348
348
|
```css
|
|
349
349
|
.date-picker-trigger .date-picker-value[data-placeholder] {
|
|
@@ -360,4 +360,4 @@ forty-cdk ships no styles. Add your own class to each piece — the `for*` selec
|
|
|
360
360
|
|
|
361
361
|
## Wrapping in a design system
|
|
362
362
|
|
|
363
|
-
Both supported wrapper patterns — `hostDirectives` with the exported `FOR_DATE_PICKER_HOST_DIRECTIVE_INPUTS` / `FOR_DATE_PICKER_HOST_DIRECTIVE_OUTPUTS` name tuples, and subclassing — are documented in [Wrapping form primitives](
|
|
363
|
+
Both supported wrapper patterns — `hostDirectives` with the exported `FOR_DATE_PICKER_HOST_DIRECTIVE_INPUTS` / `FOR_DATE_PICKER_HOST_DIRECTIVE_OUTPUTS` name tuples, and subclassing — are documented in [Wrapping form primitives](../../../docs/wrapping-form-primitives.md).
|