ngx-kit 7.1.0 → 7.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.
Files changed (73) hide show
  1. package/angle-selector/README.md +34 -34
  2. package/box-shadow/README.md +33 -33
  3. package/color-picker/README.md +52 -52
  4. package/{shared → core}/README.md +117 -117
  5. package/data-table/README.md +120 -120
  6. package/date-picker/README.md +74 -74
  7. package/dialog/README.md +122 -92
  8. package/drag-resize/README.md +53 -55
  9. package/fesm2022/ngx-kit-angle-selector.mjs +9 -26
  10. package/fesm2022/ngx-kit-angle-selector.mjs.map +1 -1
  11. package/fesm2022/ngx-kit-box-shadow.mjs +330 -356
  12. package/fesm2022/ngx-kit-box-shadow.mjs.map +1 -1
  13. package/fesm2022/ngx-kit-color-picker.mjs +132 -272
  14. package/fesm2022/ngx-kit-color-picker.mjs.map +1 -1
  15. package/fesm2022/{ngx-kit-shared.mjs → ngx-kit-core.mjs} +908 -277
  16. package/fesm2022/ngx-kit-core.mjs.map +1 -0
  17. package/fesm2022/ngx-kit-data-table.mjs +1 -1
  18. package/fesm2022/ngx-kit-data-table.mjs.map +1 -1
  19. package/fesm2022/ngx-kit-date-picker.mjs +34 -22
  20. package/fesm2022/ngx-kit-date-picker.mjs.map +1 -1
  21. package/fesm2022/ngx-kit-dialog.mjs +430 -331
  22. package/fesm2022/ngx-kit-dialog.mjs.map +1 -1
  23. package/fesm2022/ngx-kit-drag-resize.mjs +193 -140
  24. package/fesm2022/ngx-kit-drag-resize.mjs.map +1 -1
  25. package/fesm2022/ngx-kit-drawer-menu.mjs +3 -3
  26. package/fesm2022/ngx-kit-drawer-menu.mjs.map +1 -1
  27. package/fesm2022/ngx-kit-dropzone.mjs.map +1 -1
  28. package/fesm2022/ngx-kit-form-field.mjs +9 -3
  29. package/fesm2022/ngx-kit-form-field.mjs.map +1 -1
  30. package/fesm2022/ngx-kit-gallery.mjs +3 -3
  31. package/fesm2022/ngx-kit-gallery.mjs.map +1 -1
  32. package/fesm2022/ngx-kit-gradient-picker.mjs +20 -38
  33. package/fesm2022/ngx-kit-gradient-picker.mjs.map +1 -1
  34. package/fesm2022/ngx-kit-grid-layout.mjs +32 -30
  35. package/fesm2022/ngx-kit-grid-layout.mjs.map +1 -1
  36. package/fesm2022/ngx-kit-image-editor.mjs +3 -3
  37. package/fesm2022/ngx-kit-image-editor.mjs.map +1 -1
  38. package/fesm2022/ngx-kit-menu.mjs +1 -1
  39. package/fesm2022/ngx-kit-menu.mjs.map +1 -1
  40. package/fesm2022/ngx-kit-message.mjs +2 -2
  41. package/fesm2022/ngx-kit-message.mjs.map +1 -1
  42. package/fesm2022/ngx-kit-notify.mjs +1 -1
  43. package/fesm2022/ngx-kit-notify.mjs.map +1 -1
  44. package/fesm2022/ngx-kit-time-picker.mjs +1 -1
  45. package/fesm2022/ngx-kit-time-picker.mjs.map +1 -1
  46. package/fesm2022/ngx-kit-virtual-scroll.mjs +2 -2
  47. package/fesm2022/ngx-kit-virtual-scroll.mjs.map +1 -1
  48. package/gallery/README.md +71 -71
  49. package/gradient-picker/README.md +41 -41
  50. package/grid-layout/README.md +64 -64
  51. package/image-editor/README.md +44 -44
  52. package/menu/README.md +85 -85
  53. package/message/README.md +70 -70
  54. package/notify/README.md +56 -56
  55. package/package.json +5 -9
  56. package/time-picker/README.md +89 -89
  57. package/types/ngx-kit-angle-selector.d.ts +13 -16
  58. package/types/ngx-kit-box-shadow.d.ts +37 -95
  59. package/types/ngx-kit-color-picker.d.ts +61 -58
  60. package/types/{ngx-kit-shared.d.ts → ngx-kit-core.d.ts} +194 -34
  61. package/types/ngx-kit-data-table.d.ts +2 -2
  62. package/types/ngx-kit-date-picker.d.ts +15 -12
  63. package/types/ngx-kit-dialog.d.ts +208 -107
  64. package/types/ngx-kit-drag-resize.d.ts +74 -47
  65. package/types/ngx-kit-form-field.d.ts +26 -23
  66. package/types/ngx-kit-gradient-picker.d.ts +4 -7
  67. package/types/ngx-kit-menu.d.ts +1 -1
  68. package/types/ngx-kit-time-picker.d.ts +1 -1
  69. package/virtual-scroll/README.md +199 -199
  70. package/fesm2022/ngx-kit-shared.mjs.map +0 -1
  71. package/fesm2022/ngx-kit-webflow.mjs +0 -709
  72. package/fesm2022/ngx-kit-webflow.mjs.map +0 -1
  73. package/types/ngx-kit-webflow.d.ts +0 -286
