forty-cdk 0.2.0 → 0.3.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 +122 -0
- package/aspect-ratio/README.md +76 -0
- package/avatar/README.md +100 -0
- package/breadcrumbs/README.md +49 -0
- package/breakpoints/README.md +81 -0
- package/button/README.md +49 -0
- package/calendar/README.md +458 -0
- package/carousel/README.md +358 -0
- package/checkbox/README.md +146 -0
- package/combobox/README.md +535 -0
- package/context-menu/README.md +139 -0
- package/date-field/README.md +184 -0
- package/date-picker/README.md +338 -0
- package/dialog/README.md +388 -0
- package/disclosure/README.md +114 -0
- package/drag-drop/README.md +359 -0
- package/drawer/README.md +560 -0
- package/dropdown-menu/README.md +176 -0
- package/fesm2022/forty-cdk-accordion.mjs +348 -0
- package/fesm2022/forty-cdk-accordion.mjs.map +1 -0
- package/fesm2022/forty-cdk-aspect-ratio.mjs +74 -0
- package/fesm2022/forty-cdk-aspect-ratio.mjs.map +1 -0
- package/fesm2022/forty-cdk-avatar.mjs +308 -0
- package/fesm2022/forty-cdk-avatar.mjs.map +1 -0
- package/fesm2022/forty-cdk-breadcrumbs.mjs +125 -0
- package/fesm2022/forty-cdk-breadcrumbs.mjs.map +1 -0
- package/fesm2022/forty-cdk-breakpoints.mjs +117 -0
- package/fesm2022/forty-cdk-breakpoints.mjs.map +1 -0
- package/fesm2022/forty-cdk-button.mjs +134 -0
- package/fesm2022/forty-cdk-button.mjs.map +1 -0
- package/fesm2022/forty-cdk-calendar.mjs +2034 -0
- package/fesm2022/forty-cdk-calendar.mjs.map +1 -0
- package/fesm2022/forty-cdk-carousel.mjs +968 -0
- package/fesm2022/forty-cdk-carousel.mjs.map +1 -0
- package/fesm2022/forty-cdk-checkbox.mjs +226 -0
- package/fesm2022/forty-cdk-checkbox.mjs.map +1 -0
- package/fesm2022/forty-cdk-combobox.mjs +2596 -0
- package/fesm2022/forty-cdk-combobox.mjs.map +1 -0
- package/fesm2022/forty-cdk-context-menu.mjs +413 -0
- package/fesm2022/forty-cdk-context-menu.mjs.map +1 -0
- package/fesm2022/forty-cdk-core.mjs +9022 -0
- package/fesm2022/forty-cdk-core.mjs.map +1 -0
- package/fesm2022/forty-cdk-date-field.mjs +744 -0
- package/fesm2022/forty-cdk-date-field.mjs.map +1 -0
- package/fesm2022/forty-cdk-date-picker.mjs +1011 -0
- package/fesm2022/forty-cdk-date-picker.mjs.map +1 -0
- package/fesm2022/forty-cdk-dialog.mjs +707 -0
- package/fesm2022/forty-cdk-dialog.mjs.map +1 -0
- package/fesm2022/forty-cdk-disclosure.mjs +190 -0
- package/fesm2022/forty-cdk-disclosure.mjs.map +1 -0
- package/fesm2022/forty-cdk-drag-drop.mjs +1180 -0
- package/fesm2022/forty-cdk-drag-drop.mjs.map +1 -0
- package/fesm2022/forty-cdk-drawer.mjs +1641 -0
- package/fesm2022/forty-cdk-drawer.mjs.map +1 -0
- package/fesm2022/forty-cdk-dropdown-menu.mjs +350 -0
- package/fesm2022/forty-cdk-dropdown-menu.mjs.map +1 -0
- package/fesm2022/forty-cdk-field.mjs +425 -0
- package/fesm2022/forty-cdk-field.mjs.map +1 -0
- package/fesm2022/forty-cdk-fieldset.mjs +164 -0
- package/fesm2022/forty-cdk-fieldset.mjs.map +1 -0
- package/fesm2022/forty-cdk-file-upload.mjs +221 -0
- package/fesm2022/forty-cdk-file-upload.mjs.map +1 -0
- package/fesm2022/forty-cdk-hover-card.mjs +496 -0
- package/fesm2022/forty-cdk-hover-card.mjs.map +1 -0
- package/fesm2022/forty-cdk-input.mjs +274 -0
- package/fesm2022/forty-cdk-input.mjs.map +1 -0
- package/fesm2022/forty-cdk-internationalized-date.mjs +1 -1
- package/fesm2022/forty-cdk-internationalized-date.mjs.map +1 -1
- package/fesm2022/forty-cdk-listbox.mjs +1279 -0
- package/fesm2022/forty-cdk-listbox.mjs.map +1 -0
- package/fesm2022/forty-cdk-menu.mjs +1439 -0
- package/fesm2022/forty-cdk-menu.mjs.map +1 -0
- package/fesm2022/forty-cdk-menubar.mjs +787 -0
- package/fesm2022/forty-cdk-menubar.mjs.map +1 -0
- package/fesm2022/forty-cdk-meter.mjs +211 -0
- package/fesm2022/forty-cdk-meter.mjs.map +1 -0
- package/fesm2022/forty-cdk-navigation-menu.mjs +1145 -0
- package/fesm2022/forty-cdk-navigation-menu.mjs.map +1 -0
- package/fesm2022/forty-cdk-number-input.mjs +559 -0
- package/fesm2022/forty-cdk-number-input.mjs.map +1 -0
- package/fesm2022/forty-cdk-otp-input.mjs +527 -0
- package/fesm2022/forty-cdk-otp-input.mjs.map +1 -0
- package/fesm2022/forty-cdk-pagination.mjs +323 -0
- package/fesm2022/forty-cdk-pagination.mjs.map +1 -0
- package/fesm2022/forty-cdk-pane-resizer.mjs +297 -0
- package/fesm2022/forty-cdk-pane-resizer.mjs.map +1 -0
- package/fesm2022/forty-cdk-popover.mjs +698 -0
- package/fesm2022/forty-cdk-popover.mjs.map +1 -0
- package/fesm2022/forty-cdk-progress.mjs +226 -0
- package/fesm2022/forty-cdk-progress.mjs.map +1 -0
- package/fesm2022/forty-cdk-radio-group.mjs +378 -0
- package/fesm2022/forty-cdk-radio-group.mjs.map +1 -0
- package/fesm2022/forty-cdk-scroll-area.mjs +640 -0
- package/fesm2022/forty-cdk-scroll-area.mjs.map +1 -0
- package/fesm2022/forty-cdk-search.mjs +205 -0
- package/fesm2022/forty-cdk-search.mjs.map +1 -0
- package/fesm2022/forty-cdk-select.mjs +1661 -0
- package/fesm2022/forty-cdk-select.mjs.map +1 -0
- package/fesm2022/forty-cdk-separator.mjs +82 -0
- package/fesm2022/forty-cdk-separator.mjs.map +1 -0
- package/fesm2022/forty-cdk-signal-forms.mjs +97 -0
- package/fesm2022/forty-cdk-signal-forms.mjs.map +1 -0
- package/fesm2022/forty-cdk-slider.mjs +803 -0
- package/fesm2022/forty-cdk-slider.mjs.map +1 -0
- package/fesm2022/forty-cdk-stepper.mjs +886 -0
- package/fesm2022/forty-cdk-stepper.mjs.map +1 -0
- package/fesm2022/forty-cdk-switch.mjs +137 -0
- package/fesm2022/forty-cdk-switch.mjs.map +1 -0
- package/fesm2022/forty-cdk-table.mjs +1518 -0
- package/fesm2022/forty-cdk-table.mjs.map +1 -0
- package/fesm2022/forty-cdk-tabs.mjs +400 -0
- package/fesm2022/forty-cdk-tabs.mjs.map +1 -0
- package/fesm2022/forty-cdk-time-field.mjs +593 -0
- package/fesm2022/forty-cdk-time-field.mjs.map +1 -0
- package/fesm2022/forty-cdk-time-picker.mjs +1013 -0
- package/fesm2022/forty-cdk-time-picker.mjs.map +1 -0
- package/fesm2022/forty-cdk-toast.mjs +1153 -0
- package/fesm2022/forty-cdk-toast.mjs.map +1 -0
- package/fesm2022/forty-cdk-toggle.mjs +516 -0
- package/fesm2022/forty-cdk-toggle.mjs.map +1 -0
- package/fesm2022/forty-cdk-toolbar.mjs +374 -0
- package/fesm2022/forty-cdk-toolbar.mjs.map +1 -0
- package/fesm2022/forty-cdk-tooltip.mjs +672 -0
- package/fesm2022/forty-cdk-tooltip.mjs.map +1 -0
- package/fesm2022/forty-cdk-tree.mjs +2007 -0
- package/fesm2022/forty-cdk-tree.mjs.map +1 -0
- package/fesm2022/forty-cdk-virtualization.mjs +1 -1
- package/fesm2022/forty-cdk-virtualization.mjs.map +1 -1
- package/fesm2022/forty-cdk.mjs +0 -43310
- package/fesm2022/forty-cdk.mjs.map +1 -1
- package/field/README.md +97 -0
- package/fieldset/README.md +86 -0
- package/file-upload/README.md +73 -0
- package/hover-card/README.md +171 -0
- package/input/README.md +156 -0
- package/listbox/README.md +424 -0
- package/menu/README.md +181 -0
- package/menubar/README.md +140 -0
- package/meter/README.md +128 -0
- package/navigation-menu/README.md +253 -0
- package/number-input/README.md +171 -0
- package/otp-input/README.md +198 -0
- package/package.json +213 -1
- package/pagination/README.md +61 -0
- package/pane-resizer/README.md +136 -0
- package/popover/README.md +262 -0
- package/progress/README.md +115 -0
- package/radio-group/README.md +129 -0
- package/scroll-area/README.md +184 -0
- package/search/README.md +42 -0
- package/select/README.md +488 -0
- package/separator/README.md +84 -0
- package/signal-forms/README.md +72 -0
- package/slider/README.md +152 -0
- package/stepper/README.md +292 -0
- package/switch/README.md +116 -0
- package/table/README.md +769 -0
- package/tabs/README.md +130 -0
- package/time-field/README.md +157 -0
- package/time-picker/README.md +172 -0
- package/toast/README.md +398 -0
- package/toggle/README.md +224 -0
- package/toolbar/README.md +109 -0
- package/tooltip/README.md +274 -0
- package/tree/README.md +708 -0
- package/types/forty-cdk-accordion.d.ts +242 -0
- package/types/forty-cdk-aspect-ratio.d.ts +59 -0
- package/types/forty-cdk-avatar.d.ts +133 -0
- package/types/forty-cdk-breadcrumbs.d.ts +92 -0
- package/types/forty-cdk-breakpoints.d.ts +141 -0
- package/types/forty-cdk-button.d.ts +80 -0
- package/types/forty-cdk-calendar.d.ts +914 -0
- package/types/forty-cdk-carousel.d.ts +530 -0
- package/types/forty-cdk-checkbox.d.ts +141 -0
- package/types/forty-cdk-combobox.d.ts +1259 -0
- package/types/forty-cdk-context-menu.d.ts +313 -0
- package/types/forty-cdk-core.d.ts +5774 -0
- package/types/forty-cdk-date-field.d.ts +307 -0
- package/types/forty-cdk-date-picker.d.ts +622 -0
- package/types/forty-cdk-dialog.d.ts +546 -0
- package/types/forty-cdk-disclosure.d.ts +127 -0
- package/types/forty-cdk-drag-drop.d.ts +456 -0
- package/types/forty-cdk-drawer.d.ts +871 -0
- package/types/forty-cdk-dropdown-menu.d.ts +242 -0
- package/types/forty-cdk-field.d.ts +236 -0
- package/types/forty-cdk-fieldset.d.ts +119 -0
- package/types/forty-cdk-file-upload.d.ts +124 -0
- package/types/forty-cdk-hover-card.d.ts +320 -0
- package/types/forty-cdk-input.d.ts +169 -0
- package/types/forty-cdk-internationalized-date.d.ts +1 -1
- package/types/forty-cdk-listbox.d.ts +513 -0
- package/types/forty-cdk-menu.d.ts +629 -0
- package/types/forty-cdk-menubar.d.ts +451 -0
- package/types/forty-cdk-meter.d.ts +122 -0
- package/types/forty-cdk-navigation-menu.d.ts +514 -0
- package/types/forty-cdk-number-input.d.ts +319 -0
- package/types/forty-cdk-otp-input.d.ts +248 -0
- package/types/forty-cdk-pagination.d.ts +214 -0
- package/types/forty-cdk-pane-resizer.d.ts +145 -0
- package/types/forty-cdk-popover.d.ts +509 -0
- package/types/forty-cdk-progress.d.ts +143 -0
- package/types/forty-cdk-radio-group.d.ts +222 -0
- package/types/forty-cdk-scroll-area.d.ts +258 -0
- package/types/forty-cdk-search.d.ts +142 -0
- package/types/forty-cdk-select.d.ts +899 -0
- package/types/forty-cdk-separator.d.ts +59 -0
- package/types/forty-cdk-signal-forms.d.ts +58 -0
- package/types/forty-cdk-slider.d.ts +379 -0
- package/types/forty-cdk-stepper.d.ts +650 -0
- package/types/forty-cdk-switch.d.ts +87 -0
- package/types/forty-cdk-table.d.ts +723 -0
- package/types/forty-cdk-tabs.d.ts +235 -0
- package/types/forty-cdk-time-field.d.ts +307 -0
- package/types/forty-cdk-time-picker.d.ts +578 -0
- package/types/forty-cdk-toast.d.ts +598 -0
- package/types/forty-cdk-toggle.d.ts +310 -0
- package/types/forty-cdk-toolbar.d.ts +217 -0
- package/types/forty-cdk-tooltip.d.ts +436 -0
- package/types/forty-cdk-tree.d.ts +688 -0
- package/types/forty-cdk.d.ts +1 -19743
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { createDefaults, injectMediaQuery } from 'forty-cdk/core';
|
|
2
|
+
import { inject, Injector, runInInjectionContext, computed } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The default breakpoint map, mirroring Tailwind CSS's `sm`–`2xl` scale. Used
|
|
6
|
+
* as the library fallback when no `provideForBreakpoints` is in scope, and the
|
|
7
|
+
* source of the typed breakpoint names when the consumer has not augmented
|
|
8
|
+
* {@link BreakpointRegistry}.
|
|
9
|
+
*/
|
|
10
|
+
const breakpointsTailwind = {
|
|
11
|
+
sm: 640,
|
|
12
|
+
md: 768,
|
|
13
|
+
lg: 1024,
|
|
14
|
+
xl: 1280,
|
|
15
|
+
'2xl': 1536,
|
|
16
|
+
};
|
|
17
|
+
const FALLBACK = {
|
|
18
|
+
breakpoints: breakpointsTailwind,
|
|
19
|
+
};
|
|
20
|
+
const { token, provideDefaults } = createDefaults('FOR_BREAKPOINTS', FALLBACK);
|
|
21
|
+
/**
|
|
22
|
+
* Token holding the resolved breakpoint map for the current injector scope.
|
|
23
|
+
* The library always provides a fully-populated value (the Tailwind fallback
|
|
24
|
+
* at the root, or the map from the nearest `provideForBreakpoints`).
|
|
25
|
+
*/
|
|
26
|
+
const FOR_BREAKPOINTS = token;
|
|
27
|
+
/**
|
|
28
|
+
* Configures the breakpoint map for this injector scope so `injectBreakpoints`
|
|
29
|
+
* can be called with no arguments. Provide it once in your application config:
|
|
30
|
+
*
|
|
31
|
+
* ```ts
|
|
32
|
+
* providers: [
|
|
33
|
+
* provideForBreakpoints({ mobile: 0, tablet: 640, laptop: 1024, desktop: 1280 }),
|
|
34
|
+
* ]
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* Providing it again on a component injector replaces the map for that subtree
|
|
38
|
+
* only (the nearest scope wins; the map is replaced wholesale, never merged
|
|
39
|
+
* key-by-key). Omit it entirely to use {@link breakpointsTailwind}.
|
|
40
|
+
*/
|
|
41
|
+
function provideForBreakpoints(breakpoints) {
|
|
42
|
+
return provideDefaults({ breakpoints });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* A signal-first, zoneless, SSR-safe viewport breakpoint observer. Reads the
|
|
47
|
+
* breakpoint map from the ambient {@link FOR_BREAKPOINTS} token (configured
|
|
48
|
+
* with `provideForBreakpoints`, or the Tailwind fallback), so call sites never
|
|
49
|
+
* repeat the breakpoint set:
|
|
50
|
+
*
|
|
51
|
+
* ```ts
|
|
52
|
+
* private bp = injectBreakpoints();
|
|
53
|
+
* protected isDesktop = this.bp.up('desktop');
|
|
54
|
+
* protected active = this.bp.active;
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* Each query method returns a `Signal<boolean>` backed by a cached
|
|
58
|
+
* `MediaQueryList`. The returned handle captures the calling injection
|
|
59
|
+
* context, so its methods can be invoked lazily from `computed()` or a
|
|
60
|
+
* template — not only during construction. Listeners are torn down with the
|
|
61
|
+
* injector. On the server (or where `matchMedia` is unavailable) every signal
|
|
62
|
+
* reads `false` and `active` reads `null`.
|
|
63
|
+
*
|
|
64
|
+
* Must be called from an injection context.
|
|
65
|
+
*
|
|
66
|
+
* @returns A {@link ForBreakpoints} handle of reactive query methods.
|
|
67
|
+
*/
|
|
68
|
+
function injectBreakpoints() {
|
|
69
|
+
const injector = inject(Injector);
|
|
70
|
+
const map = inject(FOR_BREAKPOINTS).breakpoints;
|
|
71
|
+
const names = Object.keys(map).sort((a, b) => map[a] - map[b]);
|
|
72
|
+
const cache = new Map();
|
|
73
|
+
const observe = (query) => {
|
|
74
|
+
let result = cache.get(query);
|
|
75
|
+
if (result === undefined) {
|
|
76
|
+
result = runInInjectionContext(injector, () => injectMediaQuery(query));
|
|
77
|
+
cache.set(query, result);
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
};
|
|
81
|
+
const thresholdOf = (name) => {
|
|
82
|
+
const value = map[name];
|
|
83
|
+
if (value === undefined) {
|
|
84
|
+
throw new Error(`[forty-cdk/breakpoints] Unknown breakpoint "${name}". Defined breakpoints: ${names.join(', ') || '(none)'}.`);
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
};
|
|
88
|
+
const up = (name) => observe(`(min-width: ${thresholdOf(name)}px)`);
|
|
89
|
+
const down = (name) => observe(`(max-width: ${thresholdOf(name) - 0.02}px)`);
|
|
90
|
+
const between = (min, max) => observe(`(min-width: ${thresholdOf(min)}px) and (max-width: ${thresholdOf(max) - 0.02}px)`);
|
|
91
|
+
const only = (name) => {
|
|
92
|
+
const lower = thresholdOf(name);
|
|
93
|
+
const index = names.indexOf(name);
|
|
94
|
+
const next = index < names.length - 1 ? thresholdOf(names[index + 1]) : null;
|
|
95
|
+
return next === null
|
|
96
|
+
? observe(`(min-width: ${lower}px)`)
|
|
97
|
+
: observe(`(min-width: ${lower}px) and (max-width: ${next - 0.02}px)`);
|
|
98
|
+
};
|
|
99
|
+
const active = computed(() => {
|
|
100
|
+
let current = null;
|
|
101
|
+
for (const name of names) {
|
|
102
|
+
if (observe(`(min-width: ${map[name]}px)`)()) {
|
|
103
|
+
current = name;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return current;
|
|
107
|
+
}, /* @ts-ignore */
|
|
108
|
+
...(ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []));
|
|
109
|
+
return { up, down, between, only, active, matches: (query) => observe(query) };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Generated bundle index. Do not edit.
|
|
114
|
+
*/
|
|
115
|
+
|
|
116
|
+
export { FOR_BREAKPOINTS, breakpointsTailwind, injectBreakpoints, provideForBreakpoints };
|
|
117
|
+
//# sourceMappingURL=forty-cdk-breakpoints.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forty-cdk-breakpoints.mjs","sources":["../../../projects/forty-cdk/breakpoints/src/breakpoints-defaults.ts","../../../projects/forty-cdk/breakpoints/src/breakpoints.ts","../../../projects/forty-cdk/breakpoints/src/forty-cdk-breakpoints.ts"],"sourcesContent":["import { type Provider } from '@angular/core';\n\nimport { createDefaults } from 'forty-cdk/core';\n\n/**\n * A breakpoint map: each named breakpoint paired with its `min-width`\n * threshold in CSS pixels. Names are arbitrary — `injectBreakpoints` derives\n * its query methods (`up`, `down`, `between`, `only`) from whatever keys this\n * map declares, sorted ascending by threshold.\n */\nexport type BreakpointMap = Record<string, number>;\n\n/**\n * The default breakpoint map, mirroring Tailwind CSS's `sm`–`2xl` scale. Used\n * as the library fallback when no `provideForBreakpoints` is in scope, and the\n * source of the typed breakpoint names when the consumer has not augmented\n * {@link BreakpointRegistry}.\n */\nexport const breakpointsTailwind = {\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n '2xl': 1536,\n} as const satisfies BreakpointMap;\n\n/** The breakpoint names from the default Tailwind scale. */\nexport type TailwindBreakpointName = keyof typeof breakpointsTailwind;\n\n/** Resolved shape stored against {@link FOR_BREAKPOINTS}. */\nexport interface ForBreakpointsDefaults {\n /** The active breakpoint map for the current injector scope. */\n breakpoints: BreakpointMap;\n}\n\nconst FALLBACK: ForBreakpointsDefaults = {\n breakpoints: breakpointsTailwind,\n};\n\nconst { token, provideDefaults } = createDefaults<ForBreakpointsDefaults>(\n 'FOR_BREAKPOINTS',\n FALLBACK,\n);\n\n/**\n * Token holding the resolved breakpoint map for the current injector scope.\n * The library always provides a fully-populated value (the Tailwind fallback\n * at the root, or the map from the nearest `provideForBreakpoints`).\n */\nexport const FOR_BREAKPOINTS = token;\n\n/**\n * Configures the breakpoint map for this injector scope so `injectBreakpoints`\n * can be called with no arguments. Provide it once in your application config:\n *\n * ```ts\n * providers: [\n * provideForBreakpoints({ mobile: 0, tablet: 640, laptop: 1024, desktop: 1280 }),\n * ]\n * ```\n *\n * Providing it again on a component injector replaces the map for that subtree\n * only (the nearest scope wins; the map is replaced wholesale, never merged\n * key-by-key). Omit it entirely to use {@link breakpointsTailwind}.\n */\nexport function provideForBreakpoints(breakpoints: BreakpointMap): Provider[] {\n return provideDefaults({ breakpoints });\n}\n","import { Injector, computed, inject, runInInjectionContext, type Signal } from '@angular/core';\n\nimport { injectMediaQuery } from 'forty-cdk/core';\nimport { FOR_BREAKPOINTS, type TailwindBreakpointName } from './breakpoints-defaults';\n\n/**\n * Extension point for typing custom breakpoint names. Augment it via module\n * declaration merging so `injectBreakpoints` autocompletes your own names\n * instead of the default Tailwind scale:\n *\n * ```ts\n * import type { appBreakpoints } from './breakpoints';\n *\n * declare module 'forty-cdk' {\n * interface BreakpointRegistry extends Record<keyof typeof appBreakpoints, true> {}\n * }\n * ```\n *\n * When left empty (no augmentation), {@link BreakpointName} falls back to the\n * keys of {@link breakpointsTailwind}.\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface BreakpointRegistry {}\n\n/**\n * The set of valid breakpoint names. Resolves to the augmented\n * {@link BreakpointRegistry} keys when present, otherwise the Tailwind scale\n * (`'sm' | 'md' | 'lg' | 'xl' | '2xl'`).\n */\nexport type BreakpointName = [keyof BreakpointRegistry] extends [never]\n ? TailwindBreakpointName\n : keyof BreakpointRegistry & string;\n\n/** Reactive handle returned by {@link injectBreakpoints}. */\nexport interface ForBreakpoints<K extends string = BreakpointName> {\n /**\n * Matches the named breakpoint and wider — `(min-width: <threshold>px)`.\n * @param name A breakpoint declared in the active map.\n */\n up(name: K): Signal<boolean>;\n /**\n * Matches narrower than the named breakpoint —\n * `(max-width: <threshold - 0.02>px)`. The 0.02px back-off keeps `up(name)`\n * and `down(name)` from both matching at the exact threshold.\n * @param name A breakpoint declared in the active map.\n */\n down(name: K): Signal<boolean>;\n /**\n * Matches from `min` (inclusive) up to but not including `max`.\n * @param min Lower breakpoint, inclusive.\n * @param max Upper breakpoint, exclusive.\n */\n between(min: K, max: K): Signal<boolean>;\n /**\n * Matches only the named breakpoint's own band — from its threshold up to\n * but not including the next-larger breakpoint (open-ended for the largest).\n * @param name A breakpoint declared in the active map.\n */\n only(name: K): Signal<boolean>;\n /**\n * The largest breakpoint whose `min-width` currently matches, or `null` when\n * the viewport is narrower than the smallest breakpoint (and on the server).\n */\n readonly active: Signal<K | null>;\n /**\n * Escape hatch for an arbitrary media query string (orientation, pointer,\n * `prefers-color-scheme`, …) that the named helpers don't cover.\n * @param query Any valid media query.\n */\n matches(query: string): Signal<boolean>;\n}\n\n/**\n * A signal-first, zoneless, SSR-safe viewport breakpoint observer. Reads the\n * breakpoint map from the ambient {@link FOR_BREAKPOINTS} token (configured\n * with `provideForBreakpoints`, or the Tailwind fallback), so call sites never\n * repeat the breakpoint set:\n *\n * ```ts\n * private bp = injectBreakpoints();\n * protected isDesktop = this.bp.up('desktop');\n * protected active = this.bp.active;\n * ```\n *\n * Each query method returns a `Signal<boolean>` backed by a cached\n * `MediaQueryList`. The returned handle captures the calling injection\n * context, so its methods can be invoked lazily from `computed()` or a\n * template — not only during construction. Listeners are torn down with the\n * injector. On the server (or where `matchMedia` is unavailable) every signal\n * reads `false` and `active` reads `null`.\n *\n * Must be called from an injection context.\n *\n * @returns A {@link ForBreakpoints} handle of reactive query methods.\n */\nexport function injectBreakpoints(): ForBreakpoints {\n const injector = inject(Injector);\n const map = inject(FOR_BREAKPOINTS).breakpoints;\n const names = Object.keys(map).sort((a, b) => map[a] - map[b]);\n const cache = new Map<string, Signal<boolean>>();\n\n const observe = (query: string): Signal<boolean> => {\n let result = cache.get(query);\n if (result === undefined) {\n result = runInInjectionContext(injector, () => injectMediaQuery(query));\n cache.set(query, result);\n }\n return result;\n };\n\n const thresholdOf = (name: string): number => {\n const value = map[name];\n if (value === undefined) {\n throw new Error(\n `[forty-cdk/breakpoints] Unknown breakpoint \"${name}\". Defined breakpoints: ${\n names.join(', ') || '(none)'\n }.`,\n );\n }\n return value;\n };\n\n const up = (name: string): Signal<boolean> => observe(`(min-width: ${thresholdOf(name)}px)`);\n\n const down = (name: string): Signal<boolean> =>\n observe(`(max-width: ${thresholdOf(name) - 0.02}px)`);\n\n const between = (min: string, max: string): Signal<boolean> =>\n observe(`(min-width: ${thresholdOf(min)}px) and (max-width: ${thresholdOf(max) - 0.02}px)`);\n\n const only = (name: string): Signal<boolean> => {\n const lower = thresholdOf(name);\n const index = names.indexOf(name);\n const next = index < names.length - 1 ? thresholdOf(names[index + 1]) : null;\n return next === null\n ? observe(`(min-width: ${lower}px)`)\n : observe(`(min-width: ${lower}px) and (max-width: ${next - 0.02}px)`);\n };\n\n const active = computed<BreakpointName | null>(() => {\n let current: string | null = null;\n for (const name of names) {\n if (observe(`(min-width: ${map[name]}px)`)()) {\n current = name;\n }\n }\n return current as BreakpointName | null;\n });\n\n return { up, down, between, only, active, matches: (query) => observe(query) };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, ElementRef, input, booleanAttribute, output, signal, computed, Directive } from '@angular/core';
|
|
3
|
+
import { injectFocusVisible, injectHovered, injectPressed, createDefaults } from 'forty-cdk/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Headless implementation of the [WAI-ARIA Button pattern](https://www.w3.org/WAI/ARIA/apg/patterns/button/).
|
|
7
|
+
*
|
|
8
|
+
* Works on a native `<button>` host and on any arbitrary host element (e.g. `<div>`, `<span>`).
|
|
9
|
+
* On a native button the platform handles Enter/Space → click synthesis and no `role` or
|
|
10
|
+
* `tabindex` is emitted (the platform owns those). On a non-button host, `role="button"` and
|
|
11
|
+
* `tabindex="0"` are applied, and keydown for Enter/Space synthesizes a click so the directive's
|
|
12
|
+
* single `onClick` path handles all activations.
|
|
13
|
+
*
|
|
14
|
+
* Disabled stays focusable: per the APG a disabled button must remain reachable by assistive
|
|
15
|
+
* technology, so the native `disabled` attribute is never set. Instead `aria-disabled="true"` and
|
|
16
|
+
* `data-disabled=""` are reflected and the activation handler becomes a no-op.
|
|
17
|
+
*
|
|
18
|
+
* Interaction state is reflected as `data-pressed`, `data-hovered`, and `data-focus-visible`
|
|
19
|
+
* (present/absent boolean attributes). There is no `data-state` — this primitive has no
|
|
20
|
+
* open/closed or checked/unchecked logical state.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```html
|
|
24
|
+
* <!-- Native button — platform handles Enter/Space -->
|
|
25
|
+
* <button forButton (activate)="doSomething()">Click me</button>
|
|
26
|
+
*
|
|
27
|
+
* <!-- Non-button host — role, tabindex, and keyboard handling added automatically -->
|
|
28
|
+
* <div forButton (activate)="doSomething()">Click me</div>
|
|
29
|
+
*
|
|
30
|
+
* <!-- Disabled: stays focusable, activation is a no-op -->
|
|
31
|
+
* <button forButton [disabled]="true" (activate)="doSomething()">Disabled</button>
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
class ForButton {
|
|
35
|
+
#host = inject(ElementRef).nativeElement;
|
|
36
|
+
#isNativeButton = this.#host.tagName === 'BUTTON';
|
|
37
|
+
#initialType = this.#host.getAttribute('type');
|
|
38
|
+
/**
|
|
39
|
+
* When `true`, activation (click, Enter, Space) is suppressed and the element
|
|
40
|
+
* reflects `aria-disabled="true"` + `data-disabled=""`. The element remains
|
|
41
|
+
* focusable so assistive technology can announce it.
|
|
42
|
+
*/
|
|
43
|
+
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
44
|
+
/**
|
|
45
|
+
* Emitted once per user activation: a pointer click on any host, or Enter / Space
|
|
46
|
+
* on a non-native-button host (native buttons synthesize click from keyboard). The
|
|
47
|
+
* name `activate` is chosen deliberately to avoid colliding with the native `click`
|
|
48
|
+
* event (which would trip `@angular-eslint/no-output-native` on wrapping consumers).
|
|
49
|
+
*/
|
|
50
|
+
activate = output();
|
|
51
|
+
#focused = signal(false, /* @ts-ignore */
|
|
52
|
+
...(ngDevMode ? [{ debugName: "#focused" }] : /* istanbul ignore next */ []));
|
|
53
|
+
#keyboardModality = injectFocusVisible();
|
|
54
|
+
hovered = injectHovered({ disabled: this.disabled });
|
|
55
|
+
pressed = injectPressed({ disabled: this.disabled });
|
|
56
|
+
focusVisible = computed(() => this.#focused() && this.#keyboardModality(), /* @ts-ignore */
|
|
57
|
+
...(ngDevMode ? [{ debugName: "focusVisible" }] : /* istanbul ignore next */ []));
|
|
58
|
+
resolvedType = computed(() => this.#initialType ?? (this.#isNativeButton ? 'button' : null), /* @ts-ignore */
|
|
59
|
+
...(ngDevMode ? [{ debugName: "resolvedType" }] : /* istanbul ignore next */ []));
|
|
60
|
+
resolvedRole = computed(() => (this.#isNativeButton ? null : 'button'), /* @ts-ignore */
|
|
61
|
+
...(ngDevMode ? [{ debugName: "resolvedRole" }] : /* istanbul ignore next */ []));
|
|
62
|
+
resolvedTabindex = computed(() => (this.#isNativeButton ? null : '0'), /* @ts-ignore */
|
|
63
|
+
...(ngDevMode ? [{ debugName: "resolvedTabindex" }] : /* istanbul ignore next */ []));
|
|
64
|
+
onClick(event) {
|
|
65
|
+
if (this.disabled()) {
|
|
66
|
+
event.preventDefault();
|
|
67
|
+
event.stopImmediatePropagation();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
this.activate.emit();
|
|
71
|
+
}
|
|
72
|
+
onKeydown(event) {
|
|
73
|
+
if (this.#isNativeButton) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (event.key !== 'Enter' && event.key !== ' ') {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (this.disabled()) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
event.preventDefault();
|
|
83
|
+
this.#host.click();
|
|
84
|
+
}
|
|
85
|
+
onFocusIn() {
|
|
86
|
+
this.#focused.set(true);
|
|
87
|
+
}
|
|
88
|
+
onFocusOut() {
|
|
89
|
+
this.#focused.set(false);
|
|
90
|
+
}
|
|
91
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForButton, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
92
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: ForButton, isStandalone: true, selector: "[forButton]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activate: "activate" }, host: { listeners: { "click": "onClick($event)", "keydown": "onKeydown($event)", "focusin": "onFocusIn()", "focusout": "onFocusOut()" }, properties: { "attr.type": "resolvedType()", "attr.role": "resolvedRole()", "attr.tabindex": "resolvedTabindex()", "attr.aria-disabled": "disabled() ? 'true' : null", "attr.data-disabled": "disabled() ? '' : null", "attr.data-pressed": "pressed() ? '' : null", "attr.data-hovered": "hovered() ? '' : null", "attr.data-focus-visible": "focusVisible() ? '' : null" } }, exportAs: ["forButton"], ngImport: i0 });
|
|
93
|
+
}
|
|
94
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForButton, decorators: [{
|
|
95
|
+
type: Directive,
|
|
96
|
+
args: [{
|
|
97
|
+
selector: '[forButton]',
|
|
98
|
+
exportAs: 'forButton',
|
|
99
|
+
host: {
|
|
100
|
+
'[attr.type]': 'resolvedType()',
|
|
101
|
+
'[attr.role]': 'resolvedRole()',
|
|
102
|
+
'[attr.tabindex]': 'resolvedTabindex()',
|
|
103
|
+
'[attr.aria-disabled]': "disabled() ? 'true' : null",
|
|
104
|
+
'[attr.data-disabled]': "disabled() ? '' : null",
|
|
105
|
+
'[attr.data-pressed]': "pressed() ? '' : null",
|
|
106
|
+
'[attr.data-hovered]': "hovered() ? '' : null",
|
|
107
|
+
'[attr.data-focus-visible]': "focusVisible() ? '' : null",
|
|
108
|
+
'(click)': 'onClick($event)',
|
|
109
|
+
'(keydown)': 'onKeydown($event)',
|
|
110
|
+
'(focusin)': 'onFocusIn()',
|
|
111
|
+
'(focusout)': 'onFocusOut()',
|
|
112
|
+
},
|
|
113
|
+
}]
|
|
114
|
+
}], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], activate: [{ type: i0.Output, args: ["activate"] }] } });
|
|
115
|
+
|
|
116
|
+
const FALLBACK = {};
|
|
117
|
+
const { token, provideDefaults } = createDefaults('FOR_BUTTON_DEFAULTS', FALLBACK);
|
|
118
|
+
/** Token holding the resolved button defaults for the current scope. */
|
|
119
|
+
const FOR_BUTTON_DEFAULTS = token;
|
|
120
|
+
/**
|
|
121
|
+
* Configures forty-cdk button defaults for this injector scope. Partial
|
|
122
|
+
* overrides inherit unspecified keys from the parent scope (or library
|
|
123
|
+
* defaults at the root).
|
|
124
|
+
*/
|
|
125
|
+
function provideForButtonDefaults(defaults = {}) {
|
|
126
|
+
return provideDefaults(defaults);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Generated bundle index. Do not edit.
|
|
131
|
+
*/
|
|
132
|
+
|
|
133
|
+
export { FOR_BUTTON_DEFAULTS, ForButton, provideForButtonDefaults };
|
|
134
|
+
//# sourceMappingURL=forty-cdk-button.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forty-cdk-button.mjs","sources":["../../../projects/forty-cdk/button/src/button.ts","../../../projects/forty-cdk/button/src/button-defaults.ts","../../../projects/forty-cdk/button/src/forty-cdk-button.ts"],"sourcesContent":["import {\n Directive,\n ElementRef,\n booleanAttribute,\n computed,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport { injectFocusVisible, injectHovered, injectPressed } from 'forty-cdk/core';\n\n/**\n * Headless implementation of the [WAI-ARIA Button pattern](https://www.w3.org/WAI/ARIA/apg/patterns/button/).\n *\n * Works on a native `<button>` host and on any arbitrary host element (e.g. `<div>`, `<span>`).\n * On a native button the platform handles Enter/Space → click synthesis and no `role` or\n * `tabindex` is emitted (the platform owns those). On a non-button host, `role=\"button\"` and\n * `tabindex=\"0\"` are applied, and keydown for Enter/Space synthesizes a click so the directive's\n * single `onClick` path handles all activations.\n *\n * Disabled stays focusable: per the APG a disabled button must remain reachable by assistive\n * technology, so the native `disabled` attribute is never set. Instead `aria-disabled=\"true\"` and\n * `data-disabled=\"\"` are reflected and the activation handler becomes a no-op.\n *\n * Interaction state is reflected as `data-pressed`, `data-hovered`, and `data-focus-visible`\n * (present/absent boolean attributes). There is no `data-state` — this primitive has no\n * open/closed or checked/unchecked logical state.\n *\n * @example\n * ```html\n * <!-- Native button — platform handles Enter/Space -->\n * <button forButton (activate)=\"doSomething()\">Click me</button>\n *\n * <!-- Non-button host — role, tabindex, and keyboard handling added automatically -->\n * <div forButton (activate)=\"doSomething()\">Click me</div>\n *\n * <!-- Disabled: stays focusable, activation is a no-op -->\n * <button forButton [disabled]=\"true\" (activate)=\"doSomething()\">Disabled</button>\n * ```\n */\n@Directive({\n selector: '[forButton]',\n exportAs: 'forButton',\n host: {\n '[attr.type]': 'resolvedType()',\n '[attr.role]': 'resolvedRole()',\n '[attr.tabindex]': 'resolvedTabindex()',\n '[attr.aria-disabled]': \"disabled() ? 'true' : null\",\n '[attr.data-disabled]': \"disabled() ? '' : null\",\n '[attr.data-pressed]': \"pressed() ? '' : null\",\n '[attr.data-hovered]': \"hovered() ? '' : null\",\n '[attr.data-focus-visible]': \"focusVisible() ? '' : null\",\n '(click)': 'onClick($event)',\n '(keydown)': 'onKeydown($event)',\n '(focusin)': 'onFocusIn()',\n '(focusout)': 'onFocusOut()',\n },\n})\nexport class ForButton {\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n readonly #isNativeButton = this.#host.tagName === 'BUTTON';\n readonly #initialType = this.#host.getAttribute('type');\n\n /**\n * When `true`, activation (click, Enter, Space) is suppressed and the element\n * reflects `aria-disabled=\"true\"` + `data-disabled=\"\"`. The element remains\n * focusable so assistive technology can announce it.\n */\n readonly disabled = input(false, { transform: booleanAttribute });\n\n /**\n * Emitted once per user activation: a pointer click on any host, or Enter / Space\n * on a non-native-button host (native buttons synthesize click from keyboard). The\n * name `activate` is chosen deliberately to avoid colliding with the native `click`\n * event (which would trip `@angular-eslint/no-output-native` on wrapping consumers).\n */\n readonly activate = output<void>();\n\n readonly #focused = signal(false);\n readonly #keyboardModality = injectFocusVisible();\n protected readonly hovered = injectHovered({ disabled: this.disabled });\n protected readonly pressed = injectPressed({ disabled: this.disabled });\n protected readonly focusVisible = computed(() => this.#focused() && this.#keyboardModality());\n\n protected readonly resolvedType = computed(\n () => this.#initialType ?? (this.#isNativeButton ? 'button' : null),\n );\n protected readonly resolvedRole = computed(() => (this.#isNativeButton ? null : 'button'));\n protected readonly resolvedTabindex = computed(() => (this.#isNativeButton ? null : '0'));\n\n protected onClick(event: MouseEvent): void {\n if (this.disabled()) {\n event.preventDefault();\n event.stopImmediatePropagation();\n return;\n }\n this.activate.emit();\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (this.#isNativeButton) {\n return;\n }\n if (event.key !== 'Enter' && event.key !== ' ') {\n return;\n }\n if (this.disabled()) {\n return;\n }\n event.preventDefault();\n this.#host.click();\n }\n\n protected onFocusIn(): void {\n this.#focused.set(true);\n }\n\n protected onFocusOut(): void {\n this.#focused.set(false);\n }\n}\n","import { type Provider } from '@angular/core';\n\nimport { createDefaults } from 'forty-cdk/core';\n\n/**\n * Defaults inherited by descendant buttons in the surrounding injector\n * scope. Configure with `provideForButtonDefaults`. The shape is a stub\n * today — present so future per-scope tuning can land without churning the\n * public surface.\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface ForButtonDefaults {}\n\nconst FALLBACK: ForButtonDefaults = {};\n\nconst { token, provideDefaults } = createDefaults<ForButtonDefaults>(\n 'FOR_BUTTON_DEFAULTS',\n FALLBACK,\n);\n\n/** Token holding the resolved button defaults for the current scope. */\nexport const FOR_BUTTON_DEFAULTS = token;\n\n/**\n * Configures forty-cdk button defaults for this injector scope. Partial\n * overrides inherit unspecified keys from the parent scope (or library\n * defaults at the root).\n */\nexport function provideForButtonDefaults(defaults: Partial<ForButtonDefaults> = {}): Provider[] {\n return provideDefaults(defaults);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|