agnosticui-core 2.0.0-alpha.2 → 2.0.0-alpha.21

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 (249) hide show
  1. package/README.md +67 -33
  2. package/dist/{VueButton.vue_vue_type_script_setup_true_lang-Bq8IPXqd.js → VueButton.vue_vue_type_script_setup_true_lang-D1jGatE9.js} +17 -15
  3. package/dist/{VueButtonFx.vue_vue_type_script_setup_true_lang-BUudF-lg.js → VueButtonFx.vue_vue_type_script_setup_true_lang-BRrt6Nxs.js} +1 -0
  4. package/dist/{VueCheckbox.vue_vue_type_script_setup_true_lang-DERDRO2P.js → VueCheckbox.vue_vue_type_script_setup_true_lang-VtQfJ-6f.js} +9 -10
  5. package/dist/{VueCombobox.vue_vue_type_script_setup_true_lang-C7gDMrYJ.js → VueCombobox.vue_vue_type_script_setup_true_lang-BSTZGX2X.js} +15 -13
  6. package/dist/VueIcon.vue_vue_type_script_setup_true_lang-C2Sky3bU.js +22 -0
  7. package/dist/{VueImage.vue_vue_type_script_setup_true_lang-CUwbK3NF.js → VueImage.vue_vue_type_script_setup_true_lang-SddK93SB.js} +23 -17
  8. package/dist/{VueInput.vue_vue_type_script_setup_true_lang-Dsxo7DuX.js → VueInput.vue_vue_type_script_setup_true_lang-wYdAqg-i.js} +19 -19
  9. package/dist/{VueMenu.vue_vue_type_script_setup_true_lang-bnn7ochj.js → VueMenu.vue_vue_type_script_setup_true_lang-BXc7397e.js} +5 -4
  10. package/dist/{VueRadio.vue_vue_type_script_setup_true_lang-DxNhH12d.js → VueRadio.vue_vue_type_script_setup_true_lang-C7Z-sWpa.js} +10 -12
  11. package/dist/{VueRating.vue_vue_type_script_setup_true_lang-CICncp71.js → VueRating.vue_vue_type_script_setup_true_lang-Bm2nRrqr.js} +11 -9
  12. package/dist/VueSelectionButton.vue_vue_type_script_setup_true_lang-DJN-Uk6n.js +24 -0
  13. package/dist/VueSelectionButtonGroup.vue_vue_type_script_setup_true_lang-DwYrIMVO.js +46 -0
  14. package/dist/VueSelectionCard.vue_vue_type_script_setup_true_lang-DJiyPsXH.js +24 -0
  15. package/dist/VueSelectionCardGroup.vue_vue_type_script_setup_true_lang-D5CycLY5.js +40 -0
  16. package/dist/{VueToggle.vue_vue_type_script_setup_true_lang-BxrvAsse.js → VueToggle.vue_vue_type_script_setup_true_lang-DLPCBOqZ.js} +18 -16
  17. package/dist/components/Alert/core/_Alert.d.ts.map +1 -1
  18. package/dist/components/Alert/core/_Alert.js +38 -19
  19. package/dist/components/Button/core/_Button.d.ts +5 -0
  20. package/dist/components/Button/core/_Button.d.ts.map +1 -1
  21. package/dist/components/Button/core/_Button.js +147 -65
  22. package/dist/components/Button/vue/VueButton.js +1 -1
  23. package/dist/components/Button/vue/VueButton.vue.d.ts +3 -0
  24. package/dist/components/Button/vue/VueButton.vue.d.ts.map +1 -1
  25. package/dist/components/Button/vue/index.js +1 -1
  26. package/dist/components/ButtonFx/vue/VueButtonFx.js +1 -1
  27. package/dist/components/ButtonFx/vue/index.js +1 -1
  28. package/dist/components/Card/core/_Card.d.ts +9 -1
  29. package/dist/components/Card/core/_Card.d.ts.map +1 -1
  30. package/dist/components/Card/core/_Card.js +83 -29
  31. package/dist/components/Card/vue/VueCard.js +29 -16
  32. package/dist/components/Card/vue/VueCard.vue.d.ts +25 -5
  33. package/dist/components/Card/vue/VueCard.vue.d.ts.map +1 -1
  34. package/dist/components/Checkbox/core/_Checkbox.d.ts +37 -11
  35. package/dist/components/Checkbox/core/_Checkbox.d.ts.map +1 -1
  36. package/dist/components/Checkbox/core/_Checkbox.js +73 -42
  37. package/dist/components/Checkbox/vue/VueCheckbox.js +1 -1
  38. package/dist/components/Checkbox/vue/VueCheckbox.vue.d.ts +3 -3
  39. package/dist/components/Checkbox/vue/VueCheckbox.vue.d.ts.map +1 -1
  40. package/dist/components/Checkbox/vue/index.js +1 -1
  41. package/dist/components/Combobox/core/_Combobox.d.ts +24 -1
  42. package/dist/components/Combobox/core/_Combobox.d.ts.map +1 -1
  43. package/dist/components/Combobox/core/_Combobox.js +141 -92
  44. package/dist/components/Combobox/vue/VueCombobox.js +1 -1
  45. package/dist/components/Combobox/vue/index.js +1 -1
  46. package/dist/components/Fieldset/vue/VueFieldset.vue.d.ts +1 -1
  47. package/dist/components/Icon/vue/VueIcon.js +1 -1
  48. package/dist/components/Icon/vue/VueIcon.vue.d.ts.map +1 -1
  49. package/dist/components/Icon/vue/index.js +1 -1
  50. package/dist/components/Image/vue/VueImage.js +1 -1
  51. package/dist/components/Image/vue/VueImage.vue.d.ts.map +1 -1
  52. package/dist/components/Image/vue/index.js +1 -1
  53. package/dist/components/Input/core/_Input.d.ts +21 -2
  54. package/dist/components/Input/core/_Input.d.ts.map +1 -1
  55. package/dist/components/Input/core/_Input.js +71 -35
  56. package/dist/components/Input/vue/VueInput.js +1 -1
  57. package/dist/components/Input/vue/VueInput.vue.d.ts.map +1 -1
  58. package/dist/components/Input/vue/index.js +1 -1
  59. package/dist/components/Link/core/_Link.d.ts.map +1 -1
  60. package/dist/components/Link/core/_Link.js +1 -0
  61. package/dist/components/Link/vue/VueLink.js +6 -5
  62. package/dist/components/Link/vue/VueLink.vue.d.ts.map +1 -1
  63. package/dist/components/Menu/vue/VueMenu.js +1 -1
  64. package/dist/components/Menu/vue/index.js +1 -1
  65. package/dist/components/Pagination/core/_Pagination.d.ts +0 -1
  66. package/dist/components/Pagination/core/_Pagination.d.ts.map +1 -1
  67. package/dist/components/Pagination/core/_Pagination.js +6 -9
  68. package/dist/components/Radio/core/_Radio.d.ts +55 -10
  69. package/dist/components/Radio/core/_Radio.d.ts.map +1 -1
  70. package/dist/components/Radio/core/_Radio.js +165 -116
  71. package/dist/components/Radio/vue/VueRadio.js +1 -1
  72. package/dist/components/Radio/vue/VueRadio.vue.d.ts.map +1 -1
  73. package/dist/components/Radio/vue/index.js +1 -1
  74. package/dist/components/Rating/core/_Rating.d.ts +23 -2
  75. package/dist/components/Rating/core/_Rating.d.ts.map +1 -1
  76. package/dist/components/Rating/core/_Rating.js +97 -64
  77. package/dist/components/Rating/vue/VueRating.js +1 -1
  78. package/dist/components/Rating/vue/VueRating.vue.d.ts +2 -0
  79. package/dist/components/Rating/vue/VueRating.vue.d.ts.map +1 -1
  80. package/dist/components/Rating/vue/index.js +1 -1
  81. package/dist/components/Select/core/_Select.d.ts +20 -2
  82. package/dist/components/Select/core/_Select.d.ts.map +1 -1
  83. package/dist/components/Select/core/_Select.js +99 -69
  84. package/dist/components/SelectionButton/core/SelectionButton.d.ts +9 -0
  85. package/dist/components/SelectionButton/core/SelectionButton.d.ts.map +1 -0
  86. package/dist/components/SelectionButton/core/SelectionButton.js +5 -0
  87. package/dist/components/SelectionButton/core/_SelectionButton.d.ts +47 -0
  88. package/dist/components/SelectionButton/core/_SelectionButton.d.ts.map +1 -0
  89. package/dist/components/SelectionButton/core/_SelectionButton.js +474 -0
  90. package/dist/components/SelectionButton/react/ReactSelectionButton.d.ts +9 -0
  91. package/dist/components/SelectionButton/react/ReactSelectionButton.d.ts.map +1 -0
  92. package/dist/components/SelectionButton/react/ReactSelectionButton.js +12 -0
  93. package/dist/components/SelectionButton/react/index.d.ts +3 -0
  94. package/dist/components/SelectionButton/react/index.d.ts.map +1 -0
  95. package/dist/components/SelectionButton/react/index.js +4 -0
  96. package/dist/components/SelectionButton/vue/VueSelectionButton.js +4 -0
  97. package/dist/components/SelectionButton/vue/VueSelectionButton.vue.d.ts +55 -0
  98. package/dist/components/SelectionButton/vue/VueSelectionButton.vue.d.ts.map +1 -0
  99. package/dist/components/SelectionButton/vue/index.d.ts +6 -0
  100. package/dist/components/SelectionButton/vue/index.d.ts.map +1 -0
  101. package/dist/components/SelectionButton/vue/index.js +4 -0
  102. package/dist/components/SelectionButtonGroup/core/SelectionButtonGroup.d.ts +9 -0
  103. package/dist/components/SelectionButtonGroup/core/SelectionButtonGroup.d.ts.map +1 -0
  104. package/dist/components/SelectionButtonGroup/core/SelectionButtonGroup.js +5 -0
  105. package/dist/components/SelectionButtonGroup/core/_SelectionButtonGroup.d.ts +87 -0
  106. package/dist/components/SelectionButtonGroup/core/_SelectionButtonGroup.d.ts.map +1 -0
  107. package/dist/components/SelectionButtonGroup/core/_SelectionButtonGroup.js +235 -0
  108. package/dist/components/SelectionButtonGroup/react/ReactSelectionButtonGroup.d.ts +13 -0
  109. package/dist/components/SelectionButtonGroup/react/ReactSelectionButtonGroup.d.ts.map +1 -0
  110. package/dist/components/SelectionButtonGroup/react/ReactSelectionButtonGroup.js +15 -0
  111. package/dist/components/SelectionButtonGroup/react/index.d.ts +3 -0
  112. package/dist/components/SelectionButtonGroup/react/index.d.ts.map +1 -0
  113. package/dist/components/SelectionButtonGroup/react/index.js +4 -0
  114. package/dist/components/SelectionButtonGroup/vue/VueSelectionButtonGroup.js +4 -0
  115. package/dist/components/SelectionButtonGroup/vue/VueSelectionButtonGroup.vue.d.ts +101 -0
  116. package/dist/components/SelectionButtonGroup/vue/VueSelectionButtonGroup.vue.d.ts.map +1 -0
  117. package/dist/components/SelectionButtonGroup/vue/index.d.ts +6 -0
  118. package/dist/components/SelectionButtonGroup/vue/index.d.ts.map +1 -0
  119. package/dist/components/SelectionButtonGroup/vue/index.js +4 -0
  120. package/dist/components/SelectionCard/core/SelectionCard.d.ts +9 -0
  121. package/dist/components/SelectionCard/core/SelectionCard.d.ts.map +1 -0
  122. package/dist/components/SelectionCard/core/SelectionCard.js +5 -0
  123. package/dist/components/SelectionCard/core/_SelectionCard.d.ts +39 -0
  124. package/dist/components/SelectionCard/core/_SelectionCard.d.ts.map +1 -0
  125. package/dist/components/SelectionCard/core/_SelectionCard.js +318 -0
  126. package/dist/components/SelectionCard/react/ReactSelectionCard.d.ts +9 -0
  127. package/dist/components/SelectionCard/react/ReactSelectionCard.d.ts.map +1 -0
  128. package/dist/components/SelectionCard/react/ReactSelectionCard.js +12 -0
  129. package/dist/components/SelectionCard/react/index.d.ts +3 -0
  130. package/dist/components/SelectionCard/react/index.d.ts.map +1 -0
  131. package/dist/components/SelectionCard/react/index.js +4 -0
  132. package/dist/components/SelectionCard/vue/VueSelectionCard.js +4 -0
  133. package/dist/components/SelectionCard/vue/VueSelectionCard.vue.d.ts +55 -0
  134. package/dist/components/SelectionCard/vue/VueSelectionCard.vue.d.ts.map +1 -0
  135. package/dist/components/SelectionCard/vue/index.d.ts +6 -0
  136. package/dist/components/SelectionCard/vue/index.d.ts.map +1 -0
  137. package/dist/components/SelectionCard/vue/index.js +4 -0
  138. package/dist/components/SelectionCardGroup/core/SelectionCardGroup.d.ts +9 -0
  139. package/dist/components/SelectionCardGroup/core/SelectionCardGroup.d.ts.map +1 -0
  140. package/dist/components/SelectionCardGroup/core/SelectionCardGroup.js +5 -0
  141. package/dist/components/SelectionCardGroup/core/_SelectionCardGroup.d.ts +69 -0
  142. package/dist/components/SelectionCardGroup/core/_SelectionCardGroup.d.ts.map +1 -0
  143. package/dist/components/SelectionCardGroup/core/_SelectionCardGroup.js +220 -0
  144. package/dist/components/SelectionCardGroup/react/ReactSelectionCardGroup.d.ts +13 -0
  145. package/dist/components/SelectionCardGroup/react/ReactSelectionCardGroup.d.ts.map +1 -0
  146. package/dist/components/SelectionCardGroup/react/ReactSelectionCardGroup.js +15 -0
  147. package/dist/components/SelectionCardGroup/react/index.d.ts +3 -0
  148. package/dist/components/SelectionCardGroup/react/index.d.ts.map +1 -0
  149. package/dist/components/SelectionCardGroup/react/index.js +4 -0
  150. package/dist/components/SelectionCardGroup/vue/VueSelectionCardGroup.js +4 -0
  151. package/dist/components/SelectionCardGroup/vue/VueSelectionCardGroup.vue.d.ts +86 -0
  152. package/dist/components/SelectionCardGroup/vue/VueSelectionCardGroup.vue.d.ts.map +1 -0
  153. package/dist/components/SelectionCardGroup/vue/index.d.ts +6 -0
  154. package/dist/components/SelectionCardGroup/vue/index.d.ts.map +1 -0
  155. package/dist/components/SelectionCardGroup/vue/index.js +4 -0
  156. package/dist/components/Slider/core/_Slider.d.ts +10 -16
  157. package/dist/components/Slider/core/_Slider.d.ts.map +1 -1
  158. package/dist/components/Slider/core/_Slider.js +28 -39
  159. package/dist/components/Timeline/core/_Timeline.d.ts.map +1 -1
  160. package/dist/components/Timeline/core/_Timeline.js +8 -3
  161. package/dist/components/Timeline/react/ReactTimeline.d.ts +23 -9
  162. package/dist/components/Timeline/react/ReactTimeline.d.ts.map +1 -1
  163. package/dist/components/Timeline/react/ReactTimeline.js +18 -14
  164. package/dist/components/Toggle/core/_Toggle.d.ts +36 -6
  165. package/dist/components/Toggle/core/_Toggle.d.ts.map +1 -1
  166. package/dist/components/Toggle/core/_Toggle.js +117 -77
  167. package/dist/components/Toggle/vue/VueToggle.js +1 -1
  168. package/dist/components/Toggle/vue/VueToggle.vue.d.ts.map +1 -1
  169. package/dist/components/Toggle/vue/index.js +1 -1
  170. package/dist/shared/face-mixin.d.ts +82 -0
  171. package/dist/shared/face-mixin.d.ts.map +1 -0
  172. package/dist/shared/face-mixin.js +86 -0
  173. package/dist/shared/form-control-styles.js +1 -1
  174. package/dist/styles/ag-tokens-dark.css +4 -0
  175. package/dist/styles/ag-tokens.css +18 -13
  176. package/dist/test-setup.js +340 -255
  177. package/package.json +51 -13
  178. package/src/components/Alert/core/_Alert.ts +21 -2
  179. package/src/components/Button/core/_Button.ts +111 -21
  180. package/src/components/Button/vue/VueButton.vue +2 -0
  181. package/src/components/Card/core/_Card.ts +70 -3
  182. package/src/components/Card/vue/VueCard.vue +19 -3
  183. package/src/components/Checkbox/core/_Checkbox.ts +78 -18
  184. package/src/components/Checkbox/vue/VueCheckbox.vue +0 -6
  185. package/src/components/Combobox/core/_Combobox.ts +84 -2
  186. package/src/components/Combobox/vue/VueCombobox.vue +1 -0
  187. package/src/components/Drawer/v1/dialog--drawer-bottom.hbs +48 -0
  188. package/src/components/Drawer/v1/dialog--drawer-end.hbs +48 -0
  189. package/src/components/Drawer/v1/dialog--drawer-start.hbs +48 -0
  190. package/src/components/Drawer/v1/dialog--drawer-top.hbs +48 -0
  191. package/src/components/Drawer/v1/dialog-demo.css +13 -0
  192. package/src/components/Drawer/v1/dialog.config.yml +5 -0
  193. package/src/components/Drawer/v1/dialog.css +99 -0
  194. package/src/components/Drawer/v1/dialog.hbs +48 -0
  195. package/src/components/Drawer/v1/drawer-animations.css +52 -0
  196. package/src/components/Drawer/v1/drawer.css +50 -0
  197. package/src/components/Icon/vue/VueIcon.vue +2 -5
  198. package/src/components/Image/vue/VueImage.vue +17 -13
  199. package/src/components/Input/core/_Input.ts +58 -3
  200. package/src/components/Input/vue/VueInput.vue +2 -6
  201. package/src/components/Link/core/_Link.ts +1 -0
  202. package/src/components/Link/vue/VueLink.vue +1 -0
  203. package/src/components/Pagination/core/_Pagination.ts +10 -18
  204. package/src/components/Radio/core/_Radio.ts +131 -41
  205. package/src/components/Radio/vue/VueRadio.vue +1 -5
  206. package/src/components/Rating/core/_Rating.ts +62 -5
  207. package/src/components/Rating/vue/VueRating.vue +3 -0
  208. package/src/components/Select/core/_Select.ts +55 -6
  209. package/src/components/SelectionButton/core/SelectionButton.ts +13 -0
  210. package/src/components/SelectionButton/core/_SelectionButton.ts +551 -0
  211. package/src/components/SelectionButton/react/ReactSelectionButton.tsx +16 -0
  212. package/src/components/SelectionButton/react/index.ts +4 -0
  213. package/src/components/SelectionButton/vue/VueSelectionButton.vue +33 -0
  214. package/src/components/SelectionButton/vue/index.ts +5 -0
  215. package/src/components/SelectionButtonGroup/core/SelectionButtonGroup.ts +13 -0
  216. package/src/components/SelectionButtonGroup/core/_SelectionButtonGroup.ts +423 -0
  217. package/src/components/SelectionButtonGroup/react/ReactSelectionButtonGroup.tsx +29 -0
  218. package/src/components/SelectionButtonGroup/react/index.ts +9 -0
  219. package/src/components/SelectionButtonGroup/vue/VueSelectionButtonGroup.vue +89 -0
  220. package/src/components/SelectionButtonGroup/vue/index.ts +5 -0
  221. package/src/components/SelectionCard/core/SelectionCard.ts +13 -0
  222. package/src/components/SelectionCard/core/_SelectionCard.ts +384 -0
  223. package/src/components/SelectionCard/react/ReactSelectionCard.tsx +16 -0
  224. package/src/components/SelectionCard/react/index.ts +4 -0
  225. package/src/components/SelectionCard/vue/VueSelectionCard.vue +33 -0
  226. package/src/components/SelectionCard/vue/index.ts +5 -0
  227. package/src/components/SelectionCardGroup/core/SelectionCardGroup.ts +13 -0
  228. package/src/components/SelectionCardGroup/core/_SelectionCardGroup.ts +396 -0
  229. package/src/components/SelectionCardGroup/react/ReactSelectionCardGroup.tsx +29 -0
  230. package/src/components/SelectionCardGroup/react/index.ts +9 -0
  231. package/src/components/SelectionCardGroup/vue/VueSelectionCardGroup.vue +71 -0
  232. package/src/components/SelectionCardGroup/vue/index.ts +5 -0
  233. package/src/components/Slider/core/_Slider.ts +28 -28
  234. package/src/components/Timeline/core/_Timeline.ts +5 -0
  235. package/src/components/Timeline/react/ReactTimeline.tsx +47 -24
  236. package/src/components/Toggle/core/_Toggle.ts +83 -9
  237. package/src/components/Toggle/vue/VueToggle.vue +2 -0
  238. package/src/shared/face-mixin.ts +233 -0
  239. package/src/shared/form-control-styles.ts +1 -1
  240. package/src/styles/ag-tokens-dark.css +4 -0
  241. package/src/styles/ag-tokens.css +18 -13
  242. package/RTL_IMPLEMENTATION_PLAN.md +0 -295
  243. package/dist/VueIcon.vue_vue_type_script_setup_true_lang-kC-nzMyu.js +0 -25
  244. package/dist/components/Input/core/_Input.BACKUP.d.ts +0 -114
  245. package/dist/components/Input/core/_Input.BACKUP.d.ts.map +0 -1
  246. package/dist/components/Input/core/_Input.BACKUP.js +0 -511
  247. package/dist/global.d.js +0 -1
  248. package/src/components/Input/core/_Input.BACKUP.ts +0 -710
  249. package/src/global.d.ts +0 -43
