@ojiepermana/angular-component 22.0.27
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 +82 -0
- package/accordion/README.md +193 -0
- package/alert/README.md +180 -0
- package/alert-dialog/README.md +239 -0
- package/aspect-ratio/README.md +112 -0
- package/avatar/README.md +176 -0
- package/badge/README.md +133 -0
- package/breadcrumb/README.md +216 -0
- package/button/README.md +139 -0
- package/button-group/README.md +208 -0
- package/calendar/README.md +135 -0
- package/card/README.md +220 -0
- package/carousel/README.md +276 -0
- package/checkbox/README.md +149 -0
- package/collapsible/README.md +195 -0
- package/combobox/README.md +198 -0
- package/command/README.md +275 -0
- package/composer/README.md +235 -0
- package/context-menu/README.md +267 -0
- package/date-picker/README.md +179 -0
- package/dialog/README.md +235 -0
- package/drawer/README.md +145 -0
- package/dropdown-menu/README.md +311 -0
- package/editor/README.md +136 -0
- package/empty/README.md +183 -0
- package/fesm2022/ojiepermana-angular-component-accordion.mjs +186 -0
- package/fesm2022/ojiepermana-angular-component-accordion.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-alert-dialog.mjs +276 -0
- package/fesm2022/ojiepermana-angular-component-alert-dialog.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-alert.mjs +99 -0
- package/fesm2022/ojiepermana-angular-component-alert.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-aspect-ratio.mjs +37 -0
- package/fesm2022/ojiepermana-angular-component-aspect-ratio.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-avatar.mjs +139 -0
- package/fesm2022/ojiepermana-angular-component-avatar.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-badge.mjs +50 -0
- package/fesm2022/ojiepermana-angular-component-badge.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-breadcrumb.mjs +200 -0
- package/fesm2022/ojiepermana-angular-component-breadcrumb.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-button-group.mjs +103 -0
- package/fesm2022/ojiepermana-angular-component-button-group.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-button.mjs +68 -0
- package/fesm2022/ojiepermana-angular-component-button.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-calendar.mjs +103 -0
- package/fesm2022/ojiepermana-angular-component-calendar.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-card.mjs +152 -0
- package/fesm2022/ojiepermana-angular-component-card.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-carousel.mjs +334 -0
- package/fesm2022/ojiepermana-angular-component-carousel.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-checkbox.mjs +165 -0
- package/fesm2022/ojiepermana-angular-component-checkbox.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-collapsible.mjs +121 -0
- package/fesm2022/ojiepermana-angular-component-collapsible.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-combobox.mjs +274 -0
- package/fesm2022/ojiepermana-angular-component-combobox.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-command.mjs +297 -0
- package/fesm2022/ojiepermana-angular-component-command.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-composer.mjs +352 -0
- package/fesm2022/ojiepermana-angular-component-composer.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-context-menu.mjs +108 -0
- package/fesm2022/ojiepermana-angular-component-context-menu.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-date-picker.mjs +186 -0
- package/fesm2022/ojiepermana-angular-component-date-picker.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-dialog.mjs +283 -0
- package/fesm2022/ojiepermana-angular-component-dialog.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-drawer.mjs +6 -0
- package/fesm2022/ojiepermana-angular-component-drawer.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-dropdown-menu.mjs +494 -0
- package/fesm2022/ojiepermana-angular-component-dropdown-menu.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-editor.mjs +680 -0
- package/fesm2022/ojiepermana-angular-component-editor.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-empty.mjs +145 -0
- package/fesm2022/ojiepermana-angular-component-empty.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-form.mjs +364 -0
- package/fesm2022/ojiepermana-angular-component-form.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-hover-card.mjs +275 -0
- package/fesm2022/ojiepermana-angular-component-hover-card.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-icon.mjs +86 -0
- package/fesm2022/ojiepermana-angular-component-icon.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-input-group.mjs +179 -0
- package/fesm2022/ojiepermana-angular-component-input-group.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-input-otp.mjs +517 -0
- package/fesm2022/ojiepermana-angular-component-input-otp.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-input.mjs +45 -0
- package/fesm2022/ojiepermana-angular-component-input.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-item.mjs +264 -0
- package/fesm2022/ojiepermana-angular-component-item.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-kanban.mjs +314 -0
- package/fesm2022/ojiepermana-angular-component-kanban.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-kbd.mjs +55 -0
- package/fesm2022/ojiepermana-angular-component-kbd.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-label.mjs +33 -0
- package/fesm2022/ojiepermana-angular-component-label.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-menubar.mjs +311 -0
- package/fesm2022/ojiepermana-angular-component-menubar.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-native-select.mjs +67 -0
- package/fesm2022/ojiepermana-angular-component-native-select.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-navigation-menu.mjs +408 -0
- package/fesm2022/ojiepermana-angular-component-navigation-menu.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-pagination.mjs +226 -0
- package/fesm2022/ojiepermana-angular-component-pagination.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-pillbox.mjs +810 -0
- package/fesm2022/ojiepermana-angular-component-pillbox.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-popover.mjs +145 -0
- package/fesm2022/ojiepermana-angular-component-popover.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-progress.mjs +60 -0
- package/fesm2022/ojiepermana-angular-component-progress.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-radio.mjs +173 -0
- package/fesm2022/ojiepermana-angular-component-radio.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-resizable.mjs +478 -0
- package/fesm2022/ojiepermana-angular-component-resizable.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-scroll-area.mjs +54 -0
- package/fesm2022/ojiepermana-angular-component-scroll-area.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-select.mjs +297 -0
- package/fesm2022/ojiepermana-angular-component-select.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-separator.mjs +37 -0
- package/fesm2022/ojiepermana-angular-component-separator.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-sheet.mjs +297 -0
- package/fesm2022/ojiepermana-angular-component-sheet.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-skeleton.mjs +31 -0
- package/fesm2022/ojiepermana-angular-component-skeleton.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-slider.mjs +423 -0
- package/fesm2022/ojiepermana-angular-component-slider.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-spinner.mjs +60 -0
- package/fesm2022/ojiepermana-angular-component-spinner.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-switch.mjs +140 -0
- package/fesm2022/ojiepermana-angular-component-switch.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-table.mjs +155 -0
- package/fesm2022/ojiepermana-angular-component-table.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-tabs.mjs +271 -0
- package/fesm2022/ojiepermana-angular-component-tabs.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-textarea.mjs +39 -0
- package/fesm2022/ojiepermana-angular-component-textarea.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-timeline.mjs +237 -0
- package/fesm2022/ojiepermana-angular-component-timeline.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-toast.mjs +161 -0
- package/fesm2022/ojiepermana-angular-component-toast.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-toggle-group.mjs +289 -0
- package/fesm2022/ojiepermana-angular-component-toggle-group.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-toggle.mjs +82 -0
- package/fesm2022/ojiepermana-angular-component-toggle.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-tooltip.mjs +410 -0
- package/fesm2022/ojiepermana-angular-component-tooltip.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component-utils.mjs +81 -0
- package/fesm2022/ojiepermana-angular-component-utils.mjs.map +1 -0
- package/fesm2022/ojiepermana-angular-component.mjs +11 -0
- package/fesm2022/ojiepermana-angular-component.mjs.map +1 -0
- package/form/README.md +210 -0
- package/hover-card/README.md +142 -0
- package/icon/README.md +25 -0
- package/input/README.md +159 -0
- package/input-group/README.md +237 -0
- package/input-otp/README.md +278 -0
- package/item/README.md +247 -0
- package/kanban/README.md +81 -0
- package/kbd/README.md +139 -0
- package/label/README.md +135 -0
- package/menubar/README.md +269 -0
- package/native-select/README.md +176 -0
- package/navigation-menu/README.md +160 -0
- package/package.json +291 -0
- package/pagination/README.md +144 -0
- package/pillbox/README.md +67 -0
- package/popover/README.md +43 -0
- package/progress/README.md +160 -0
- package/radio/README.md +209 -0
- package/resizable/README.md +168 -0
- package/scroll-area/README.md +143 -0
- package/select/README.md +174 -0
- package/separator/README.md +170 -0
- package/sheet/README.md +183 -0
- package/skeleton/README.md +158 -0
- package/slider/README.md +207 -0
- package/spinner/README.md +160 -0
- package/switch/README.md +166 -0
- package/table/README.md +291 -0
- package/tabs/README.md +214 -0
- package/textarea/README.md +153 -0
- package/timeline/README.md +94 -0
- package/toast/README.md +321 -0
- package/toggle/README.md +131 -0
- package/toggle-group/README.md +206 -0
- package/tooltip/README.md +207 -0
- package/types/ojiepermana-angular-component-accordion.d.ts +51 -0
- package/types/ojiepermana-angular-component-alert-dialog.d.ts +93 -0
- package/types/ojiepermana-angular-component-alert.d.ts +37 -0
- package/types/ojiepermana-angular-component-aspect-ratio.d.ts +12 -0
- package/types/ojiepermana-angular-component-avatar.d.ts +51 -0
- package/types/ojiepermana-angular-component-badge.d.ts +19 -0
- package/types/ojiepermana-angular-component-breadcrumb.d.ts +46 -0
- package/types/ojiepermana-angular-component-button-group.d.ts +26 -0
- package/types/ojiepermana-angular-component-button.d.ts +22 -0
- package/types/ojiepermana-angular-component-calendar.d.ts +39 -0
- package/types/ojiepermana-angular-component-card.d.ts +60 -0
- package/types/ojiepermana-angular-component-carousel.d.ts +86 -0
- package/types/ojiepermana-angular-component-checkbox.d.ts +42 -0
- package/types/ojiepermana-angular-component-collapsible.d.ts +42 -0
- package/types/ojiepermana-angular-component-combobox.d.ts +53 -0
- package/types/ojiepermana-angular-component-command.d.ts +102 -0
- package/types/ojiepermana-angular-component-composer.d.ts +90 -0
- package/types/ojiepermana-angular-component-context-menu.d.ts +36 -0
- package/types/ojiepermana-angular-component-date-picker.d.ts +48 -0
- package/types/ojiepermana-angular-component-dialog.d.ts +87 -0
- package/types/ojiepermana-angular-component-drawer.d.ts +1 -0
- package/types/ojiepermana-angular-component-dropdown-menu.d.ts +140 -0
- package/types/ojiepermana-angular-component-editor.d.ts +126 -0
- package/types/ojiepermana-angular-component-empty.d.ts +50 -0
- package/types/ojiepermana-angular-component-form.d.ts +140 -0
- package/types/ojiepermana-angular-component-hover-card.d.ts +75 -0
- package/types/ojiepermana-angular-component-icon.d.ts +31 -0
- package/types/ojiepermana-angular-component-input-group.d.ts +51 -0
- package/types/ojiepermana-angular-component-input-otp.d.ts +142 -0
- package/types/ojiepermana-angular-component-input.d.ts +16 -0
- package/types/ojiepermana-angular-component-item.d.ts +88 -0
- package/types/ojiepermana-angular-component-kanban.d.ts +70 -0
- package/types/ojiepermana-angular-component-kbd.d.ts +16 -0
- package/types/ojiepermana-angular-component-label.d.ts +11 -0
- package/types/ojiepermana-angular-component-menubar.d.ts +69 -0
- package/types/ojiepermana-angular-component-native-select.d.ts +26 -0
- package/types/ojiepermana-angular-component-navigation-menu.d.ts +98 -0
- package/types/ojiepermana-angular-component-pagination.d.ts +33 -0
- package/types/ojiepermana-angular-component-pillbox.d.ts +156 -0
- package/types/ojiepermana-angular-component-popover.d.ts +50 -0
- package/types/ojiepermana-angular-component-progress.d.ts +17 -0
- package/types/ojiepermana-angular-component-radio.d.ts +57 -0
- package/types/ojiepermana-angular-component-resizable.d.ts +99 -0
- package/types/ojiepermana-angular-component-scroll-area.d.ts +19 -0
- package/types/ojiepermana-angular-component-select.d.ts +56 -0
- package/types/ojiepermana-angular-component-separator.d.ts +14 -0
- package/types/ojiepermana-angular-component-sheet.d.ts +78 -0
- package/types/ojiepermana-angular-component-skeleton.d.ts +10 -0
- package/types/ojiepermana-angular-component-slider.d.ts +74 -0
- package/types/ojiepermana-angular-component-spinner.d.ts +13 -0
- package/types/ojiepermana-angular-component-switch.d.ts +44 -0
- package/types/ojiepermana-angular-component-table.d.ts +52 -0
- package/types/ojiepermana-angular-component-tabs.d.ts +92 -0
- package/types/ojiepermana-angular-component-textarea.d.ts +12 -0
- package/types/ojiepermana-angular-component-timeline.d.ts +63 -0
- package/types/ojiepermana-angular-component-toast.d.ts +51 -0
- package/types/ojiepermana-angular-component-toggle-group.d.ts +89 -0
- package/types/ojiepermana-angular-component-toggle.d.ts +25 -0
- package/types/ojiepermana-angular-component-tooltip.d.ts +101 -0
- package/types/ojiepermana-angular-component-utils.d.ts +30 -0
- package/types/ojiepermana-angular-component.d.ts +2 -0
package/slider/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Slider
|
|
2
|
+
|
|
3
|
+
Selects one or more numeric values from a bounded range.
|
|
4
|
+
|
|
5
|
+
This entrypoint now exports two related Angular surfaces:
|
|
6
|
+
|
|
7
|
+
- `Slider` via `SliderRootComponent` for shadcn-style single-thumb, range,
|
|
8
|
+
multiple-thumb, vertical, disabled, and RTL examples.
|
|
9
|
+
- `input[Slider]` via `SliderInputDirective` for browser-native range inputs
|
|
10
|
+
when labels and forms should stay on the native path.
|
|
11
|
+
|
|
12
|
+
## Import
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { SliderInputDirective, SliderRootComponent } from '@ojiepermana/angular-component/slider';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Structure
|
|
19
|
+
|
|
20
|
+
Use `Slider` when you want the richer shadcn-style component.
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<Slider [value]="[75]" />
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Keep `input[Slider]` when a plain native range input is still the best fit.
|
|
27
|
+
|
|
28
|
+
```html
|
|
29
|
+
<input type="range" Slider />
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Basic usage
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
const volume = signal<readonly number[]>([75]);
|
|
36
|
+
|
|
37
|
+
<Slider
|
|
38
|
+
aria-label="Volume"
|
|
39
|
+
[min]="0"
|
|
40
|
+
[max]="100"
|
|
41
|
+
[step]="1"
|
|
42
|
+
[value]="volume()"
|
|
43
|
+
(valueChange)="volume.set($event)"
|
|
44
|
+
class="w-full max-w-sm" />
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Common patterns
|
|
48
|
+
|
|
49
|
+
### Range
|
|
50
|
+
|
|
51
|
+
Two values render a range slider.
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
const priceRange = signal<readonly number[]>([25, 50]);
|
|
55
|
+
|
|
56
|
+
<Slider
|
|
57
|
+
aria-label="Price range"
|
|
58
|
+
min="0"
|
|
59
|
+
max="100"
|
|
60
|
+
step="5"
|
|
61
|
+
[value]="priceRange()"
|
|
62
|
+
(valueChange)="priceRange.set($event)"
|
|
63
|
+
[thumbLabels]="['Minimum price', 'Maximum price']" />
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Multiple thumbs
|
|
67
|
+
|
|
68
|
+
Three or more values render several thumbs in sorted order.
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
const equalizer = signal<readonly number[]>([10, 20, 70]);
|
|
72
|
+
|
|
73
|
+
<Slider
|
|
74
|
+
aria-label="Equalizer"
|
|
75
|
+
min="0"
|
|
76
|
+
max="100"
|
|
77
|
+
step="10"
|
|
78
|
+
[value]="equalizer()"
|
|
79
|
+
(valueChange)="equalizer.set($event)"
|
|
80
|
+
[thumbLabels]="['Bass', 'Mid', 'Treble']" />
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Vertical
|
|
84
|
+
|
|
85
|
+
Set `orientation="vertical"` and provide an explicit height through `class`.
|
|
86
|
+
|
|
87
|
+
```html
|
|
88
|
+
<div class="flex items-center gap-6">
|
|
89
|
+
<Slider aria-label="Primary level" orientation="vertical" [value]="[50]" class="h-40" />
|
|
90
|
+
<Slider aria-label="Secondary level" orientation="vertical" [value]="[25]" class="h-40" />
|
|
91
|
+
</div>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Controlled slider
|
|
95
|
+
|
|
96
|
+
Drive the values from a signal when nearby UI should react immediately.
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
const temperatureRange = signal<readonly number[]>([30, 70]);
|
|
100
|
+
|
|
101
|
+
<Slider
|
|
102
|
+
aria-label="Temperature range"
|
|
103
|
+
min="0"
|
|
104
|
+
max="100"
|
|
105
|
+
step="5"
|
|
106
|
+
[value]="temperatureRange()"
|
|
107
|
+
(valueChange)="temperatureRange.set($event)"
|
|
108
|
+
[thumbLabels]="['Minimum temperature', 'Maximum temperature']" />
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Disabled state
|
|
112
|
+
|
|
113
|
+
```html
|
|
114
|
+
<Slider aria-label="Disabled notifications volume" [value]="[50]" disabled />
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### RTL
|
|
118
|
+
|
|
119
|
+
The component follows the surrounding document direction automatically.
|
|
120
|
+
|
|
121
|
+
```html
|
|
122
|
+
<section dir="rtl" lang="ar" class="w-full max-w-sm text-right">
|
|
123
|
+
<Slider aria-label="مستوى الصوت" [value]="[75]" class="w-full" />
|
|
124
|
+
</section>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Native input companion
|
|
128
|
+
|
|
129
|
+
Use the exported native directive when the browser-native range input is still
|
|
130
|
+
the best Angular fit for forms and `label[for]` wiring.
|
|
131
|
+
|
|
132
|
+
```html
|
|
133
|
+
<label for="native-volume" class="mb-2 block">Volume</label>
|
|
134
|
+
<input id="native-volume" type="range" Slider min="0" max="100" step="1" class="w-full max-w-sm" />
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## API reference
|
|
138
|
+
|
|
139
|
+
| Input or output | Type | Notes |
|
|
140
|
+
| ----------------------------------------------------- | ---------------------------- | ----------------------------------------------------------------------------------------- |
|
|
141
|
+
| `value` | `readonly number[]` | Array of sorted thumb values. One item renders a single thumb. |
|
|
142
|
+
| `valueChange` | `readonly number[]` | Emits the next array whenever a thumb moves. |
|
|
143
|
+
| `min` | `number` | Lower bound for every thumb. |
|
|
144
|
+
| `max` | `number` | Upper bound for every thumb. |
|
|
145
|
+
| `step` | `number` | Drag and keyboard increment. |
|
|
146
|
+
| `orientation` | `'horizontal' \| 'vertical'` | Vertical sliders need an explicit height via `class`. |
|
|
147
|
+
| `disabled` | `boolean` | Disables drag and keyboard interaction. |
|
|
148
|
+
| `thumbLabels` | `readonly string[]` | Optional accessible labels for each thumb. |
|
|
149
|
+
| `aria-label` / `aria-labelledby` / `aria-describedby` | `string \| null` | Applied to thumb semantics. Prefer `thumbLabels` when several thumbs need distinct names. |
|
|
150
|
+
| `class` | `string` | Width and height utilities on the host component. |
|
|
151
|
+
|
|
152
|
+
`SliderInputDirective` keeps the native `<input type="range">` API and passes
|
|
153
|
+
through ordinary input attributes directly.
|
|
154
|
+
|
|
155
|
+
## Styling and theming
|
|
156
|
+
|
|
157
|
+
The rich `Slider` component uses:
|
|
158
|
+
|
|
159
|
+
- `--secondary` for the track.
|
|
160
|
+
- `--primary` for the active range.
|
|
161
|
+
- `--background` for the thumb surface.
|
|
162
|
+
- `--primary` for the thumb border.
|
|
163
|
+
- `--ring` for the focus-visible outline.
|
|
164
|
+
|
|
165
|
+
Apply width and height utilities through the host `class`, for example
|
|
166
|
+
`w-full`, `max-w-sm`, or `h-40` for vertical sliders.
|
|
167
|
+
|
|
168
|
+
The native input companion keeps its styling in [slider.component.css](./slider.component.css).
|
|
169
|
+
|
|
170
|
+
## Accessibility
|
|
171
|
+
|
|
172
|
+
- Each thumb exposes `role="slider"` with `aria-valuemin`, `aria-valuemax`,
|
|
173
|
+
`aria-valuenow`, and `aria-orientation`.
|
|
174
|
+
- Provide `thumbLabels` when the slider has several thumbs so each one has a
|
|
175
|
+
distinct accessible name.
|
|
176
|
+
- Use `aria-describedby` for helper text, units, or validation guidance.
|
|
177
|
+
- The focused thumb stays tabbable while sibling thumbs use roving `tabindex`.
|
|
178
|
+
- When you need browser-native label semantics, use `SliderInputDirective`
|
|
179
|
+
instead of forcing the rich component into a native-input role.
|
|
180
|
+
|
|
181
|
+
## Keyboard interactions
|
|
182
|
+
|
|
183
|
+
For `Slider`:
|
|
184
|
+
|
|
185
|
+
- Arrow keys adjust the value by `step`.
|
|
186
|
+
- `Page Up` and `Page Down` move by a larger increment.
|
|
187
|
+
- `Home` and `End` jump the active thumb to its local minimum or maximum bound.
|
|
188
|
+
- Pointer dragging and track clicks move the nearest thumb.
|
|
189
|
+
|
|
190
|
+
For `SliderInputDirective`, keyboard behavior follows the browser-native range
|
|
191
|
+
input model.
|
|
192
|
+
|
|
193
|
+
## Angular notes
|
|
194
|
+
|
|
195
|
+
- Prefer `Slider` when you need shadcn-style parity: range selection,
|
|
196
|
+
multiple thumbs, vertical layout, or explicit thumb labels.
|
|
197
|
+
- Prefer `SliderInputDirective` when the control should remain a real native
|
|
198
|
+
input inside Angular forms or a traditional field layout.
|
|
199
|
+
- The two exports are complementary rather than replacements for one another.
|
|
200
|
+
|
|
201
|
+
## Source parity
|
|
202
|
+
|
|
203
|
+
This Angular entrypoint now covers the main shadcn Radix slider examples:
|
|
204
|
+
single-thumb preview, range, multiple thumbs, vertical, controlled, disabled,
|
|
205
|
+
and RTL. The native `input[Slider]` directive remains intentionally exported
|
|
206
|
+
as an Angular companion for browser-native range inputs instead of disappearing
|
|
207
|
+
behind the richer component.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Spinner
|
|
2
|
+
|
|
3
|
+
Displays a compact loading indicator for inline status, buttons, badges, input groups, and empty states.
|
|
4
|
+
|
|
5
|
+
Use Spinner when work is in progress but the surrounding layout should stay visible and composable.
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { SpinnerComponent } from '@ojiepermana/angular-component/spinner';
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Bring in companion entrypoints such as Button, Badge, Item, Empty, or Input Group only when the surrounding example needs them.
|
|
14
|
+
|
|
15
|
+
## Basic usage
|
|
16
|
+
|
|
17
|
+
By default, `Spinner` exposes `role="status"` with an accessible name of `Loading`.
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<Spinner aria-label="Loading invoices" />
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Common patterns
|
|
24
|
+
|
|
25
|
+
### Size and color
|
|
26
|
+
|
|
27
|
+
Use the `class` input to change size, color, or surrounding spacing.
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<div class="flex items-center gap-4">
|
|
31
|
+
<Spinner class="size-3" aria-label="Refreshing alerts" />
|
|
32
|
+
<Spinner class="size-4 text-primary" aria-label="Refreshing dashboard" />
|
|
33
|
+
<Spinner class="size-6 text-muted-foreground" aria-label="Loading analytics" />
|
|
34
|
+
</div>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Decorative inline status
|
|
38
|
+
|
|
39
|
+
When nearby text already explains the loading state, mark the spinner as decorative so assistive technology does not hear duplicate status announcements.
|
|
40
|
+
|
|
41
|
+
```html
|
|
42
|
+
<button Button type="button" disabled class="gap-2">
|
|
43
|
+
<Spinner decorative />
|
|
44
|
+
Loading...
|
|
45
|
+
</button>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Button and badge composition
|
|
49
|
+
|
|
50
|
+
There is no React-style `data-icon` API in the Angular library. Place `Spinner` before or after the visible label and use standard gap utilities on the host surface.
|
|
51
|
+
|
|
52
|
+
```html
|
|
53
|
+
<button Button type="button" variant="outline" disabled class="gap-2">
|
|
54
|
+
<Spinner decorative />
|
|
55
|
+
Please wait
|
|
56
|
+
</button>
|
|
57
|
+
|
|
58
|
+
<Badge class="gap-1.5">
|
|
59
|
+
<Spinner decorative class="size-3" />
|
|
60
|
+
Syncing
|
|
61
|
+
</Badge>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Item row
|
|
65
|
+
|
|
66
|
+
The upstream preview maps cleanly to the local Item primitive.
|
|
67
|
+
|
|
68
|
+
```html
|
|
69
|
+
<Item variant="muted" class="w-full max-w-xs [--radius:1rem]">
|
|
70
|
+
<ItemMedia>
|
|
71
|
+
<Spinner decorative />
|
|
72
|
+
</ItemMedia>
|
|
73
|
+
<ItemContent>
|
|
74
|
+
<ItemTitle>Processing payment...</ItemTitle>
|
|
75
|
+
</ItemContent>
|
|
76
|
+
<ItemContent class="flex-none justify-end">
|
|
77
|
+
<span class="text-sm tabular-nums">$100.00</span>
|
|
78
|
+
</ItemContent>
|
|
79
|
+
</Item>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Input group status
|
|
83
|
+
|
|
84
|
+
Spinner works as projected content inside `InputGroupAddon` for inline or block-end status rows.
|
|
85
|
+
|
|
86
|
+
```html
|
|
87
|
+
<InputGroup>
|
|
88
|
+
<input InputGroupInput placeholder="Send a message..." disabled />
|
|
89
|
+
<InputGroupAddon align="inline-end">
|
|
90
|
+
<Spinner decorative />
|
|
91
|
+
</InputGroupAddon>
|
|
92
|
+
</InputGroup>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Empty state
|
|
96
|
+
|
|
97
|
+
Project the spinner into `EmptyMedia` when a request is still processing.
|
|
98
|
+
|
|
99
|
+
```html
|
|
100
|
+
<Empty class="w-full max-w-xl rounded-2xl border border-border bg-card/40">
|
|
101
|
+
<EmptyHeader>
|
|
102
|
+
<EmptyMedia variant="icon">
|
|
103
|
+
<Spinner decorative class="size-5" />
|
|
104
|
+
</EmptyMedia>
|
|
105
|
+
<EmptyTitle>Processing your request</EmptyTitle>
|
|
106
|
+
<EmptyDescription>Please wait while the operation completes.</EmptyDescription>
|
|
107
|
+
</EmptyHeader>
|
|
108
|
+
</Empty>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### RTL
|
|
112
|
+
|
|
113
|
+
Set `dir="rtl"` on the surrounding container or layout shell. The spinner stays direction-agnostic while the surrounding row flips logically.
|
|
114
|
+
|
|
115
|
+
```html
|
|
116
|
+
<section dir="rtl" lang="ar" class="w-full max-w-xs">
|
|
117
|
+
<Item variant="muted">
|
|
118
|
+
<ItemMedia>
|
|
119
|
+
<Spinner decorative />
|
|
120
|
+
</ItemMedia>
|
|
121
|
+
<ItemContent>
|
|
122
|
+
<ItemTitle>جاري معالجة الدفع...</ItemTitle>
|
|
123
|
+
</ItemContent>
|
|
124
|
+
</Item>
|
|
125
|
+
</section>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## API reference
|
|
129
|
+
|
|
130
|
+
| Input | Type | Default | Notes |
|
|
131
|
+
| ----------------- | ---------------- | ----------- | ------------------------------------------------------- |
|
|
132
|
+
| `class` | `string` | `''` | Controls size, color, and layout spacing. |
|
|
133
|
+
| `decorative` | `boolean` | `false` | Removes status semantics and sets `aria-hidden="true"`. |
|
|
134
|
+
| `aria-label` | `string` | `'Loading'` | Accessible name when the spinner stands alone. |
|
|
135
|
+
| `aria-labelledby` | `string \| null` | `null` | Connects the spinner to nearby visible text. |
|
|
136
|
+
|
|
137
|
+
Native host attributes such as `id`, `dir`, `data-*`, and custom utility classes still pass through to the rendered custom element.
|
|
138
|
+
|
|
139
|
+
## Styling and theming
|
|
140
|
+
|
|
141
|
+
The spinner inherits `currentColor`, so it automatically matches the surrounding button, badge, item, or muted text color unless a utility overrides it.
|
|
142
|
+
|
|
143
|
+
The default animation uses `animate-spin` and automatically stops under `prefers-reduced-motion`.
|
|
144
|
+
|
|
145
|
+
## Accessibility
|
|
146
|
+
|
|
147
|
+
- Default host is a named `status` element for standalone loading indicators.
|
|
148
|
+
- Set `decorative` when nearby text already announces the loading state.
|
|
149
|
+
- Use `aria-labelledby` instead of a second invisible label when visible copy already exists in the same row.
|
|
150
|
+
- Keep the spinner paired with meaningful text or layout context for passive loading states.
|
|
151
|
+
|
|
152
|
+
## Angular notes
|
|
153
|
+
|
|
154
|
+
- `Spinner` is a standalone component with no providers or services.
|
|
155
|
+
- Size and color remain utility-driven instead of introducing React-style variant props.
|
|
156
|
+
- The `decorative` input is the Angular-first way to avoid repeated status announcements inside composed controls.
|
|
157
|
+
|
|
158
|
+
## Source parity
|
|
159
|
+
|
|
160
|
+
This Angular implementation follows the shadcn Spinner page closely for preview, sizing, buttons, badges, input groups, empty states, and RTL composition while translating the API to standalone imports, utility-driven styling, and explicit accessibility bindings.
|
package/switch/README.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Switch
|
|
2
|
+
|
|
3
|
+
A shadcn-style switch primitive built on Angular Material's `mat-slide-toggle`, with `ControlValueAccessor` support for `ngModel` and reactive forms.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { FormsModule } from '@angular/forms';
|
|
9
|
+
import { SwitchComponent } from '@ojiepermana/angular-component/switch';
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Add `FormsModule` only when the host component uses `ngModel`. Reactive forms work through the same primitive.
|
|
13
|
+
|
|
14
|
+
## Basic usage
|
|
15
|
+
|
|
16
|
+
Use projected content for compact inline labels.
|
|
17
|
+
|
|
18
|
+
```html
|
|
19
|
+
<Switch [(ngModel)]="airplaneMode" name="airplane-mode">Airplane mode</Switch>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
For helper text or card-like settings rows, move the copy outside the switch and connect it with `aria-labelledby` plus `aria-describedby`.
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<div class="flex items-start justify-between gap-4 rounded-xl border border-border bg-card/40 p-4">
|
|
26
|
+
<div class="space-y-1">
|
|
27
|
+
<p id="switch-share-label" class="font-medium">Share across devices</p>
|
|
28
|
+
<p id="switch-share-description" class="text-sm leading-5 text-muted-foreground">
|
|
29
|
+
Focus is shared across devices, and turns off when you leave the app.
|
|
30
|
+
</p>
|
|
31
|
+
</div>
|
|
32
|
+
<Switch
|
|
33
|
+
[ngModel]="shareAcrossDevices()"
|
|
34
|
+
(ngModelChange)="shareAcrossDevices.set($event)"
|
|
35
|
+
name="share-across-devices"
|
|
36
|
+
aria-labelledby="switch-share-label"
|
|
37
|
+
aria-describedby="switch-share-description" />
|
|
38
|
+
</div>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Reactive forms continue to work through the component's value accessor.
|
|
42
|
+
|
|
43
|
+
```html
|
|
44
|
+
<Switch [formControl]="form.controls.notifications" aria-label="Email notifications" />
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Common patterns
|
|
48
|
+
|
|
49
|
+
### Descriptive settings row
|
|
50
|
+
|
|
51
|
+
Use `aria-labelledby` and `aria-describedby` when the visible copy sits outside the switch.
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<div class="flex items-start justify-between gap-4">
|
|
55
|
+
<div class="space-y-1">
|
|
56
|
+
<p id="setting-label" class="font-medium">Share across devices</p>
|
|
57
|
+
<p id="setting-description" class="text-sm text-muted-foreground">
|
|
58
|
+
Focus is shared across devices, and turns off when you leave the app.
|
|
59
|
+
</p>
|
|
60
|
+
</div>
|
|
61
|
+
<Switch
|
|
62
|
+
[ngModel]="shareAcrossDevices()"
|
|
63
|
+
(ngModelChange)="shareAcrossDevices.set($event)"
|
|
64
|
+
name="share-across-devices"
|
|
65
|
+
aria-labelledby="setting-label"
|
|
66
|
+
aria-describedby="setting-description" />
|
|
67
|
+
</div>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Choice card layout
|
|
71
|
+
|
|
72
|
+
The upstream shadcn example wraps the whole field in a clickable label. This Angular primitive keeps the switch as the single interactive control and uses the surrounding card only for layout.
|
|
73
|
+
|
|
74
|
+
```html
|
|
75
|
+
<div class="rounded-xl border border-border bg-card/40 p-4">
|
|
76
|
+
<div class="flex items-start justify-between gap-4">
|
|
77
|
+
<div class="space-y-1">
|
|
78
|
+
<p id="notifications-label" class="font-medium">Enable notifications</p>
|
|
79
|
+
<p id="notifications-description" class="text-sm text-muted-foreground">
|
|
80
|
+
Receive notifications when focus mode is enabled or disabled.
|
|
81
|
+
</p>
|
|
82
|
+
</div>
|
|
83
|
+
<Switch
|
|
84
|
+
[ngModel]="notificationsEnabled()"
|
|
85
|
+
(ngModelChange)="notificationsEnabled.set($event)"
|
|
86
|
+
name="notifications-card"
|
|
87
|
+
aria-labelledby="notifications-label"
|
|
88
|
+
aria-describedby="notifications-description" />
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Invalid state
|
|
94
|
+
|
|
95
|
+
Forward `aria-invalid="true"` when validation should promote the switch into the destructive token set.
|
|
96
|
+
|
|
97
|
+
```html
|
|
98
|
+
<Switch
|
|
99
|
+
[ngModel]="acceptTerms()"
|
|
100
|
+
(ngModelChange)="acceptTerms.set($event)"
|
|
101
|
+
name="terms-switch"
|
|
102
|
+
aria-invalid="true"
|
|
103
|
+
aria-label="Accept terms and conditions" />
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Size
|
|
107
|
+
|
|
108
|
+
Use `size="sm"` for denser settings lists and compact preference panes.
|
|
109
|
+
|
|
110
|
+
```html
|
|
111
|
+
<Switch size="sm" [(ngModel)]="compactPreference" name="compact-preference">Compact mode</Switch>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## API reference
|
|
115
|
+
|
|
116
|
+
| Input | Type | Default | Notes |
|
|
117
|
+
| ------------------ | --------------------------- | -------------- | ------------------------------------------------------------------------- |
|
|
118
|
+
| `id` | `string` | auto-generated | Forwarded to Material; the focusable switch button becomes `<id>-button`. |
|
|
119
|
+
| `name` | `string \| null` | `null` | Forwarded to the underlying switch control. |
|
|
120
|
+
| `disabled` | `boolean` | `false` | Merges with form-driven disabled state. |
|
|
121
|
+
| `required` | `boolean` | `false` | Forwarded to the underlying Material switch. |
|
|
122
|
+
| `aria-label` | `string \| null` | `null` | Use for compact or text-free switch controls. |
|
|
123
|
+
| `aria-describedby` | `string \| null` | `null` | Links helper or error text outside the control. |
|
|
124
|
+
| `aria-labelledby` | `string \| null` | `null` | Best choice for descriptive rows and card layouts. |
|
|
125
|
+
| `aria-invalid` | `boolean \| string \| null` | `null` | Switches the control into the destructive invalid treatment. |
|
|
126
|
+
| `size` | `'default' \| 'sm'` | `'default'` | Smaller track for dense settings lists. |
|
|
127
|
+
| `class` | `string` | `''` | Adds utility classes to the wrapped Material host. |
|
|
128
|
+
|
|
129
|
+
| Output | Payload |
|
|
130
|
+
| --------------- | --------- |
|
|
131
|
+
| `checkedChange` | `boolean` |
|
|
132
|
+
|
|
133
|
+
Public method: `focus()`.
|
|
134
|
+
|
|
135
|
+
## Styling and theming
|
|
136
|
+
|
|
137
|
+
The component uses a Material bridge so the MDC switch structure is restyled with the library theme tokens.
|
|
138
|
+
|
|
139
|
+
- Default track and handle colors use the shared `primary`, `input`, and `background` tokens.
|
|
140
|
+
- `aria-invalid="true"` switches the switch into the destructive token set.
|
|
141
|
+
- `size="sm"` tightens the track and handle sizing without creating a second entrypoint.
|
|
142
|
+
- Pass spacing or alignment utilities through `class` when the switch needs to line up with multi-line content.
|
|
143
|
+
|
|
144
|
+
Additional visual adjustments belong in `switch.component.css` inside the library.
|
|
145
|
+
|
|
146
|
+
## Accessibility
|
|
147
|
+
|
|
148
|
+
- Give the switch an accessible name through projected content, `aria-label`, or `aria-labelledby`.
|
|
149
|
+
- Use `aria-describedby` for helper or error text rendered outside the control.
|
|
150
|
+
- Prefer `aria-labelledby` over `label[for]` when the visible label is external, because Angular Material renders a focusable switch button rather than a labelable text input.
|
|
151
|
+
- `aria-invalid` is forwarded to the underlying Material host for validation styling and assistive technology cues.
|
|
152
|
+
|
|
153
|
+
## Keyboard interactions
|
|
154
|
+
|
|
155
|
+
- `Tab` moves focus to the switch in DOM order.
|
|
156
|
+
- `Space` toggles the checked state.
|
|
157
|
+
|
|
158
|
+
## Angular notes
|
|
159
|
+
|
|
160
|
+
- `ngModel`, reactive forms, and `checkedChange` all work with the same primitive.
|
|
161
|
+
- Passing `id` forwards a stable base id to Angular Material; the focusable button receives the derived `<id>-button` id.
|
|
162
|
+
- The direct `disabled` input and `setDisabledState()` from forms are merged, so either source can disable the control.
|
|
163
|
+
|
|
164
|
+
## Source parity
|
|
165
|
+
|
|
166
|
+
This Angular implementation follows the shadcn Switch examples while translating the upstream Field helpers and clickable-card label pattern into Angular-friendly descriptive containers, ARIA relationships, and signal-friendly state handling.
|