@@ -1,34 +1,34 @@
1
- # ngx-kit/angle-selector
2
-
3
- An angle picker (0 to 360 degrees) with a draggable circular handle — for setting a gradient's direction, a shadow's rotation, or any other angular value.
4
-
5
- ## Install
6
-
7
- ```bash
8
- npm install ngx-kit
9
- ```
10
-
11
- ## Usage
12
-
13
- ```html
14
- <ngx-input-angle [(ngModel)]="angle"></ngx-input-angle>
15
- ```
16
-
17
- Or on a plain input:
18
-
19
- ```html
20
- <input type="number" [ngxInputAngle]="angle" (change)="angle = $event" />
21
- ```
22
-
23
- ## API
24
-
25
- | Input | Type | Default | Description |
26
- | ---------------------- | ----------------------------- | -------- | -------------------------- |
27
- | `theme` | `'light' \| 'dark' \| 'auto'` | `'auto'` | Component theme |
28
- | `change` _(directive)_ | `EventEmitter<number>` | | The new angle (in degrees) |
29
-
30
- The value is always a number between `0` and `360`.
31
-
32
- ## Dark mode and RTL
33
-
34
- Supported automatically. The handle is implemented with RxJS (`switchMap` + `takeUntil` + `takeUntilDestroyed`), so drag listeners are only ever active during an actual drag.
1
+ # ngx-kit/angle-selector
2
+
3
+ An angle picker (0 to 360 degrees) with a draggable circular handle — for setting a gradient's direction, a shadow's rotation, or any other angular value.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install ngx-kit
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```html
14
+ <ngx-input-angle [(ngModel)]="angle"></ngx-input-angle>
15
+ ```
16
+
17
+ Or on a plain input:
18
+
19
+ ```html
20
+ <input type="number" [ngxInputAngle]="angle" (change)="angle = $event" />
21
+ ```
22
+
23
+ ## API
24
+
25
+ | Input | Type | Default | Description |
26
+ | ---------------------- | ----------------------------- | -------- | -------------------------- |
27
+ | `theme` | `'light' \| 'dark' \| 'auto'` | `'auto'` | Component theme |
28
+ | `change` _(directive)_ | `EventEmitter<number>` | | The new angle (in degrees) |
29
+
30
+ The value is always a number between `0` and `360`.
31
+
32
+ ## Dark mode and RTL
33
+
34
+ Supported automatically. The handle is implemented with RxJS (`switchMap` + `takeUntil` + `takeUntilDestroyed`), so drag listeners are only ever active during an actual drag.
@@ -1,33 +1,33 @@
1
- # ngx-kit/box-shadow
2
-
3
- A visual `box-shadow` builder: drag the shadow's offset on a 2D pad with mouse/touch, plus controls for blur, spread, and color.
4
-
5
- ## Install
6
-
7
- ```bash
8
- npm install ngx-kit
9
- ```
10
-
11
- ## Usage
12
-
13
- ```html
14
- <ngx-box-shadow [(ngModel)]="shadowCss"></ngx-box-shadow>
15
- ```
16
-
17
- Or on a plain input:
18
-
19
- ```html
20
- <input type="text" [ngxInputBoxShadow]="shadowCss" (change)="shadowCss = $event" />
21
- ```
22
-
23
- The output is a valid CSS string like `0px 4px 12px 0px rgba(0,0,0,0.25)`.
24
-
25
- ## API
26
-
27
- | Input | Type | Default | Description |
28
- | ---------------------------------- | --------- | ------- | ------------------------------------------------ |
29
- | `setInputBackground` _(directive)_ | `boolean` | `true` | Shows the shadow color as the input's background |
30
-
31
- ## Dark mode and RTL
32
-
33
- Supported automatically. The shadow-offset pad is implemented with Pointer Capture (no global `document` listener needed), so it works smoothly on mobile too.
1
+ # ngx-kit/box-shadow
2
+
3
+ A visual `box-shadow` builder: drag the shadow's offset on a 2D pad with mouse/touch, plus controls for blur, spread, and color.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install ngx-kit
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```html
14
+ <ngx-box-shadow [(ngModel)]="shadowCss"></ngx-box-shadow>
15
+ ```
16
+
17
+ Or on a plain input:
18
+
19
+ ```html
20
+ <input type="text" [ngxInputBoxShadow]="shadowCss" (change)="shadowCss = $event" />
21
+ ```
22
+
23
+ The output is a valid CSS string like `0px 4px 12px 0px rgba(0,0,0,0.25)`.
24
+
25
+ ## API
26
+
27
+ | Input | Type | Default | Description |
28
+ | ---------------------------------- | --------- | ------- | ------------------------------------------------ |
29
+ | `setInputBackground` _(directive)_ | `boolean` | `true` | Shows the shadow color as the input's background |
30
+
31
+ ## Dark mode and RTL
32
+
33
+ Supported automatically. The shadow-offset pad is implemented with Pointer Capture (no global `document` listener needed), so it works smoothly on mobile too.
@@ -1,52 +1,52 @@
1
- # ngx-kit/color-picker
2
-
3
- A complete color picker: a visual picker (saturation/hue), RGB/HSL/CMYK/HEX inputs, an alpha channel, and support for the browser's EyeDropper API to pick a color from anywhere on the screen.
4
-
5
- ## Install
6
-
7
- ```bash
8
- npm install ngx-kit
9
- ```
10
-
11
- ## Usage as a component
12
-
13
- ```html
14
- <ngx-input-color
15
- [(ngModel)]="color"
16
- [outputType]="'HEX'"
17
- [defaultInspector]="ColorInspector.Picker"></ngx-input-color>
18
- ```
19
-
20
- `NgxInputColorComponent` is a full `ControlValueAccessor`, so it works with `ngModel`, `formControl`, and `formControlName`.
21
-
22
- ## Usage as a directive (on a plain input)
23
-
24
- ```html
25
- <input type="text" [ngxInputColor]="color" (change)="color = $event" [outputType]="'RGB'" />
26
- ```
27
-
28
- ## API
29
-
30
- ### `<ngx-input-color>` / `[ngxInputColor]`
31
-
32
- | Input | Type | Default | Description |
33
- | -------------------------------------------- | ------------------------------------------------- | -------- | ----------------------------------------------------- |
34
- | `theme` | `'light' \| 'dark' \| 'auto'` | `'auto'` | `'auto'` follows the browser's `prefers-color-scheme` |
35
- | `simpleMode` | `boolean` | `false` | A more compact UI |
36
- | `outputType` | `'HEX' \| 'RGB' \| 'HSL' \| 'HSV' \| 'CMYK'` | `'HEX'` | Output string format |
37
- | `defaultInspector` | `ColorInspector` (`Picker \| RGB \| HSL \| CMYK`) | `Picker` | Which tab is open by default |
38
- | `useAlphaChannel` | `boolean` | `true` | Show/hide the alpha (transparency) channel |
39
- | `setInputBackgroundColor` _(directive only)_ | `boolean` | `true` | Sets the input's own background to the selected color |
40
- | `change` _(output, directive only)_ | `EventEmitter<string>` | | The new value whenever the color changes |
41
-
42
- ### Input/output formats
43
-
44
- The value can be any of: `#rrggbb`, `#rrggbbaa` (including 3- and 4-character shorthand with alpha), `rgb()`/`rgba()`, `hsl()`/`hsla()`.
45
-
46
- ## EyeDropper
47
-
48
- If the user's browser supports the [EyeDropper API](https://developer.mozilla.org/en-US/docs/Web/API/EyeDropper) (recent Chrome/Edge), the eyedropper button is enabled automatically and the user can pick a color from anywhere on the page (even outside the browser). On browsers without support, the button stays hidden.
49
-
50
- ## Dark mode and RTL
51
-
52
- Supported automatically.
1
+ # ngx-kit/color-picker
2
+
3
+ A complete color picker: a visual picker (saturation/hue), RGB/HSL/CMYK/HEX inputs, an alpha channel, and support for the browser's EyeDropper API to pick a color from anywhere on the screen.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install ngx-kit
9
+ ```
10
+
11
+ ## Usage as a component
12
+
13
+ ```html
14
+ <ngx-input-color
15
+ [(ngModel)]="color"
16
+ [outputType]="'HEX'"
17
+ [defaultInspector]="ColorInspector.Picker"></ngx-input-color>
18
+ ```
19
+
20
+ `NgxInputColorComponent` is a full `ControlValueAccessor`, so it works with `ngModel`, `formControl`, and `formControlName`.
21
+
22
+ ## Usage as a directive (on a plain input)
23
+
24
+ ```html
25
+ <input type="text" [ngxInputColor]="color" (change)="color = $event" [outputType]="'RGB'" />
26
+ ```
27
+
28
+ ## API
29
+
30
+ ### `<ngx-input-color>` / `[ngxInputColor]`
31
+
32
+ | Input | Type | Default | Description |
33
+ | -------------------------------------------- | ------------------------------------------------- | -------- | ----------------------------------------------------- |
34
+ | `theme` | `'light' \| 'dark' \| 'auto'` | `'auto'` | `'auto'` follows the browser's `prefers-color-scheme` |
35
+ | `simpleMode` | `boolean` | `false` | A more compact UI |
36
+ | `outputType` | `'HEX' \| 'RGB' \| 'HSL' \| 'HSV' \| 'CMYK'` | `'HEX'` | Output string format |
37
+ | `defaultInspector` | `ColorInspector` (`Picker \| RGB \| HSL \| CMYK`) | `Picker` | Which tab is open by default |
38
+ | `useAlphaChannel` | `boolean` | `true` | Show/hide the alpha (transparency) channel |
39
+ | `setInputBackgroundColor` _(directive only)_ | `boolean` | `true` | Sets the input's own background to the selected color |
40
+ | `change` _(output, directive only)_ | `EventEmitter<string>` | | The new value whenever the color changes |
41
+
42
+ ### Input/output formats
43
+
44
+ The value can be any of: `#rrggbb`, `#rrggbbaa` (including 3- and 4-character shorthand with alpha), `rgb()`/`rgba()`, `hsl()`/`hsla()`.
45
+
46
+ ## EyeDropper
47
+
48
+ If the user's browser supports the [EyeDropper API](https://developer.mozilla.org/en-US/docs/Web/API/EyeDropper) (recent Chrome/Edge), the eyedropper button is enabled automatically and the user can pick a color from anywhere on the page (even outside the browser). On browsers without support, the button stays hidden.
49
+
50
+ ## Dark mode and RTL
51
+
52
+ Supported automatically.
@@ -1,117 +1,117 @@
1
- # ngx-kit/shared
2
-
3
- Shared utilities and services that the rest of the `ngx-kit` packages are built on: overlay/dialog management, page-direction (RTL/LTR) detection, browser-preference detection, and a few reusable base components (slider, range slider, color-saturation panel).
4
-
5
- You usually won't need this package directly — the other packages depend on it automatically. But if you're building a custom component that should stay consistent with the rest of the library (dark mode, RTL, drag performance), use these same utilities.
6
-
7
- ## Install
8
-
9
- ```bash
10
- npm install ngx-kit
11
- ```
12
-
13
- Import the base styles (which enable dark mode via `color-scheme`) once, app-wide:
14
-
15
- ```scss
16
- // styles.scss
17
- @import 'ngx-kit/styles/all.css';
18
- ```
19
-
20
- ## Services
21
-
22
- ### `OverlayService`
23
-
24
- The engine behind everything floating in the library (menus, dialogs, the color/gradient/angle picker popups). Renders an Angular component inside a native `<dialog>` (`showModal()`) and positions it relative to an anchor.
25
-
26
- ```ts
27
- import { OverlayService } from 'ngx-kit/shared';
28
-
29
- const overlay = inject(OverlayService);
30
- const viewContainerRef = inject(ViewContainerRef);
31
-
32
- const ref = overlay.open({
33
- component: MyComponent,
34
- viewContainerRef,
35
- anchor: buttonElementRef.nativeElement,
36
- placement: 'bottom', // 'top' | 'bottom' | 'auto'
37
- alignment: 'start', // 'start' | 'center' | 'end'
38
- margin: 8,
39
- });
40
-
41
- ref.close(); // OverlayRef.close() takes no argument and has no afterClosed; for that (return value, afterClosed) use ngx-kit/dialog, which is built on top of this service
42
- ```
43
-
44
- What's handled for you automatically:
45
-
46
- - **Smart positioning**: if there isn't enough room below the anchor, it flips above (`placement: 'auto'`).
47
- - **Click-outside dismissal**: detected via the backdrop click, not a global `document` listener.
48
- - **Correct stacking**: multiple simultaneous overlays (e.g. a menu with a submenu) work correctly; Escape only closes the last (topmost) overlay.
49
- - **Focus restoration**: after closing, focus returns to whatever had focus before the overlay opened (accessibility).
50
- - **Automatic RTL**: alignment and placement are computed against the page's actual direction (not a fixed assumption).
51
-
52
- ### `DirectionService`
53
-
54
- A signal (`isRtl(): boolean`) that watches the `<html>` element's `dir` attribute with a `MutationObserver` and updates reactively the moment it changes — so if your app switches languages at runtime, everything stays in sync automatically.
55
-
56
- ```ts
57
- const direction = inject(DirectionService);
58
- direction.isRtl(); // signal<boolean>
59
- ```
60
-
61
- ### `BrowserService`
62
-
63
- ```ts
64
- const browser = inject(BrowserService);
65
- browser.prefersDarkMode; // boolean — read once at service construction time
66
- ```
67
-
68
- ## Utilities
69
-
70
- ### `startDragSession(callbacks)`
71
-
72
- Replaces the problematic `@HostListener('document:mousemove', ...)` pattern, which keeps a listener attached to `document` for the entire lifetime of the component — even when nothing is being dragged (a real performance issue on pages with many simultaneous instances). This function only adds a listener for the duration of an actual drag and removes it itself; `touchmove` is handled with `{passive: false}`, so dragging on mobile doesn't also scroll the page.
73
-
74
- ```ts
75
- import { startDragSession } from 'ngx-kit/shared';
76
-
77
- let stop: (() => void) | undefined;
78
-
79
- function onPointerDown(ev: MouseEvent | TouchEvent) {
80
- stop?.();
81
- stop = startDragSession({
82
- onMove: (ev) => {
83
- /* update position */
84
- },
85
- onEnd: () => {
86
- stop = undefined;
87
- },
88
- });
89
- }
90
- ```
91
-
92
- > If your component is `OnPush` and uses `startDragSession` (instead of `@HostListener`), make sure to call `ChangeDetectorRef.markForCheck()` inside `onMove`/`onEnd` yourself — unlike `@HostListener`, which automatically marks the view dirty, a manual `addEventListener` does not.
93
-
94
- ### `getOffsetPosition(event, element)`
95
-
96
- Returns the pointer/touch position relative to an element's top-left corner; used to implement drag-based components (sliders, color pickers, etc.).
97
-
98
- ### `mergeConfig(base, override)`
99
-
100
- Deep-merges two config objects (for the `provideXxx({...})` pattern used throughout the library).
101
-
102
- ## Base components
103
-
104
- These can be used directly, but they're mostly designed as building blocks for other components (like `color-picker`, `box-shadow`):
105
-
106
- | Component | Selector | Description |
107
- | ---------------------- | ----------------------- | --------------------------------------------------------------------- |
108
- | `SliderComponent` | `slider` | Single-value slider, `ControlValueAccessor`, `[min]`/`[max]`/`[step]` |
109
- | `RangeSliderComponent` | `range-slider` | Range slider (two thumbs) |
110
- | `SaturationComponent` | internal (color-picker) | 2D saturation/lightness picker panel |
111
-
112
- ## Dark mode and RTL
113
-
114
- Both rely directly on `ngx-kit/shared`:
115
-
116
- - **Dark mode**: uses the native CSS `light-dark()` function. For it to work, `color-scheme: light dark` (or `only light`/`only dark` to force it manually) must be set on `:root` — this happens automatically when you import `ngx-kit/styles/all.css`. To force a theme manually (independent of the OS's `prefers-color-scheme`), set `data-ngx-theme="dark"` or `"light"` on `<html>`/`<body>`.
117
- - **RTL**: enabled via `dir="rtl"` on `<html>`; the whole library uses CSS logical properties (`inset-inline-start`, etc.), so no separate styling is needed.
1
+ # ngx-kit/core
2
+
3
+ Shared utilities and services that the rest of the `ngx-kit` packages are built on: overlay/dialog management, page-direction (RTL/LTR) detection, browser-preference detection, and a few reusable base components (slider, range slider, color-saturation panel).
4
+
5
+ You usually won't need this package directly — the other packages depend on it automatically. But if you're building a custom component that should stay consistent with the rest of the library (dark mode, RTL, drag performance), use these same utilities.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install ngx-kit
11
+ ```
12
+
13
+ Import the base styles (which enable dark mode via `color-scheme`) once, app-wide:
14
+
15
+ ```scss
16
+ // styles.scss
17
+ @import 'ngx-kit/styles/all.css';
18
+ ```
19
+
20
+ ## Services
21
+
22
+ ### `OverlayService`
23
+
24
+ The engine behind everything floating in the library (menus, dialogs, the color/gradient/angle picker popups). Renders an Angular component inside a native `<dialog>` (`showModal()`) and positions it relative to an anchor.
25
+
26
+ ```ts
27
+ import { OverlayService } from 'ngx-kit/core';
28
+
29
+ const overlay = inject(OverlayService);
30
+ const viewContainerRef = inject(ViewContainerRef);
31
+
32
+ const ref = overlay.open({
33
+ component: MyComponent,
34
+ viewContainerRef,
35
+ anchor: buttonElementRef.nativeElement,
36
+ placement: 'bottom', // 'top' | 'bottom' | 'auto'
37
+ alignment: 'start', // 'start' | 'center' | 'end'
38
+ margin: 8,
39
+ });
40
+
41
+ ref.close(); // OverlayRef.close() takes no argument and has no afterClosed; for that (return value, afterClosed) use ngx-kit/dialog, which is built on top of this service
42
+ ```
43
+
44
+ What's handled for you automatically:
45
+
46
+ - **Smart positioning**: if there isn't enough room below the anchor, it flips above (`placement: 'auto'`).
47
+ - **Click-outside dismissal**: detected via the backdrop click, not a global `document` listener.
48
+ - **Correct stacking**: multiple simultaneous overlays (e.g. a menu with a submenu) work correctly; Escape only closes the last (topmost) overlay.
49
+ - **Focus restoration**: after closing, focus returns to whatever had focus before the overlay opened (accessibility).
50
+ - **Automatic RTL**: alignment and placement are computed against the page's actual direction (not a fixed assumption).
51
+
52
+ ### `DirectionService`
53
+
54
+ A signal (`isRtl(): boolean`) that watches the `<html>` element's `dir` attribute with a `MutationObserver` and updates reactively the moment it changes — so if your app switches languages at runtime, everything stays in sync automatically.
55
+
56
+ ```ts
57
+ const direction = inject(DirectionService);
58
+ direction.isRtl(); // signal<boolean>
59
+ ```
60
+
61
+ ### `BrowserService`
62
+
63
+ ```ts
64
+ const browser = inject(BrowserService);
65
+ browser.prefersDarkMode; // boolean — read once at service construction time
66
+ ```
67
+
68
+ ## Utilities
69
+
70
+ ### `startDragSession(callbacks)`
71
+
72
+ Replaces the problematic `@HostListener('document:mousemove', ...)` pattern, which keeps a listener attached to `document` for the entire lifetime of the component — even when nothing is being dragged (a real performance issue on pages with many simultaneous instances). This function only adds a listener for the duration of an actual drag and removes it itself; `touchmove` is handled with `{passive: false}`, so dragging on mobile doesn't also scroll the page.
73
+
74
+ ```ts
75
+ import { startDragSession } from 'ngx-kit/core';
76
+
77
+ let stop: (() => void) | undefined;
78
+
79
+ function onPointerDown(ev: MouseEvent | TouchEvent) {
80
+ stop?.();
81
+ stop = startDragSession({
82
+ onMove: (ev) => {
83
+ /* update position */
84
+ },
85
+ onEnd: () => {
86
+ stop = undefined;
87
+ },
88
+ });
89
+ }
90
+ ```
91
+
92
+ > If your component is `OnPush` and uses `startDragSession` (instead of `@HostListener`), make sure to call `ChangeDetectorRef.markForCheck()` inside `onMove`/`onEnd` yourself — unlike `@HostListener`, which automatically marks the view dirty, a manual `addEventListener` does not.
93
+
94
+ ### `getOffsetPosition(event, element)`
95
+
96
+ Returns the pointer/touch position relative to an element's top-left corner; used to implement drag-based components (sliders, color pickers, etc.).
97
+
98
+ ### `mergeConfig(base, override)`
99
+
100
+ Deep-merges two config objects (for the `provideXxx({...})` pattern used throughout the library).
101
+
102
+ ## Base components
103
+
104
+ These can be used directly, but they're mostly designed as building blocks for other components (like `color-picker`, `box-shadow`):
105
+
106
+ | Component | Selector | Description |
107
+ | ---------------------- | ----------------------- | --------------------------------------------------------------------- |
108
+ | `SliderComponent` | `slider` | Single-value slider, `ControlValueAccessor`, `[min]`/`[max]`/`[step]` |
109
+ | `RangeSliderComponent` | `range-slider` | Range slider (two thumbs) |
110
+ | `SaturationComponent` | internal (color-picker) | 2D saturation/lightness picker panel |
111
+
112
+ ## Dark mode and RTL
113
+
114
+ Both rely directly on `ngx-kit/core`:
115
+
116
+ - **Dark mode**: uses the native CSS `light-dark()` function. For it to work, `color-scheme: light dark` (or `only light`/`only dark` to force it manually) must be set on `:root` — this happens automatically when you import `ngx-kit/styles/all.css`. To force a theme manually (independent of the OS's `prefers-color-scheme`), set `data-ngx-theme="dark"` or `"light"` on `<html>`/`<body>`.
117
+ - **RTL**: enabled via `dir="rtl"` on `<html>`; the whole library uses CSS logical properties (`inset-inline-start`, etc.), so no separate styling is needed.