@@ -0,0 +1,396 @@
1
+ /**
2
+ * AgnosticUI v2 SelectionCardGroup - Core Implementation
3
+ *
4
+ * A container component that manages single (radio) or multiple (checkbox) selection
5
+ * using card-based UI. Provides keyboard navigation and accessibility features.
6
+ *
7
+ * @element ag-selection-card-group
8
+ * @slot - Default slot for ag-selection-card elements
9
+ * @csspart fieldset - The fieldset element
10
+ * @csspart legend - The legend element
11
+ * @csspart content - The content wrapper containing cards
12
+ */
13
+
14
+ import { LitElement, html, css, nothing } from 'lit';
15
+ import { property, state } from 'lit/decorators.js';
16
+ import type { AgSelectionCard } from '../../SelectionCard/core/_SelectionCard.js';
17
+ import { FaceMixin, type ValidationMessages } from '../../../shared/face-mixin';
18
+
19
+ export type SelectionType = 'radio' | 'checkbox';
20
+ export type SelectionCardGroupTheme = 'success' | 'info' | 'error' | 'warning' | 'monochrome' | '';
21
+
22
+ export interface SelectionChangeEventDetail {
23
+ /** The value of the card that triggered the change */
24
+ value: string;
25
+ /** Whether the card is now selected */
26
+ checked: boolean;
27
+ /** All currently selected values */
28
+ selectedValues: string[];
29
+ }
30
+
31
+ export type SelectionChangeEvent = CustomEvent<SelectionChangeEventDetail>;
32
+
33
+ export interface SelectionCardGroupProps {
34
+ /** Selection mode: 'radio' (single) or 'checkbox' (multiple) */
35
+ type: SelectionType;
36
+ /** Name attribute for the input elements */
37
+ name: string;
38
+ /** Legend text for the fieldset (accessibility) */
39
+ legend?: string;
40
+ /** Visually hide the legend while keeping it accessible */
41
+ legendHidden?: boolean;
42
+ /** Theme variant for cards */
43
+ theme?: SelectionCardGroupTheme;
44
+ /** Controlled value for radio mode */
45
+ value?: string;
46
+ /** Controlled values for checkbox mode */
47
+ values?: string[];
48
+ /** Disable all cards in the group */
49
+ disabled?: boolean;
50
+ /** Require at least one selection before the form can be submitted */
51
+ required?: boolean;
52
+ validationMessages?: ValidationMessages;
53
+ /** Callback for selection changes */
54
+ onSelectionChange?: (event: SelectionChangeEvent) => void;
55
+ }
56
+
57
+ export class AgSelectionCardGroup extends FaceMixin(LitElement) implements SelectionCardGroupProps {
58
+ static override styles = css`
59
+ :host {
60
+ display: block;
61
+ }
62
+
63
+ .selection-card-group {
64
+ border: 0;
65
+ padding: 0;
66
+ margin: 0;
67
+ min-inline-size: auto;
68
+ }
69
+
70
+ .selection-card-group__legend {
71
+ font-weight: 600;
72
+ font-size: var(--ag-font-size-base);
73
+ color: var(--ag-text-primary);
74
+ padding: 0;
75
+ margin-block-end: var(--ag-space-4);
76
+ }
77
+
78
+ .selection-card-group__legend--hidden {
79
+ position: absolute !important;
80
+ width: 1px !important;
81
+ height: 1px !important;
82
+ padding: 0 !important;
83
+ margin: -1px !important;
84
+ overflow: hidden !important;
85
+ clip: rect(0, 0, 0, 0) !important;
86
+ white-space: nowrap !important;
87
+ border: 0 !important;
88
+ }
89
+
90
+ .selection-card-group__content {
91
+ display: grid;
92
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
93
+ gap: var(--ag-selection-card-group-gap, var(--ag-space-4));
94
+ }
95
+ `;
96
+
97
+ @property({ type: String, reflect: true })
98
+ declare type: SelectionType;
99
+
100
+ @property({ type: String })
101
+ declare legend: string;
102
+
103
+ @property({ type: Boolean, attribute: 'legend-hidden' })
104
+ declare legendHidden: boolean;
105
+
106
+ @property({ type: String, reflect: true })
107
+ declare theme: SelectionCardGroupTheme;
108
+
109
+ @property({ type: String })
110
+ declare value: string;
111
+
112
+ @property({ type: Array })
113
+ declare values: string[];
114
+
115
+ @property({ type: Boolean, reflect: true })
116
+ declare disabled: boolean;
117
+
118
+ @property({ type: Boolean, reflect: true })
119
+ declare required: boolean;
120
+
121
+ @property({ attribute: false })
122
+ declare validationMessages: ValidationMessages | undefined;
123
+
124
+ @property({ attribute: false })
125
+ declare onSelectionChange: ((event: SelectionChangeEvent) => void) | undefined;
126
+
127
+ // Internal state for uncontrolled mode
128
+ @state()
129
+ declare _internalSelectedValues: string[];
130
+
131
+ constructor() {
132
+ super();
133
+ this.type = 'radio';
134
+ this.legend = '';
135
+ this.legendHidden = false;
136
+ this.theme = '';
137
+ this.value = '';
138
+ this.values = [];
139
+ this.disabled = false;
140
+ this.required = false;
141
+ this._internalSelectedValues = [];
142
+ this.validationMessages = undefined;
143
+ }
144
+
145
+ // Get current selected values (controlled or uncontrolled)
146
+ private _getSelectedValues(): string[] {
147
+ if (this.type === 'radio') {
148
+ // For radio: use controlled value if set, otherwise internal state
149
+ if (this.value) {
150
+ return [this.value];
151
+ }
152
+ return this._internalSelectedValues;
153
+ }
154
+ // For checkbox: use controlled values if set (non-empty), otherwise internal state
155
+ if (this.values && this.values.length > 0) {
156
+ return this.values;
157
+ }
158
+ return this._internalSelectedValues;
159
+ }
160
+
161
+ // ─── FACE ─────────────────────────────────────────────────────────────────
162
+
163
+ private _syncFormValue(): void {
164
+ const selected = this._getSelectedValues();
165
+ if (this.type === 'radio') {
166
+ this._internals.setFormValue(selected.length > 0 ? selected[0] : null);
167
+ } else {
168
+ if (selected.length === 0) {
169
+ this._internals.setFormValue(null);
170
+ } else {
171
+ const formData = new FormData();
172
+ selected.forEach(val => formData.append(this.name, val));
173
+ this._internals.setFormValue(formData);
174
+ }
175
+ }
176
+ }
177
+
178
+ private _syncValidity(): void {
179
+ const selected = this._getSelectedValues();
180
+ if (this.required && selected.length === 0) {
181
+ this._internals.setValidity(
182
+ { valueMissing: true },
183
+ this.validationMessages?.valueMissing ?? 'Please select an option.'
184
+ );
185
+ } else {
186
+ this._internals.setValidity({});
187
+ }
188
+ }
189
+
190
+ override formResetCallback(): void {
191
+ this._internalSelectedValues = [];
192
+ this._internals.setFormValue(null);
193
+ this._syncValidity();
194
+ this._syncChildCards();
195
+ }
196
+
197
+ // ─── End FACE ─────────────────────────────────────────────────────────────
198
+
199
+ override connectedCallback() {
200
+ super.connectedCallback();
201
+ this.addEventListener('selection-card-change', this._handleCardChange as EventListener);
202
+ this.addEventListener('keydown', this._handleKeyDown);
203
+ }
204
+
205
+ override disconnectedCallback() {
206
+ super.disconnectedCallback();
207
+ this.removeEventListener('selection-card-change', this._handleCardChange as EventListener);
208
+ this.removeEventListener('keydown', this._handleKeyDown);
209
+ }
210
+
211
+ override updated(changedProperties: Map<string, unknown>) {
212
+ super.updated(changedProperties);
213
+
214
+ // Sync props to child cards
215
+ if (
216
+ changedProperties.has('type') ||
217
+ changedProperties.has('name') ||
218
+ changedProperties.has('theme') ||
219
+ changedProperties.has('disabled') ||
220
+ changedProperties.has('value') ||
221
+ changedProperties.has('values') ||
222
+ changedProperties.has('_internalSelectedValues')
223
+ ) {
224
+ this._syncChildCards();
225
+ }
226
+
227
+ // FACE: sync for programmatic value/values changes
228
+ if (
229
+ changedProperties.has('value') ||
230
+ changedProperties.has('values') ||
231
+ changedProperties.has('_internalSelectedValues')
232
+ ) {
233
+ this._syncFormValue();
234
+ this._syncValidity();
235
+ } else if (changedProperties.has('required')) {
236
+ this._syncValidity();
237
+ }
238
+ }
239
+
240
+ override firstUpdated() {
241
+ this._syncChildCards();
242
+ this._syncFormValue();
243
+ this._syncValidity();
244
+ }
245
+
246
+ private _getCards(): AgSelectionCard[] {
247
+ const slot = this.shadowRoot?.querySelector('slot');
248
+ if (!slot) return [];
249
+
250
+ return slot
251
+ .assignedElements({ flatten: true })
252
+ .filter((el): el is AgSelectionCard => el.tagName.toLowerCase() === 'ag-selection-card');
253
+ }
254
+
255
+ private _syncChildCards() {
256
+ const cards = this._getCards();
257
+ const selectedValues = this._getSelectedValues();
258
+
259
+ cards.forEach((card) => {
260
+ card._type = this.type;
261
+ card._name = this.name;
262
+ card._theme = this.theme;
263
+ card.checked = selectedValues.includes(card.value);
264
+ if (this.disabled) {
265
+ card.disabled = true;
266
+ }
267
+ });
268
+ }
269
+
270
+ private _handleCardChange = (e: CustomEvent<{ value: string; checked: boolean }>) => {
271
+ e.stopPropagation();
272
+
273
+ const { value, checked } = e.detail;
274
+ let newSelectedValues: string[];
275
+
276
+ if (this.type === 'radio') {
277
+ // Radio: only one selected
278
+ newSelectedValues = checked ? [value] : [];
279
+ } else {
280
+ // Checkbox: toggle in list - use current selected values
281
+ const current = [...this._getSelectedValues()];
282
+ if (checked) {
283
+ if (!current.includes(value)) {
284
+ current.push(value);
285
+ }
286
+ } else {
287
+ const index = current.indexOf(value);
288
+ if (index > -1) {
289
+ current.splice(index, 1);
290
+ }
291
+ }
292
+ newSelectedValues = current;
293
+ }
294
+
295
+ // Update internal state (for uncontrolled mode)
296
+ this._internalSelectedValues = newSelectedValues;
297
+
298
+ // FACE: sync form value and validity on user interaction
299
+ this._syncFormValue();
300
+ this._syncValidity();
301
+
302
+ // Dispatch event
303
+ const changeEvent = new CustomEvent<SelectionChangeEventDetail>('selection-change', {
304
+ detail: {
305
+ value,
306
+ checked,
307
+ selectedValues: newSelectedValues,
308
+ },
309
+ bubbles: true,
310
+ composed: true,
311
+ });
312
+
313
+ this.dispatchEvent(changeEvent);
314
+
315
+ if (this.onSelectionChange) {
316
+ this.onSelectionChange(changeEvent);
317
+ }
318
+ };
319
+
320
+ private _handleKeyDown = (e: KeyboardEvent) => {
321
+ const cards = this._getCards().filter((card) => !card.disabled);
322
+ if (cards.length === 0) return;
323
+
324
+ // Find currently focused card (check shadowRoot for focus)
325
+ const focusedCard = cards.find(card => {
326
+ try {
327
+ return card.shadowRoot?.activeElement || card === document.activeElement;
328
+ } catch {
329
+ return card === document.activeElement;
330
+ }
331
+ });
332
+ const currentIndex = focusedCard ? cards.indexOf(focusedCard) : -1;
333
+
334
+ let nextIndex: number | null = null;
335
+
336
+ switch (e.key) {
337
+ case 'ArrowDown':
338
+ case 'ArrowRight':
339
+ e.preventDefault();
340
+ nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % cards.length;
341
+ break;
342
+ case 'ArrowUp':
343
+ case 'ArrowLeft':
344
+ e.preventDefault();
345
+ nextIndex = currentIndex === -1 ? cards.length - 1 : (currentIndex - 1 + cards.length) % cards.length;
346
+ break;
347
+ case 'Home':
348
+ e.preventDefault();
349
+ nextIndex = 0;
350
+ break;
351
+ case 'End':
352
+ e.preventDefault();
353
+ nextIndex = cards.length - 1;
354
+ break;
355
+ }
356
+
357
+ if (nextIndex !== null) {
358
+ const nextCard = cards[nextIndex];
359
+ nextCard.focus();
360
+
361
+ // For radio groups, arrow keys also select
362
+ if (this.type === 'radio') {
363
+ this._handleCardChange(new CustomEvent('selection-card-change', {
364
+ detail: { value: nextCard.value, checked: true },
365
+ }));
366
+ }
367
+ }
368
+ };
369
+
370
+ private _handleSlotChange() {
371
+ this._syncChildCards();
372
+ }
373
+
374
+ override render() {
375
+ const legendClasses = [
376
+ 'selection-card-group__legend',
377
+ this.legendHidden ? 'selection-card-group__legend--hidden' : '',
378
+ ].filter(Boolean).join(' ');
379
+
380
+ return html`
381
+ <fieldset
382
+ class="selection-card-group"
383
+ part="ag-selection-card-group-fieldset"
384
+ role="${this.type === 'radio' ? 'radiogroup' : 'group'}"
385
+ aria-disabled="${this.disabled ? 'true' : 'false'}"
386
+ >
387
+ ${this.legend
388
+ ? html`<legend class="${legendClasses}" part="ag-selection-card-group-legend">${this.legend}</legend>`
389
+ : nothing}
390
+ <div class="selection-card-group__content" part="ag-selection-card-group-content">
391
+ <slot @slotchange="${this._handleSlotChange}"></slot>
392
+ </div>
393
+ </fieldset>
394
+ `;
395
+ }
396
+ }
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ import { createComponent, type EventName } from '@lit/react';
3
+ import {
4
+ AgSelectionCardGroup,
5
+ type SelectionCardGroupProps,
6
+ type SelectionChangeEvent,
7
+ } from '../core/SelectionCardGroup';
8
+
9
+ export interface ReactSelectionCardGroupProps extends SelectionCardGroupProps {
10
+ children?: React.ReactNode;
11
+ className?: string;
12
+ onSelectionChange?: (event: SelectionChangeEvent) => void;
13
+ }
14
+
15
+ export const ReactSelectionCardGroup = createComponent({
16
+ tagName: 'ag-selection-card-group',
17
+ elementClass: AgSelectionCardGroup,
18
+ react: React,
19
+ events: {
20
+ onSelectionChange: 'selection-change' as EventName<SelectionChangeEvent>,
21
+ },
22
+ });
23
+
24
+ export type {
25
+ SelectionCardGroupProps,
26
+ SelectionChangeEvent,
27
+ SelectionChangeEventDetail,
28
+ SelectionType,
29
+ } from '../core/SelectionCardGroup';
@@ -0,0 +1,9 @@
1
+ export { ReactSelectionCardGroup, type ReactSelectionCardGroupProps } from './ReactSelectionCardGroup';
2
+
3
+ // Re-export types from core for convenience
4
+ export type {
5
+ SelectionCardGroupProps,
6
+ SelectionChangeEvent,
7
+ SelectionChangeEventDetail,
8
+ SelectionType,
9
+ } from '../core/SelectionCardGroup';
@@ -0,0 +1,71 @@
1
+ <template>
2
+ <ag-selection-card-group
3
+ :type="type"
4
+ :name="name"
5
+ :legend="legend"
6
+ :legend-hidden="legendHidden"
7
+ :value="value"
8
+ :values="values"
9
+ .disabled="disabled"
10
+ .required="required"
11
+ .validationMessages="validationMessages"
12
+ @selection-change="handleSelectionChange"
13
+ v-bind="$attrs"
14
+ >
15
+ <slot />
16
+ </ag-selection-card-group>
17
+ </template>
18
+
19
+ <script setup lang="ts">
20
+ import '../core/SelectionCardGroup';
21
+ import type { SelectionType, SelectionChangeEventDetail } from '../core/SelectionCardGroup';
22
+ import type { ValidationMessages } from '../../../shared/face-mixin';
23
+
24
+ export interface VueSelectionCardGroupProps {
25
+ /** Selection mode: 'radio' (single) or 'checkbox' (multiple) */
26
+ type?: SelectionType;
27
+ /** Name attribute for the input elements */
28
+ name: string;
29
+ /** Legend text for the fieldset (accessibility) */
30
+ legend?: string;
31
+ /** Visually hide the legend while keeping it accessible */
32
+ legendHidden?: boolean;
33
+ /** Controlled value for radio mode */
34
+ value?: string;
35
+ /** Controlled values for checkbox mode */
36
+ values?: string[];
37
+ /** Disable all cards in the group */
38
+ disabled?: boolean;
39
+ /** Require at least one selection before the form can be submitted */
40
+ required?: boolean;
41
+ validationMessages?: ValidationMessages;
42
+ }
43
+
44
+ withDefaults(defineProps<VueSelectionCardGroupProps>(), {
45
+ type: 'radio',
46
+ name: '',
47
+ legend: '',
48
+ legendHidden: false,
49
+ value: '',
50
+ values: () => [],
51
+ disabled: false,
52
+ required: false,
53
+ });
54
+
55
+ const emit = defineEmits<{
56
+ 'selection-change': [detail: SelectionChangeEventDetail];
57
+ 'update:value': [value: string];
58
+ 'update:values': [values: string[]];
59
+ }>();
60
+
61
+ const handleSelectionChange = (event: Event) => {
62
+ const detail = (event as CustomEvent<SelectionChangeEventDetail>).detail;
63
+ emit('selection-change', detail);
64
+ // Support v-model:value for radio
65
+ if (detail.selectedValues.length <= 1) {
66
+ emit('update:value', detail.selectedValues[0] || '');
67
+ }
68
+ // Support v-model:values for checkbox
69
+ emit('update:values', detail.selectedValues);
70
+ };
71
+ </script>
@@ -0,0 +1,5 @@
1
+ import VueSelectionCardGroup from './VueSelectionCardGroup.vue';
2
+ import type { SelectionCardGroupProps as VueSelectionCardGroupProps } from '../core/_SelectionCardGroup';
3
+
4
+ export { VueSelectionCardGroup };
5
+ export type { VueSelectionCardGroupProps };
@@ -17,6 +17,7 @@ import {
17
17
  type LabelPosition,
18
18
  } from '../../../shared/form-control-utils';
