@raqm/ui 0.0.0-stage → 0.1.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 (178) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE.md +28 -0
  4. package/README.md +125 -3
  5. package/combobox/README.md +17 -0
  6. package/fesm2022/raqm-ui-accordion.mjs +414 -0
  7. package/fesm2022/raqm-ui-accordion.mjs.map +1 -0
  8. package/fesm2022/raqm-ui-alert-dialog.mjs +457 -0
  9. package/fesm2022/raqm-ui-alert-dialog.mjs.map +1 -0
  10. package/fesm2022/raqm-ui-alert.mjs +195 -0
  11. package/fesm2022/raqm-ui-alert.mjs.map +1 -0
  12. package/fesm2022/raqm-ui-aspect-ratio.mjs +66 -0
  13. package/fesm2022/raqm-ui-aspect-ratio.mjs.map +1 -0
  14. package/fesm2022/raqm-ui-attachment.mjs +435 -0
  15. package/fesm2022/raqm-ui-attachment.mjs.map +1 -0
  16. package/fesm2022/raqm-ui-avatar.mjs +337 -0
  17. package/fesm2022/raqm-ui-avatar.mjs.map +1 -0
  18. package/fesm2022/raqm-ui-badge.mjs +68 -0
  19. package/fesm2022/raqm-ui-badge.mjs.map +1 -0
  20. package/fesm2022/raqm-ui-breadcrumb.mjs +309 -0
  21. package/fesm2022/raqm-ui-breadcrumb.mjs.map +1 -0
  22. package/fesm2022/raqm-ui-button-group.mjs +138 -0
  23. package/fesm2022/raqm-ui-button-group.mjs.map +1 -0
  24. package/fesm2022/raqm-ui-button.mjs +295 -0
  25. package/fesm2022/raqm-ui-button.mjs.map +1 -0
  26. package/fesm2022/raqm-ui-calendar.mjs +1394 -0
  27. package/fesm2022/raqm-ui-calendar.mjs.map +1 -0
  28. package/fesm2022/raqm-ui-card.mjs +331 -0
  29. package/fesm2022/raqm-ui-card.mjs.map +1 -0
  30. package/fesm2022/raqm-ui-carousel.mjs +410 -0
  31. package/fesm2022/raqm-ui-carousel.mjs.map +1 -0
  32. package/fesm2022/raqm-ui-checkbox.mjs +86 -0
  33. package/fesm2022/raqm-ui-checkbox.mjs.map +1 -0
  34. package/fesm2022/raqm-ui-collapsible.mjs +266 -0
  35. package/fesm2022/raqm-ui-collapsible.mjs.map +1 -0
  36. package/fesm2022/raqm-ui-combobox.mjs +1584 -0
  37. package/fesm2022/raqm-ui-combobox.mjs.map +1 -0
  38. package/fesm2022/raqm-ui-command.mjs +1210 -0
  39. package/fesm2022/raqm-ui-command.mjs.map +1 -0
  40. package/fesm2022/raqm-ui-context-menu.mjs +723 -0
  41. package/fesm2022/raqm-ui-context-menu.mjs.map +1 -0
  42. package/fesm2022/raqm-ui-dialog.mjs +1214 -0
  43. package/fesm2022/raqm-ui-dialog.mjs.map +1 -0
  44. package/fesm2022/raqm-ui-drawer.mjs +687 -0
  45. package/fesm2022/raqm-ui-drawer.mjs.map +1 -0
  46. package/fesm2022/raqm-ui-dropdown-menu.mjs +1168 -0
  47. package/fesm2022/raqm-ui-dropdown-menu.mjs.map +1 -0
  48. package/fesm2022/raqm-ui-empty.mjs +272 -0
  49. package/fesm2022/raqm-ui-empty.mjs.map +1 -0
  50. package/fesm2022/raqm-ui-field.mjs +517 -0
  51. package/fesm2022/raqm-ui-field.mjs.map +1 -0
  52. package/fesm2022/raqm-ui-hover-card.mjs +828 -0
  53. package/fesm2022/raqm-ui-hover-card.mjs.map +1 -0
  54. package/fesm2022/raqm-ui-input-group.mjs +270 -0
  55. package/fesm2022/raqm-ui-input-group.mjs.map +1 -0
  56. package/fesm2022/raqm-ui-input-otp.mjs +788 -0
  57. package/fesm2022/raqm-ui-input-otp.mjs.map +1 -0
  58. package/fesm2022/raqm-ui-input.mjs +73 -0
  59. package/fesm2022/raqm-ui-input.mjs.map +1 -0
  60. package/fesm2022/raqm-ui-item.mjs +495 -0
  61. package/fesm2022/raqm-ui-item.mjs.map +1 -0
  62. package/fesm2022/raqm-ui-kbd.mjs +80 -0
  63. package/fesm2022/raqm-ui-kbd.mjs.map +1 -0
  64. package/fesm2022/raqm-ui-label.mjs +44 -0
  65. package/fesm2022/raqm-ui-label.mjs.map +1 -0
  66. package/fesm2022/raqm-ui-menubar.mjs +536 -0
  67. package/fesm2022/raqm-ui-menubar.mjs.map +1 -0
  68. package/fesm2022/raqm-ui-native-select.mjs +131 -0
  69. package/fesm2022/raqm-ui-native-select.mjs.map +1 -0
  70. package/fesm2022/raqm-ui-navigation-menu.mjs +1399 -0
  71. package/fesm2022/raqm-ui-navigation-menu.mjs.map +1 -0
  72. package/fesm2022/raqm-ui-overlay-internal.mjs +185 -0
  73. package/fesm2022/raqm-ui-overlay-internal.mjs.map +1 -0
  74. package/fesm2022/raqm-ui-pagination.mjs +440 -0
  75. package/fesm2022/raqm-ui-pagination.mjs.map +1 -0
  76. package/fesm2022/raqm-ui-popover.mjs +1495 -0
  77. package/fesm2022/raqm-ui-popover.mjs.map +1 -0
  78. package/fesm2022/raqm-ui-progress.mjs +369 -0
  79. package/fesm2022/raqm-ui-progress.mjs.map +1 -0
  80. package/fesm2022/raqm-ui-questionnaire.mjs +1005 -0
  81. package/fesm2022/raqm-ui-questionnaire.mjs.map +1 -0
  82. package/fesm2022/raqm-ui-radio-group.mjs +151 -0
  83. package/fesm2022/raqm-ui-radio-group.mjs.map +1 -0
  84. package/fesm2022/raqm-ui-resizable.mjs +439 -0
  85. package/fesm2022/raqm-ui-resizable.mjs.map +1 -0
  86. package/fesm2022/raqm-ui-scroll-area.mjs +510 -0
  87. package/fesm2022/raqm-ui-scroll-area.mjs.map +1 -0
  88. package/fesm2022/raqm-ui-select.mjs +1073 -0
  89. package/fesm2022/raqm-ui-select.mjs.map +1 -0
  90. package/fesm2022/raqm-ui-separator.mjs +103 -0
  91. package/fesm2022/raqm-ui-separator.mjs.map +1 -0
  92. package/fesm2022/raqm-ui-sheet.mjs +411 -0
  93. package/fesm2022/raqm-ui-sheet.mjs.map +1 -0
  94. package/fesm2022/raqm-ui-sidebar.mjs +1784 -0
  95. package/fesm2022/raqm-ui-sidebar.mjs.map +1 -0
  96. package/fesm2022/raqm-ui-skeleton.mjs +50 -0
  97. package/fesm2022/raqm-ui-skeleton.mjs.map +1 -0
  98. package/fesm2022/raqm-ui-slider.mjs +609 -0
  99. package/fesm2022/raqm-ui-slider.mjs.map +1 -0
  100. package/fesm2022/raqm-ui-spinner.mjs +137 -0
  101. package/fesm2022/raqm-ui-spinner.mjs.map +1 -0
  102. package/fesm2022/raqm-ui-switch.mjs +109 -0
  103. package/fesm2022/raqm-ui-switch.mjs.map +1 -0
  104. package/fesm2022/raqm-ui-table.mjs +271 -0
  105. package/fesm2022/raqm-ui-table.mjs.map +1 -0
  106. package/fesm2022/raqm-ui-tabs.mjs +536 -0
  107. package/fesm2022/raqm-ui-tabs.mjs.map +1 -0
  108. package/fesm2022/raqm-ui-textarea.mjs +37 -0
  109. package/fesm2022/raqm-ui-textarea.mjs.map +1 -0
  110. package/fesm2022/raqm-ui-toast.mjs +918 -0
  111. package/fesm2022/raqm-ui-toast.mjs.map +1 -0
  112. package/fesm2022/raqm-ui-toggle-group.mjs +462 -0
  113. package/fesm2022/raqm-ui-toggle-group.mjs.map +1 -0
  114. package/fesm2022/raqm-ui-toggle.mjs +158 -0
  115. package/fesm2022/raqm-ui-toggle.mjs.map +1 -0
  116. package/fesm2022/raqm-ui-tooltip.mjs +1226 -0
  117. package/fesm2022/raqm-ui-tooltip.mjs.map +1 -0
  118. package/fesm2022/raqm-ui.mjs +50 -0
  119. package/input-otp/README.md +12 -0
  120. package/package.json +275 -3
  121. package/styles/theme.css +4322 -0
  122. package/types/raqm-ui-accordion.d.ts +124 -0
  123. package/types/raqm-ui-alert-dialog.d.ts +81 -0
  124. package/types/raqm-ui-alert.d.ts +29 -0
  125. package/types/raqm-ui-aspect-ratio.d.ts +13 -0
  126. package/types/raqm-ui-attachment.d.ts +72 -0
  127. package/types/raqm-ui-avatar.d.ts +67 -0
  128. package/types/raqm-ui-badge.d.ts +20 -0
  129. package/types/raqm-ui-breadcrumb.d.ts +35 -0
  130. package/types/raqm-ui-button-group.d.ts +27 -0
  131. package/types/raqm-ui-button.d.ts +80 -0
  132. package/types/raqm-ui-calendar.d.ts +359 -0
  133. package/types/raqm-ui-card.d.ts +34 -0
  134. package/types/raqm-ui-carousel.d.ts +81 -0
  135. package/types/raqm-ui-checkbox.d.ts +24 -0
  136. package/types/raqm-ui-collapsible.d.ts +72 -0
  137. package/types/raqm-ui-combobox.d.ts +405 -0
  138. package/types/raqm-ui-command.d.ts +256 -0
  139. package/types/raqm-ui-context-menu.d.ts +196 -0
  140. package/types/raqm-ui-dialog.d.ts +232 -0
  141. package/types/raqm-ui-drawer.d.ts +121 -0
  142. package/types/raqm-ui-dropdown-menu.d.ts +319 -0
  143. package/types/raqm-ui-empty.d.ts +35 -0
  144. package/types/raqm-ui-field.d.ts +88 -0
  145. package/types/raqm-ui-hover-card.d.ts +139 -0
  146. package/types/raqm-ui-input-group.d.ts +45 -0
  147. package/types/raqm-ui-input-otp.d.ts +197 -0
  148. package/types/raqm-ui-input.d.ts +16 -0
  149. package/types/raqm-ui-item.d.ts +71 -0
  150. package/types/raqm-ui-kbd.d.ts +12 -0
  151. package/types/raqm-ui-label.d.ts +6 -0
  152. package/types/raqm-ui-menubar.d.ts +159 -0
  153. package/types/raqm-ui-native-select.d.ts +23 -0
  154. package/types/raqm-ui-navigation-menu.d.ts +230 -0
  155. package/types/raqm-ui-overlay-internal.d.ts +5 -0
  156. package/types/raqm-ui-pagination.d.ts +84 -0
  157. package/types/raqm-ui-popover.d.ts +235 -0
  158. package/types/raqm-ui-progress.d.ts +79 -0
  159. package/types/raqm-ui-questionnaire.d.ts +217 -0
  160. package/types/raqm-ui-radio-group.d.ts +48 -0
  161. package/types/raqm-ui-resizable.d.ts +98 -0
  162. package/types/raqm-ui-scroll-area.d.ts +132 -0
  163. package/types/raqm-ui-select.d.ts +205 -0
  164. package/types/raqm-ui-separator.d.ts +21 -0
  165. package/types/raqm-ui-sheet.d.ts +79 -0
  166. package/types/raqm-ui-sidebar.d.ts +285 -0
  167. package/types/raqm-ui-skeleton.d.ts +6 -0
  168. package/types/raqm-ui-slider.d.ts +129 -0
  169. package/types/raqm-ui-spinner.d.ts +32 -0
  170. package/types/raqm-ui-switch.d.ts +32 -0
  171. package/types/raqm-ui-table.d.ts +36 -0
  172. package/types/raqm-ui-tabs.d.ts +154 -0
  173. package/types/raqm-ui-textarea.d.ts +6 -0
  174. package/types/raqm-ui-toast.d.ts +190 -0
  175. package/types/raqm-ui-toggle-group.d.ts +167 -0
  176. package/types/raqm-ui-toggle.d.ts +42 -0
  177. package/types/raqm-ui-tooltip.d.ts +207 -0
  178. package/types/raqm-ui.d.ts +50 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@raqm/ui` are recorded here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project follows
5
+ [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Before `1.0.0`, minor
6
+ releases may include breaking changes.
7
+
8
+ ## [0.1.0] - 2026-11-04
9
+
10
+ ### Added
11
+
12
+ - Initial public release of Raqm UI, an Angular UI library with its own design and API.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Raqm UI contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE.md ADDED
@@ -0,0 +1,28 @@
1
+ # Notices
2
+
3
+ ## shadcn/ui
4
+
5
+ Raqm UI's early visual direction was informed by [shadcn/ui](https://ui.shadcn.com),
6
+ specifically its **Nova** style. shadcn/ui is distributed under the MIT License,
7
+ Copyright (c) 2023 shadcn.
8
+
9
+ The reference checkout used during that work was the shadcn/ui v4 monorepo, identified by
10
+ these package versions:
11
+
12
+ - `shadcn` 4.21.4 (`packages/shadcn`)
13
+ - `@shadcn/react` 0.3.1 (`packages/react`)
14
+ - `@shadcn/registry` 0.1.3 (`packages/registry`)
15
+
16
+ The checkout is not tracked in this repository. To retrieve the same source, check out
17
+ [shadcn-ui/ui](https://github.com/shadcn-ui/ui) at the release or commit that publishes
18
+ those versions.
19
+
20
+ Raqm UI does not include or bundle shadcn/ui source code. The components are implemented
21
+ from scratch for Angular with the Angular CDK, and Raqm UI's design and API are its own;
22
+ shadcn/ui was an early reference, not a parity target. The attribution is kept because the
23
+ initial visual direction and several token values were derived from that reference.
24
+
25
+ ## Angular
26
+
27
+ Raqm UI is built on Angular and the Angular CDK, both distributed under the MIT
28
+ License, Copyright (c) 2010-2026 Google LLC.
package/README.md CHANGED
@@ -1,3 +1,125 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # Raqm UI
2
+
3
+ UI components with Raqm's own design and APIs,
4
+ implemented natively for Angular with the Angular CDK. Standalone components and
5
+ directives, signal inputs and outputs, light/dark themes and first-class RTL.
6
+
7
+ - **Status:** `0.1.0` — pre-1.0, the component API may still change in minor releases.
8
+ - **Angular:** 22.2 (peer dependency), Angular CDK 22.2, `@angular/forms` for the
9
+ form controls.
10
+ - **Styles:** plain CSS custom properties and SCSS. No Tailwind, no React, no runtime
11
+ copy of shadcn/ui.
12
+
13
+ ## Install
14
+
15
+ ```sh
16
+ npm install @raqm/ui @angular/cdk
17
+ ```
18
+
19
+ `@angular/core`, `@angular/common` and `@angular/forms` are peer dependencies and
20
+ are expected to come from your application.
21
+
22
+ ## Load the theme
23
+
24
+ Load the CDK overlay stylesheet first, then the package theme, then your own styles:
25
+
26
+ ```jsonc
27
+ // angular.json -> projects.<app>.architect.build.options.styles
28
+ "styles": [
29
+ "@angular/cdk/overlay-prebuilt.css",
30
+ "@raqm/ui/theme.css",
31
+ "src/styles.scss"
32
+ ]
33
+ ```
34
+
35
+ Import the components you use from their own entrypoint. Focused subpaths keep each
36
+ lazy route from pulling the whole library into its bundle:
37
+
38
+ ```ts
39
+ import { Component } from '@angular/core';
40
+ import { RaqmButton } from '@raqm/ui/button';
41
+ import { RaqmCard } from '@raqm/ui/card';
42
+
43
+ @Component({
44
+ selector: 'app-example',
45
+ imports: [RaqmButton, RaqmCard],
46
+ template: `
47
+ <raqm-card>
48
+ <raqm-card-header>
49
+ <h3 raqm-card-title>Monthly report</h3>
50
+ </raqm-card-header>
51
+ <raqm-card-content>
52
+ <button raqm-button="outline" type="button">Download</button>
53
+ </raqm-card-content>
54
+ </raqm-card>
55
+ `,
56
+ })
57
+ export class ExampleComponent {}
58
+ ```
59
+
60
+ The root import (`from '@raqm/ui'`) aggregates the historically root-exported
61
+ families. Attachment, Calendar, Carousel, Resizable, and Questionnaire remain
62
+ subpath-only. Prefer focused subpaths in application code.
63
+
64
+ ## Themes
65
+
66
+ The theme ships light and dark scopes and follows `prefers-reduced-motion`:
67
+
68
+ | Scope | Effect |
69
+ | --------------------------- | ------------------------------------------ |
70
+ | `:root` | light theme (default) |
71
+ | `[data-raqm-theme="light"]` | explicit light island inside a dark app |
72
+ | `[data-raqm-theme="dark"]` | dark theme for the element and its subtree |
73
+
74
+ All design tokens are `--raqm-*` custom properties, so an application can override
75
+ them in its own stylesheet after the package theme loads. Components use logical CSS
76
+ properties, so `dir="rtl"` mirrors layouts without extra overrides.
77
+
78
+ ## Entrypoints
79
+
80
+ | Area | Subpaths |
81
+ | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
82
+ | Form controls | `button`, `button-group`, `input`, `checkbox`, `switch`, `textarea`, `label`, `radio-group`, `native-select`, `field`, `input-group`, `input-otp`, `select`, `combobox`, `slider`, `calendar`, `toggle`, `toggle-group` |
83
+ | Layout and content | `card`, `item`, `table`, `sidebar`, `pagination`, `breadcrumb`, `empty`, `attachment`, `resizable`, `scroll-area` |
84
+ | Overlays | `dialog`, `alert-dialog`, `drawer`, `sheet`, `popover`, `hover-card`, `tooltip`, `toast`, `command` |
85
+ | Menus and disclosure | `dropdown-menu`, `context-menu`, `menubar`, `navigation-menu`, `accordion`, `collapsible`, `tabs` |
86
+ | Display | `badge`, `avatar`, `spinner`, `kbd`, `separator`, `skeleton`, `aspect-ratio` |
87
+ | Feedback | `alert`, `progress`, `questionnaire` |
88
+ | Media | `carousel` (bundles `embla-carousel`) |
89
+
90
+ Multipart families provide one readonly Angular template dependency array:
91
+
92
+ ```ts
93
+ import { RaqmCard } from '@raqm/ui/card';
94
+ // Use imports: [RaqmCard] to enable the Card template parts.
95
+ ```
96
+
97
+ Single-piece controls export their class directly, for example `RaqmInput` from
98
+ `@raqm/ui/input`. Use actual `Component`/`Directive` suffixed declarations for
99
+ instance queries, injection, and inheritance—not a family array. Services and
100
+ data types remain separately exported. The former `/controls` and `/display`
101
+ entrypoints are removed; Toggle Group now uses `/toggle-group`. This is an
102
+ intentional pre-release breaking import migration, without compatibility aliases.
103
+
104
+ Attachment, Calendar, Carousel, Resizable, and Questionnaire are secondary-only;
105
+ the root aggregate preserves its historical family boundary.
106
+
107
+ ## Accessibility
108
+
109
+ Components are authored with keyboard and screen-reader semantics in hand: the dialog
110
+ family warns in development when no accessible name is provided, focus is moved and
111
+ restored through the CDK, and interactive parts expose their state through ARIA.
112
+ Overlay panes render in a CDK overlay; load `@angular/cdk/overlay-prebuilt.css` as
113
+ shown above.
114
+
115
+ ## Component guides
116
+
117
+ - [Button](https://github.com/KeyLitDev/RaqmUI/blob/main/Raqm-UI-demo/src/app/pages/button/button.md)
118
+ - [Button Group](https://github.com/KeyLitDev/RaqmUI/blob/main/Raqm-UI-demo/src/app/pages/button-group/button-group.md)
119
+
120
+ ## License
121
+
122
+ MIT — see [LICENSE](https://github.com/KeyLitDev/RaqmUI/blob/main/LICENSE).
123
+
124
+ For attribution, see
125
+ [NOTICE.md](https://github.com/KeyLitDev/RaqmUI/blob/main/NOTICE.md).
@@ -0,0 +1,17 @@
1
+ # Combobox data and templates
2
+
3
+ `items` accepts a mixture of `RaqmComboboxOption` and `RaqmComboboxGroup` entries. A group has a `label` and an `options` array. Values must be unique across all entries, including groups. Filtering uses option labels, hides groups with no matching options, and preserves entry order. As in the existing single-value behavior, a query equal to the selected label shows all options. Group labels are not selectable.
4
+
5
+ Set `separatorBefore` on a group to draw a nonselectable separator before it when a preceding entry is visible. Empty filtered groups and leading separators are omitted.
6
+
7
+ In single-value modes, a disabled selected option cannot be cleared or replaced by the user; programmatic value writes remain available.
8
+
9
+ For inline mode, project an `ng-template[raqm-combobox-prefix]` to render passive content in the input group's start addon. Other modes ignore it. Mark decorative icons `aria-hidden="true"`; provide the combobox's accessible label separately.
10
+
11
+ `popupWidth` accepts a CSS width string; by default the popup follows its anchor's width. `popupAlignOffset` is a number of CSS pixels along the logical inline axis: negative moves toward inline-start, including in RTL. For the input-group reference, use `popupWidth="15rem"` and `[popupAlignOffset]="-28"`. The existing minimum width and viewport collision constraints still apply. Both inputs apply in every mode and can change while open.
12
+
13
+ While open, direction updates follow the `dir` input, CDK direction changes, viewport resize, and `dir`, `class`, or `style` attribute changes on the host or its existing ancestors. Stylesheet-only changes without those events and reparenting the host while open are not observed; reopening resolves direction again.
14
+
15
+ Project an `ng-template[raqm-combobox-item]` to customize option content in any mode. Its implicit value and `item` are the option; `selected` and `active` are booleans. The component retains the option role, selection state and accessible name from `item.label`; filtering and selected labels also use that label. Template content must be noninteractive, without nested buttons, links, inputs or focusable elements.
16
+
17
+ For meaningful secondary content, set the option's `description` to the corresponding text. It is exposed as an accessible description without changing the option name or filtering; render the visible description in the item template if desired.
@@ -0,0 +1,414 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, DestroyRef, Directive, InjectionToken, booleanAttribute, computed, inject, input, isDevMode, model, signal } from "@angular/core";
3
+ const RAQM_ACCORDION = new InjectionToken("RaqmAccordion");
4
+ const RAQM_ACCORDION_ITEM = new InjectionToken("RaqmAccordionItem");
5
+ var RaqmAccordionComponent = class RaqmAccordionComponent {
6
+ multiple = input(false, {
7
+ ...ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {},
8
+ transform: booleanAttribute
9
+ });
10
+ value = model([], ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
11
+ defaultValue = input([], ...ngDevMode ? [{ debugName: "defaultValue" }] : /* istanbul ignore next */ []);
12
+ disabled = input(false, {
13
+ ...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
14
+ transform: booleanAttribute
15
+ });
16
+ items = signal([], ...ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []);
17
+ interacted = signal(false, ...ngDevMode ? [{ debugName: "interacted" }] : /* istanbul ignore next */ []);
18
+ openValues = computed(() => {
19
+ const bound = this.value();
20
+ if (bound.length > 0 || this.interacted()) return bound;
21
+ const seed = this.defaultValue();
22
+ return this.multiple() ? seed : seed.slice(0, 1);
23
+ }, ...ngDevMode ? [{ debugName: "openValues" }] : /* istanbul ignore next */ []);
24
+ isOpen(value) {
25
+ const current = this.openValues();
26
+ return this.multiple() ? current.includes(value) : current[0] === value;
27
+ }
28
+ toggle(value) {
29
+ if (this.disabled()) return;
30
+ const current = this.openValues();
31
+ this.interacted.set(true);
32
+ if (this.multiple()) {
33
+ this.value.set(current.includes(value) ? current.filter((open) => open !== value) : [...current, value]);
34
+ return;
35
+ }
36
+ this.value.set(current[0] === value ? [] : [value]);
37
+ }
38
+ register(item) {
39
+ if (isDevMode() && this.items().some((registered) => registered.value === item.value)) console.error(`[raqm-accordion] Duplicate item value "${item.value}"; Accordion item values must be unique.`);
40
+ this.items.update((items) => [...items, item]);
41
+ }
42
+ unregister(item) {
43
+ this.items.update((items) => items.filter((registered) => registered !== item));
44
+ }
45
+ static ɵfac = i0.ɵɵngDeclareFactory({
46
+ minVersion: "12.0.0",
47
+ version: "22.2.2",
48
+ ngImport: i0,
49
+ type: RaqmAccordionComponent,
50
+ deps: [],
51
+ target: i0.ɵɵFactoryTarget.Component
52
+ });
53
+ static ɵcmp = i0.ɵɵngDeclareComponent({
54
+ minVersion: "17.1.0",
55
+ version: "22.2.2",
56
+ type: RaqmAccordionComponent,
57
+ isStandalone: true,
58
+ selector: "raqm-accordion",
59
+ inputs: {
60
+ multiple: {
61
+ classPropertyName: "multiple",
62
+ publicName: "multiple",
63
+ isSignal: true,
64
+ isRequired: false,
65
+ transformFunction: null
66
+ },
67
+ value: {
68
+ classPropertyName: "value",
69
+ publicName: "value",
70
+ isSignal: true,
71
+ isRequired: false,
72
+ transformFunction: null
73
+ },
74
+ defaultValue: {
75
+ classPropertyName: "defaultValue",
76
+ publicName: "defaultValue",
77
+ isSignal: true,
78
+ isRequired: false,
79
+ transformFunction: null
80
+ },
81
+ disabled: {
82
+ classPropertyName: "disabled",
83
+ publicName: "disabled",
84
+ isSignal: true,
85
+ isRequired: false,
86
+ transformFunction: null
87
+ }
88
+ },
89
+ outputs: { value: "valueChange" },
90
+ host: { classAttribute: "raqm-accordion" },
91
+ providers: [{
92
+ provide: RAQM_ACCORDION,
93
+ useExisting: RaqmAccordionComponent
94
+ }],
95
+ ngImport: i0,
96
+ template: "<ng-content />",
97
+ isInline: true,
98
+ styles: [":host{display:flex;flex-direction:column;inline-size:100%}\n"],
99
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
100
+ });
101
+ };
102
+ i0.ɵɵngDeclareClassMetadata({
103
+ minVersion: "12.0.0",
104
+ version: "22.2.2",
105
+ ngImport: i0,
106
+ type: RaqmAccordionComponent,
107
+ decorators: [{
108
+ type: Component,
109
+ args: [{
110
+ selector: "raqm-accordion",
111
+ template: "<ng-content />",
112
+ changeDetection: ChangeDetectionStrategy.OnPush,
113
+ host: { class: "raqm-accordion" },
114
+ providers: [{
115
+ provide: RAQM_ACCORDION,
116
+ useExisting: RaqmAccordionComponent
117
+ }],
118
+ styles: [":host{display:flex;flex-direction:column;inline-size:100%}\n"]
119
+ }]
120
+ }],
121
+ propDecorators: {
122
+ multiple: [{
123
+ type: i0.Input,
124
+ args: [{
125
+ isSignal: true,
126
+ alias: "multiple",
127
+ required: false
128
+ }]
129
+ }],
130
+ value: [{
131
+ type: i0.Input,
132
+ args: [{
133
+ isSignal: true,
134
+ alias: "value",
135
+ required: false
136
+ }]
137
+ }, {
138
+ type: i0.Output,
139
+ args: ["valueChange"]
140
+ }],
141
+ defaultValue: [{
142
+ type: i0.Input,
143
+ args: [{
144
+ isSignal: true,
145
+ alias: "defaultValue",
146
+ required: false
147
+ }]
148
+ }],
149
+ disabled: [{
150
+ type: i0.Input,
151
+ args: [{
152
+ isSignal: true,
153
+ alias: "disabled",
154
+ required: false
155
+ }]
156
+ }]
157
+ }
158
+ });
159
+ let nextAccordionItemId = 0;
160
+ var RaqmAccordionItemComponent = class RaqmAccordionItemComponent {
161
+ accordion = inject(RAQM_ACCORDION, { optional: true });
162
+ destroyRef = inject(DestroyRef);
163
+ value = input.required(...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
164
+ disabled = input(false, {
165
+ ...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
166
+ transform: booleanAttribute
167
+ });
168
+ instanceId = `raqm-accordion-item-${++nextAccordionItemId}`;
169
+ triggerId = `${this.instanceId}-trigger`;
170
+ contentId = `${this.instanceId}-content`;
171
+ effectiveDisabled = computed(() => this.disabled() || (this.accordion?.disabled() ?? false), ...ngDevMode ? [{ debugName: "effectiveDisabled" }] : /* istanbul ignore next */ []);
172
+ open = computed(() => this.accordion?.isOpen(this.value()) ?? false, ...ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []);
173
+ ref = (() => {
174
+ const self = this;
175
+ return { get value() {
176
+ return self.value();
177
+ } };
178
+ })();
179
+ constructor() {
180
+ if (isDevMode() && this.accordion === null) console.error("[raqm-accordion-item] No parent <raqm-accordion> found; the item has no open state.");
181
+ this.destroyRef.onDestroy(() => this.accordion?.unregister(this.ref));
182
+ }
183
+ ngOnInit() {
184
+ this.accordion?.register(this.ref);
185
+ }
186
+ toggle() {
187
+ if (this.effectiveDisabled()) return;
188
+ this.accordion?.toggle(this.value());
189
+ }
190
+ static ɵfac = i0.ɵɵngDeclareFactory({
191
+ minVersion: "12.0.0",
192
+ version: "22.2.2",
193
+ ngImport: i0,
194
+ type: RaqmAccordionItemComponent,
195
+ deps: [],
196
+ target: i0.ɵɵFactoryTarget.Component
197
+ });
198
+ static ɵcmp = i0.ɵɵngDeclareComponent({
199
+ minVersion: "17.1.0",
200
+ version: "22.2.2",
201
+ type: RaqmAccordionItemComponent,
202
+ isStandalone: true,
203
+ selector: "raqm-accordion-item",
204
+ inputs: {
205
+ value: {
206
+ classPropertyName: "value",
207
+ publicName: "value",
208
+ isSignal: true,
209
+ isRequired: true,
210
+ transformFunction: null
211
+ },
212
+ disabled: {
213
+ classPropertyName: "disabled",
214
+ publicName: "disabled",
215
+ isSignal: true,
216
+ isRequired: false,
217
+ transformFunction: null
218
+ }
219
+ },
220
+ host: {
221
+ properties: {
222
+ "attr.data-raqm-state": "open() ? \"open\" : \"closed\"",
223
+ "attr.data-raqm-disabled": "effectiveDisabled() ? \"\" : null"
224
+ },
225
+ classAttribute: "raqm-accordion-item"
226
+ },
227
+ providers: [{
228
+ provide: RAQM_ACCORDION_ITEM,
229
+ useExisting: RaqmAccordionItemComponent
230
+ }],
231
+ ngImport: i0,
232
+ template: "<ng-content />",
233
+ isInline: true,
234
+ styles: [":host{display:block}:host(:not(:last-child)){border-block-end:1px solid var(--raqm-border)}\n"],
235
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
236
+ });
237
+ };
238
+ i0.ɵɵngDeclareClassMetadata({
239
+ minVersion: "12.0.0",
240
+ version: "22.2.2",
241
+ ngImport: i0,
242
+ type: RaqmAccordionItemComponent,
243
+ decorators: [{
244
+ type: Component,
245
+ args: [{
246
+ selector: "raqm-accordion-item",
247
+ template: "<ng-content />",
248
+ changeDetection: ChangeDetectionStrategy.OnPush,
249
+ host: {
250
+ class: "raqm-accordion-item",
251
+ "[attr.data-raqm-state]": "open() ? \"open\" : \"closed\"",
252
+ "[attr.data-raqm-disabled]": "effectiveDisabled() ? \"\" : null"
253
+ },
254
+ providers: [{
255
+ provide: RAQM_ACCORDION_ITEM,
256
+ useExisting: RaqmAccordionItemComponent
257
+ }],
258
+ styles: [":host{display:block}:host(:not(:last-child)){border-block-end:1px solid var(--raqm-border)}\n"]
259
+ }]
260
+ }],
261
+ ctorParameters: () => [],
262
+ propDecorators: {
263
+ value: [{
264
+ type: i0.Input,
265
+ args: [{
266
+ isSignal: true,
267
+ alias: "value",
268
+ required: true
269
+ }]
270
+ }],
271
+ disabled: [{
272
+ type: i0.Input,
273
+ args: [{
274
+ isSignal: true,
275
+ alias: "disabled",
276
+ required: false
277
+ }]
278
+ }]
279
+ }
280
+ });
281
+ var RaqmAccordionTriggerDirective = class RaqmAccordionTriggerDirective {
282
+ item = inject(RAQM_ACCORDION_ITEM, { optional: true });
283
+ open = computed(() => this.item?.open() ?? false, ...ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []);
284
+ effectiveDisabled = computed(() => this.item?.effectiveDisabled() ?? false, ...ngDevMode ? [{ debugName: "effectiveDisabled" }] : /* istanbul ignore next */ []);
285
+ triggerId = computed(() => this.item?.triggerId ?? null, ...ngDevMode ? [{ debugName: "triggerId" }] : /* istanbul ignore next */ []);
286
+ contentId = computed(() => this.item?.contentId ?? null, ...ngDevMode ? [{ debugName: "contentId" }] : /* istanbul ignore next */ []);
287
+ constructor() {
288
+ if (isDevMode() && this.item === null) console.error("[raqm-accordion-trigger] No parent <raqm-accordion-item> found; the trigger cannot toggle a panel.");
289
+ }
290
+ onClick() {
291
+ if (!this.effectiveDisabled()) this.item?.toggle();
292
+ }
293
+ static ɵfac = i0.ɵɵngDeclareFactory({
294
+ minVersion: "12.0.0",
295
+ version: "22.2.2",
296
+ ngImport: i0,
297
+ type: RaqmAccordionTriggerDirective,
298
+ deps: [],
299
+ target: i0.ɵɵFactoryTarget.Directive
300
+ });
301
+ static ɵdir = i0.ɵɵngDeclareDirective({
302
+ minVersion: "14.0.0",
303
+ version: "22.2.2",
304
+ type: RaqmAccordionTriggerDirective,
305
+ isStandalone: true,
306
+ selector: "button[raqm-accordion-trigger]",
307
+ host: {
308
+ attributes: { "type": "button" },
309
+ listeners: { "click": "onClick()" },
310
+ properties: {
311
+ "attr.id": "triggerId()",
312
+ "attr.aria-expanded": "open() ? \"true\" : \"false\"",
313
+ "attr.aria-controls": "contentId()",
314
+ "attr.aria-disabled": "effectiveDisabled() ? \"true\" : null"
315
+ },
316
+ classAttribute: "raqm-accordion-trigger"
317
+ },
318
+ ngImport: i0
319
+ });
320
+ };
321
+ i0.ɵɵngDeclareClassMetadata({
322
+ minVersion: "12.0.0",
323
+ version: "22.2.2",
324
+ ngImport: i0,
325
+ type: RaqmAccordionTriggerDirective,
326
+ decorators: [{
327
+ type: Directive,
328
+ args: [{
329
+ selector: "button[raqm-accordion-trigger]",
330
+ host: {
331
+ class: "raqm-accordion-trigger",
332
+ type: "button",
333
+ "[attr.id]": "triggerId()",
334
+ "[attr.aria-expanded]": "open() ? \"true\" : \"false\"",
335
+ "[attr.aria-controls]": "contentId()",
336
+ "[attr.aria-disabled]": "effectiveDisabled() ? \"true\" : null",
337
+ "(click)": "onClick()"
338
+ }
339
+ }]
340
+ }],
341
+ ctorParameters: () => []
342
+ });
343
+ var RaqmAccordionContentComponent = class RaqmAccordionContentComponent {
344
+ item = inject(RAQM_ACCORDION_ITEM, { optional: true });
345
+ open = computed(() => this.item?.open() ?? true, ...ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []);
346
+ contentId = computed(() => this.item?.contentId ?? null, ...ngDevMode ? [{ debugName: "contentId" }] : /* istanbul ignore next */ []);
347
+ triggerId = computed(() => this.item?.triggerId ?? null, ...ngDevMode ? [{ debugName: "triggerId" }] : /* istanbul ignore next */ []);
348
+ constructor() {
349
+ if (isDevMode() && this.item === null) console.error("[raqm-accordion-content] No parent <raqm-accordion-item> found; the content cannot know its open state.");
350
+ }
351
+ static ɵfac = i0.ɵɵngDeclareFactory({
352
+ minVersion: "12.0.0",
353
+ version: "22.2.2",
354
+ ngImport: i0,
355
+ type: RaqmAccordionContentComponent,
356
+ deps: [],
357
+ target: i0.ɵɵFactoryTarget.Component
358
+ });
359
+ static ɵcmp = i0.ɵɵngDeclareComponent({
360
+ minVersion: "14.0.0",
361
+ version: "22.2.2",
362
+ type: RaqmAccordionContentComponent,
363
+ isStandalone: true,
364
+ selector: "raqm-accordion-content",
365
+ host: {
366
+ attributes: { "role": "region" },
367
+ properties: {
368
+ "attr.id": "contentId()",
369
+ "attr.aria-labelledby": "triggerId()",
370
+ "attr.data-raqm-state": "open() ? \"open\" : \"closed\"",
371
+ "attr.inert": "open() ? null : \"\""
372
+ },
373
+ classAttribute: "raqm-accordion-content"
374
+ },
375
+ ngImport: i0,
376
+ template: "<div class=\"raqm-accordion-content-inner\"><ng-content /></div>",
377
+ isInline: true,
378
+ styles: [":host{display:grid;grid-template-rows:0fr;overflow:hidden;font-size:var(--raqm-font-size-sm);line-height:calc(var(--raqm-spacing) * 5);transition:grid-template-rows var(--raqm-duration-slow) var(--raqm-ease-out)}:host([data-raqm-state=open]){grid-template-rows:1fr}.raqm-accordion-content-inner{min-block-size:0;overflow:hidden}.raqm-accordion-content-inner:after{content:\"\";display:block;block-size:calc(var(--raqm-spacing) * 2.5)}\n"],
379
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
380
+ });
381
+ };
382
+ i0.ɵɵngDeclareClassMetadata({
383
+ minVersion: "12.0.0",
384
+ version: "22.2.2",
385
+ ngImport: i0,
386
+ type: RaqmAccordionContentComponent,
387
+ decorators: [{
388
+ type: Component,
389
+ args: [{
390
+ selector: "raqm-accordion-content",
391
+ template: "<div class=\"raqm-accordion-content-inner\"><ng-content /></div>",
392
+ changeDetection: ChangeDetectionStrategy.OnPush,
393
+ host: {
394
+ class: "raqm-accordion-content",
395
+ role: "region",
396
+ "[attr.id]": "contentId()",
397
+ "[attr.aria-labelledby]": "triggerId()",
398
+ "[attr.data-raqm-state]": "open() ? \"open\" : \"closed\"",
399
+ "[attr.inert]": "open() ? null : \"\""
400
+ },
401
+ styles: [":host{display:grid;grid-template-rows:0fr;overflow:hidden;font-size:var(--raqm-font-size-sm);line-height:calc(var(--raqm-spacing) * 5);transition:grid-template-rows var(--raqm-duration-slow) var(--raqm-ease-out)}:host([data-raqm-state=open]){grid-template-rows:1fr}.raqm-accordion-content-inner{min-block-size:0;overflow:hidden}.raqm-accordion-content-inner:after{content:\"\";display:block;block-size:calc(var(--raqm-spacing) * 2.5)}\n"]
402
+ }]
403
+ }],
404
+ ctorParameters: () => []
405
+ });
406
+ const RaqmAccordion = [
407
+ RaqmAccordionComponent,
408
+ RaqmAccordionItemComponent,
409
+ RaqmAccordionTriggerDirective,
410
+ RaqmAccordionContentComponent
411
+ ];
412
+ export { RaqmAccordion, RaqmAccordionComponent, RaqmAccordionContentComponent, RaqmAccordionItemComponent, RaqmAccordionTriggerDirective };
413
+
414
+ //# sourceMappingURL=raqm-ui-accordion.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raqm-ui-accordion.mjs","names":[],"sources":["../../../projects/ui/accordion/accordion.ts","../../../projects/ui/accordion/public-api.ts"],"sourcesContent":["import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n DestroyRef,\r\n Directive,\r\n OnInit,\r\n InjectionToken,\r\n Signal,\r\n booleanAttribute,\r\n computed,\r\n inject,\r\n input,\r\n isDevMode,\r\n model,\r\n signal,\r\n} from '@angular/core';\r\n\r\nexport interface RaqmAccordionItemRef {\r\n /** Unique, non-empty item value used by the root's open-state contract. */\r\n readonly value: string;\r\n}\r\n\r\n/** Root contract published under {@link RAQM_ACCORDION}; the dedicated token avoids a runtime module cycle. */\r\nexport interface RaqmAccordionContext {\r\n readonly multiple: Signal<boolean>;\r\n readonly disabled: Signal<boolean>;\r\n isOpen(value: string): boolean;\r\n /** Applies the root's open-state rules to an activated value (no-op if disabled). */\r\n toggle(value: string): void;\r\n register(item: RaqmAccordionItemRef): void;\r\n unregister(item: RaqmAccordionItemRef): void;\r\n}\r\n\r\n/** Item contract; the item owns both ids so the trigger/content ARIA pair cannot drift. */\r\nexport interface RaqmAccordionItemContext {\r\n readonly open: Signal<boolean>;\r\n readonly effectiveDisabled: Signal<boolean>;\r\n readonly triggerId: string;\r\n readonly contentId: string;\r\n toggle(): void;\r\n}\r\n\r\n/** Root token; injected optionally so a misplaced item renders and only logs a dev-mode error. */\r\nexport const RAQM_ACCORDION = new InjectionToken<RaqmAccordionContext>('RaqmAccordion');\r\n\r\n/** Item token; optional so a misplaced part renders and only logs a dev-mode error. */\r\nexport const RAQM_ACCORDION_ITEM = new InjectionToken<RaqmAccordionItemContext>(\r\n 'RaqmAccordionItem',\r\n);\r\n\r\n/** Accordion root; carries no ARIA role (each trigger owns the heading) and keeps at most one open value in single mode. */\r\n@Component({\r\n selector: 'raqm-accordion',\r\n template: '<ng-content />',\r\n styles: [\r\n `\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n inline-size: 100%;\r\n }\r\n `,\r\n ],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n class: 'raqm-accordion',\r\n },\r\n providers: [{ provide: RAQM_ACCORDION, useExisting: RaqmAccordionComponent }],\r\n})\r\nexport class RaqmAccordionComponent implements RaqmAccordionContext {\r\n readonly multiple = input(false, { transform: booleanAttribute });\r\n\r\n readonly value = model<readonly string[]>([]);\r\n\r\n // Uncontrolled seed, read only while the model is empty and the user has not interacted.\r\n readonly defaultValue = input<readonly string[]>([]);\r\n\r\n readonly disabled = input(false, { transform: booleanAttribute });\r\n\r\n // Registered in DOM order; a signal so the dev-only duplicate check sees dynamic additions.\r\n private readonly items = signal<readonly RaqmAccordionItemRef[]>([]);\r\n\r\n // Empty model means the seed until the first toggle; afterwards it means \"all closed\".\r\n private readonly interacted = signal(false);\r\n\r\n // Effective open values: bound model, else the seed. Single mode keeps one entry without coercing the model.\r\n private readonly openValues = computed<readonly string[]>(() => {\r\n const bound = this.value();\r\n if (bound.length > 0 || this.interacted()) {\r\n return bound;\r\n }\r\n const seed = this.defaultValue();\r\n return this.multiple() ? seed : seed.slice(0, 1);\r\n });\r\n\r\n /** Whether the given value is currently expanded; single mode reads only the first entry. */\r\n isOpen(value: string): boolean {\r\n const current = this.openValues();\r\n return this.multiple() ? current.includes(value) : current[0] === value;\r\n }\r\n\r\n toggle(value: string): void {\r\n if (this.disabled()) {\r\n return;\r\n }\r\n const current = this.openValues();\r\n this.interacted.set(true);\r\n if (this.multiple()) {\r\n this.value.set(\r\n current.includes(value) ? current.filter((open) => open !== value) : [...current, value],\r\n );\r\n return;\r\n }\r\n this.value.set(current[0] === value ? [] : [value]);\r\n }\r\n\r\n /** Registers in DOM order; reads the bound `value`, so items must register from `ngOnInit`. */\r\n register(item: RaqmAccordionItemRef): void {\r\n if (isDevMode() && this.items().some((registered) => registered.value === item.value)) {\r\n console.error(\r\n `[raqm-accordion] Duplicate item value \"${item.value}\"; Accordion item values must be unique.`,\r\n );\r\n }\r\n this.items.update((items) => [...items, item]);\r\n }\r\n\r\n /** Unregisters an item on destroy; never changes the open state. */\r\n unregister(item: RaqmAccordionItemRef): void {\r\n this.items.update((items) => items.filter((registered) => registered !== item));\r\n }\r\n}\r\n\r\n// Monotonic counter for stable per-item element ids.\r\nlet nextAccordionItemId = 0;\r\n\r\n/** Accordion item; owns both element ids and registers from `ngOnInit` so the duplicate check sees the bound `value`. */\r\n@Component({\r\n selector: 'raqm-accordion-item',\r\n template: '<ng-content />',\r\n styles: [\r\n `\r\n :host {\r\n display: block;\r\n }\r\n\r\n :host(:not(:last-child)) {\r\n border-block-end: 1px solid var(--raqm-border);\r\n }\r\n `,\r\n ],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n class: 'raqm-accordion-item',\r\n // Open/closed hook driving the shipped content animation.\r\n '[attr.data-raqm-state]': 'open() ? \"open\" : \"closed\"',\r\n // Presence-only hook; the native button carries the real disabled state.\r\n '[attr.data-raqm-disabled]': 'effectiveDisabled() ? \"\" : null',\r\n },\r\n providers: [{ provide: RAQM_ACCORDION_ITEM, useExisting: RaqmAccordionItemComponent }],\r\n})\r\nexport class RaqmAccordionItemComponent implements RaqmAccordionItemContext, OnInit {\r\n private readonly accordion = inject<RaqmAccordionContext | null>(RAQM_ACCORDION, {\r\n optional: true,\r\n });\r\n\r\n private readonly destroyRef = inject(DestroyRef);\r\n\r\n readonly value = input.required<string>();\r\n\r\n readonly disabled = input(false, { transform: booleanAttribute });\r\n\r\n private readonly instanceId = `raqm-accordion-item-${++nextAccordionItemId}`;\r\n\r\n readonly triggerId = `${this.instanceId}-trigger`;\r\n\r\n readonly contentId = `${this.instanceId}-content`;\r\n\r\n readonly effectiveDisabled = computed(\r\n () => this.disabled() || (this.accordion?.disabled() ?? false),\r\n );\r\n\r\n readonly open = computed(() => this.accordion?.isOpen(this.value()) ?? false);\r\n\r\n // Reads the live input, so registration always sees the bound value.\r\n private readonly ref: RaqmAccordionItemRef = (() => {\r\n const self = this;\r\n return {\r\n get value(): string {\r\n return self.value();\r\n },\r\n };\r\n })();\r\n\r\n constructor() {\r\n if (isDevMode() && this.accordion === null) {\r\n console.error(\r\n '[raqm-accordion-item] No parent <raqm-accordion> found; the item has no open state.',\r\n );\r\n }\r\n\r\n // Unregisters on destroy; registration deliberately lives in `ngOnInit`, never here.\r\n this.destroyRef.onDestroy(() => this.accordion?.unregister(this.ref));\r\n }\r\n\r\n /** Registers the item with its parent root once its required `value` input is bound. */\r\n ngOnInit(): void {\r\n this.accordion?.register(this.ref);\r\n }\r\n\r\n toggle(): void {\r\n if (this.effectiveDisabled()) {\r\n return;\r\n }\r\n this.accordion?.toggle(this.value());\r\n }\r\n}\r\n\r\n/** Viewless directive on the real `<button>`, the only activation path; disabled triggers stay focusable via `aria-disabled`. */\r\n@Directive({\r\n selector: 'button[raqm-accordion-trigger]',\r\n host: {\r\n class: 'raqm-accordion-trigger',\r\n // A disclosure button never submits a form.\r\n type: 'button',\r\n '[attr.id]': 'triggerId()',\r\n '[attr.aria-expanded]': 'open() ? \"true\" : \"false\"',\r\n '[attr.aria-controls]': 'contentId()',\r\n // Kept focusable while disabled, advertising the state instead.\r\n '[attr.aria-disabled]': 'effectiveDisabled() ? \"true\" : null',\r\n '(click)': 'onClick()',\r\n },\r\n})\r\nexport class RaqmAccordionTriggerDirective {\r\n private readonly item = inject<RaqmAccordionItemContext | null>(RAQM_ACCORDION_ITEM, {\r\n optional: true,\r\n });\r\n\r\n protected readonly open = computed(() => this.item?.open() ?? false);\r\n\r\n protected readonly effectiveDisabled = computed(() => this.item?.effectiveDisabled() ?? false);\r\n\r\n protected readonly triggerId = computed(() => this.item?.triggerId ?? null);\r\n\r\n protected readonly contentId = computed(() => this.item?.contentId ?? null);\r\n\r\n constructor() {\r\n if (isDevMode() && this.item === null) {\r\n console.error(\r\n '[raqm-accordion-trigger] No parent <raqm-accordion-item> found; the trigger cannot toggle a panel.',\r\n );\r\n }\r\n }\r\n\r\n protected onClick(): void {\r\n if (!this.effectiveDisabled()) {\r\n this.item?.toggle();\r\n }\r\n }\r\n}\r\n\r\n/** `role=\"region\"` paired with its trigger by owned ids; stays mounted, animates by grid row, and is `inert` while closed. */\r\n@Component({\r\n selector: 'raqm-accordion-content',\r\n template: '<div class=\"raqm-accordion-content-inner\"><ng-content /></div>',\r\n styleUrl: './accordion-content.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n class: 'raqm-accordion-content',\r\n role: 'region',\r\n '[attr.id]': 'contentId()',\r\n '[attr.aria-labelledby]': 'triggerId()',\r\n // Open/closed hook driving the shipped grid animation.\r\n '[attr.data-raqm-state]': 'open() ? \"open\" : \"closed\"',\r\n // A closed region is inert, so its content is unreachable while collapsed.\r\n '[attr.inert]': 'open() ? null : \"\"',\r\n },\r\n})\r\nexport class RaqmAccordionContentComponent {\r\n private readonly item = inject<RaqmAccordionItemContext | null>(RAQM_ACCORDION_ITEM, {\r\n optional: true,\r\n });\r\n\r\n protected readonly open = computed(() => this.item?.open() ?? true);\r\n\r\n protected readonly contentId = computed(() => this.item?.contentId ?? null);\r\n\r\n protected readonly triggerId = computed(() => this.item?.triggerId ?? null);\r\n\r\n constructor() {\r\n if (isDevMode() && this.item === null) {\r\n console.error(\r\n '[raqm-accordion-content] No parent <raqm-accordion-item> found; the content cannot know its open state.',\r\n );\r\n }\r\n }\r\n}\r\n","// Public API for the `@raqm/ui/accordion` secondary entry point; also re-exported by the root.\r\nimport {\r\n RaqmAccordionComponent,\r\n RaqmAccordionContentComponent,\r\n RaqmAccordionItemComponent,\r\n RaqmAccordionTriggerDirective,\r\n} from './accordion';\r\n\r\nexport {\r\n RaqmAccordionComponent,\r\n RaqmAccordionContentComponent,\r\n RaqmAccordionItemComponent,\r\n RaqmAccordionTriggerDirective,\r\n};\r\n\r\n// A nested readonly array is accepted by Angular `imports`, so the whole family imports as one entry.\r\nexport const RaqmAccordion = [\r\n RaqmAccordionComponent,\r\n RaqmAccordionItemComponent,\r\n RaqmAccordionTriggerDirective,\r\n RaqmAccordionContentComponent,\r\n] as const;\r\n"],"mappings":"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"}