19
19
  import { formControlStyles } from '../../../shared/form-control-styles';
20
+ import { FaceMixin } from '../../../shared/face-mixin';
20
21
 
21
22
  // Props interface following INTERFACE_STANDARDS.md
22
23
  export interface SliderProps {
@@ -72,9 +73,8 @@ export interface SliderProps {
72
73
  /**
73
74
  * AgSlider - Foundation slider component with single/dual range support
74
75
  */
75
- export class AgSlider extends LitElement implements SliderProps {
76
- static formAssociated = true;
77
- static styles = [
76
+ export class AgSlider extends FaceMixin(LitElement) implements SliderProps {
77
+ static override styles = [
78
78
  formControlStyles,
79
79
  css`
80
80
  :host {
@@ -427,8 +427,8 @@ export class AgSlider extends LitElement implements SliderProps {
427
427
  `,
428
428
  ];
429
429
 
430
- // Form association
431
- private _internals: ElementInternals;
430
+ // Default value captured at firstUpdated for formResetCallback
431
+ private _defaultValue: number | [number, number] = 0;
432
432
 
433
433
  // Form control IDs
434
434
  private _sliderId: string;
@@ -453,7 +453,6 @@ export class AgSlider extends LitElement implements SliderProps {
453
453
 
454
454
  constructor() {
455
455
  super();
456
- this._internals = this.attachInternals();
457
456
 
458
457
  // Initialize form control IDs
459
458
  const ids = createFormControlIds('slider');
@@ -484,7 +483,6 @@ export class AgSlider extends LitElement implements SliderProps {
484
483
  this.invalid = false;
485
484
  this.errorMessage = '';
486
485
  this.helpText = '';
487
- this.name = '';
488
486
  this.showTooltip = false;
489
487
  this.showTicks = false;
490
488
  this.tickStep = 25;
@@ -576,12 +574,6 @@ export class AgSlider extends LitElement implements SliderProps {
576
574
  @property({ type: String, attribute: 'help-text' })
577
575
  declare helpText: string;
578
576
 
579
- /**
580
- * Form association
581
- */
582
- @property({ type: String, reflect: true })
583
- declare name: string;
584
-
585
577
  /**
586
578
  * Display options
587
579
  */
@@ -627,21 +619,6 @@ export class AgSlider extends LitElement implements SliderProps {
627
619
  @query('.ag-slider__live-region')
628
620
  private _liveRegion?: HTMLElement;
629
621
 
630
- /**
631
- * Form value handling
632
- */
633
- get form() { return this._internals.form; }
634
-
635
- get validity() { return this._internals.validity; }
636
-
637
- get validationMessage() { return this._internals.validationMessage; }
638
-
639
- get willValidate() { return this._internals.willValidate; }
640
-
641
- checkValidity() { return this._internals.checkValidity(); }
642
-
643
- reportValidity() { return this._internals.reportValidity(); }
644
-
645
622
  /**
646
623
  * Property validation
647
624
  */
@@ -692,6 +669,29 @@ export class AgSlider extends LitElement implements SliderProps {
692
669
  }
693
670
  }
694
671
 
672
+ // ─── FACE ─────────────────────────────────────────────────────────────────
673
+
674
+ override firstUpdated() {
675
+ // Capture default value for formResetCallback, then set initial form value
676
+ this._defaultValue = Array.isArray(this.value)
677
+ ? ([...this.value] as [number, number])
678
+ : this.value;
679
+ this._updateFormValue();
680
+ }
681
+
682
+ /**
683
+ * FACE lifecycle: called when the parent form is reset.
684
+ * Restores the slider to the value it had on first render.
685
+ */
686
+ override formResetCallback(): void {
687
+ this.value = Array.isArray(this._defaultValue)
688
+ ? ([...this._defaultValue] as [number, number])
689
+ : this._defaultValue;
690
+ this._updateFormValue();
691
+ }
692
+
693
+ // ─── End FACE ─────────────────────────────────────────────────────────────
694
+
695
695
  /**
696
696
  * Update form value when component value changes
697
697
  */
@@ -267,6 +267,11 @@ export class AgTimelineItem extends LitElement {
267
267
  line-height: normal;
268
268
  }
269
269
 
270
+ /* Ensure consistent sizing for slotted marker content */
271
+ .ag-marker ::slotted(*) {
272
+ box-sizing: border-box;
273
+ }
274
+
270
275
  /* End slot positioning */
271
276
  .ag-end {
272
277
  margin: var(--ag-space-1);