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,423 @@
1
+ /**
2
+ * AgnosticUI v2 SelectionButtonGroup - Core Implementation
3
+ *
4
+ * A container component that manages single (radio) or multiple (checkbox) selection
5
+ * using button-styled UI. Provides keyboard navigation and accessibility features.
6
+ *
7
+ * @element ag-selection-button-group
8
+ * @slot - Default slot for ag-selection-button elements
9
+ * @csspart fieldset - The fieldset element
10
+ * @csspart legend - The legend element
11
+ * @csspart content - The content wrapper containing buttons
12
+ */
13
+
14
+ import { LitElement, html, css, nothing } from 'lit';
15
+ import { property, state } from 'lit/decorators.js';
16
+ import { FaceMixin, type ValidationMessages } from '../../../shared/face-mixin';
17
+ import type { AgSelectionButton, SelectionButtonTheme, SelectionButtonSize, SelectionButtonShape } from '../../SelectionButton/core/_SelectionButton.js';
18
+
19
+ export type SelectionButtonType = 'radio' | 'checkbox';
20
+ export type SelectionButtonGroupTheme = SelectionButtonTheme;
21
+ export type SelectionButtonGroupSize = SelectionButtonSize;
22
+ export type SelectionButtonGroupShape = SelectionButtonShape;
23
+
24
+ export interface SelectionButtonChangeEventDetail {
25
+ /** The value of the button that triggered the change */
26
+ value: string;
27
+ /** Whether the button is now selected */
28
+ checked: boolean;
29
+ /** All currently selected values */
30
+ selectedValues: string[];
31
+ }
32
+
33
+ export type SelectionButtonChangeEvent = CustomEvent<SelectionButtonChangeEventDetail>;
34
+
35
+ export interface SelectionButtonGroupProps {
36
+ /** Selection mode: 'radio' (single) or 'checkbox' (multiple) */
37
+ type: SelectionButtonType;
38
+ /** Name attribute for the input elements */
39
+ name: string;
40
+ /** Legend text for the fieldset (accessibility) */
41
+ legend?: string;
42
+ /** Visually hide the legend while keeping it accessible */
43
+ legendHidden?: boolean;
44
+ /** Theme variant for buttons */
45
+ theme?: SelectionButtonGroupTheme;
46
+ /** Size variant for buttons */
47
+ size?: SelectionButtonGroupSize;
48
+ /** Shape variant for buttons */
49
+ shape?: SelectionButtonGroupShape;
50
+ /** Controlled value for radio mode */
51
+ value?: string;
52
+ /** Controlled values for checkbox mode */
53
+ values?: string[];
54
+ /** Disable all buttons in the group */
55
+ disabled?: boolean;
56
+ /** Require at least one selection before the form can be submitted */
57
+ required?: boolean;
58
+ validationMessages?: ValidationMessages;
59
+ /** Callback for selection changes */
60
+ onSelectionChange?: (event: SelectionButtonChangeEvent) => void;
61
+ }
62
+
63
+ export class AgSelectionButtonGroup extends FaceMixin(LitElement) implements SelectionButtonGroupProps {
64
+ static override styles = css`
65
+ :host {
66
+ display: block;
67
+ }
68
+
69
+ .selection-button-group {
70
+ border: 0;
71
+ padding: 0;
72
+ margin: 0;
73
+ min-inline-size: auto;
74
+ }
75
+
76
+ .selection-button-group__legend {
77
+ font-weight: 600;
78
+ font-size: var(--ag-font-size-base);
79
+ color: var(--ag-text-primary);
80
+ padding: 0;
81
+ margin-block-end: var(--ag-space-4);
82
+ }
83
+
84
+ .selection-button-group__legend--hidden {
85
+ position: absolute !important;
86
+ width: 1px !important;
87
+ height: 1px !important;
88
+ padding: 0 !important;
89
+ margin: -1px !important;
90
+ overflow: hidden !important;
91
+ clip: rect(0, 0, 0, 0) !important;
92
+ white-space: nowrap !important;
93
+ border: 0 !important;
94
+ }
95
+
96
+ .selection-button-group__content {
97
+ display: flex;
98
+ flex-wrap: wrap;
99
+ gap: var(--ag-selection-button-group-gap, var(--ag-space-2));
100
+ }
101
+ `;
102
+
103
+ @property({ type: String, reflect: true })
104
+ declare type: SelectionButtonType;
105
+
106
+ @property({ type: String })
107
+ declare legend: string;
108
+
109
+ @property({ type: Boolean, attribute: 'legend-hidden' })
110
+ declare legendHidden: boolean;
111
+
112
+ @property({ type: String, reflect: true })
113
+ declare theme: SelectionButtonGroupTheme;
114
+
115
+ @property({ type: String, reflect: true })
116
+ declare size: SelectionButtonGroupSize;
117
+
118
+ @property({ type: String, reflect: true })
119
+ declare shape: SelectionButtonGroupShape;
120
+
121
+ @property({ type: String })
122
+ declare value: string;
123
+
124
+ @property({ type: Array })
125
+ declare values: string[];
126
+
127
+ @property({ type: Boolean, reflect: true })
128
+ declare disabled: boolean;
129
+
130
+ @property({ type: Boolean, reflect: true })
131
+ declare required: boolean;
132
+
133
+ @property({ attribute: false })
134
+ declare validationMessages: ValidationMessages | undefined;
135
+
136
+ @property({ attribute: false })
137
+ declare onSelectionChange: ((event: SelectionButtonChangeEvent) => void) | undefined;
138
+
139
+ // Internal state for uncontrolled mode
140
+ @state()
141
+ declare _internalSelectedValues: string[];
142
+
143
+ constructor() {
144
+ super();
145
+ this.type = 'radio';
146
+ this.legend = '';
147
+ this.legendHidden = false;
148
+ this.theme = '';
149
+ this.size = 'md';
150
+ this.shape = '';
151
+ this.value = '';
152
+ this.values = [];
153
+ this.disabled = false;
154
+ this.required = false;
155
+ this._internalSelectedValues = [];
156
+ this.validationMessages = undefined;
157
+ }
158
+
159
+ // Get current selected values (controlled or uncontrolled)
160
+ private _getSelectedValues(): string[] {
161
+ if (this.type === 'radio') {
162
+ // For radio: use controlled value if set, otherwise internal state
163
+ if (this.value) {
164
+ return [this.value];
165
+ }
166
+ return this._internalSelectedValues;
167
+ }
168
+ // For checkbox: use controlled values if set (non-empty), otherwise internal state
169
+ if (this.values && this.values.length > 0) {
170
+ return this.values;
171
+ }
172
+ return this._internalSelectedValues;
173
+ }
174
+
175
+ // ─── FACE ─────────────────────────────────────────────────────────────────
176
+
177
+ /**
178
+ * Sync the form value to ElementInternals.
179
+ * Radio: submits the selected value as a string, or null if nothing selected.
180
+ * Checkbox: submits all selected values via FormData overload.
181
+ */
182
+ private _syncFormValue(): void {
183
+ const selected = this._getSelectedValues();
184
+ if (this.type === 'radio') {
185
+ this._internals.setFormValue(selected.length > 0 ? selected[0] : null);
186
+ } else {
187
+ if (selected.length === 0) {
188
+ this._internals.setFormValue(null);
189
+ } else {
190
+ const formData = new FormData();
191
+ selected.forEach(val => formData.append(this.name, val));
192
+ this._internals.setFormValue(formData);
193
+ }
194
+ }
195
+ }
196
+
197
+ private _syncValidity(): void {
198
+ const selected = this._getSelectedValues();
199
+ if (this.required && selected.length === 0) {
200
+ this._internals.setValidity(
201
+ { valueMissing: true },
202
+ this.validationMessages?.valueMissing ?? 'Please select an option.'
203
+ );
204
+ } else {
205
+ this._internals.setValidity({});
206
+ }
207
+ }
208
+
209
+ /**
210
+ * FACE lifecycle: called when the parent form is reset.
211
+ * Clears all selections and re-syncs child buttons.
212
+ */
213
+ override formResetCallback(): void {
214
+ this._internalSelectedValues = [];
215
+ this._internals.setFormValue(null);
216
+ this._syncValidity();
217
+ this._syncChildButtons();
218
+ }
219
+
220
+ // ─── End FACE ─────────────────────────────────────────────────────────────
221
+
222
+ override connectedCallback() {
223
+ super.connectedCallback();
224
+ this.addEventListener('selection-button-change', this._handleButtonChange as EventListener);
225
+ this.addEventListener('keydown', this._handleKeyDown);
226
+ }
227
+
228
+ override disconnectedCallback() {
229
+ super.disconnectedCallback();
230
+ this.removeEventListener('selection-button-change', this._handleButtonChange as EventListener);
231
+ this.removeEventListener('keydown', this._handleKeyDown);
232
+ }
233
+
234
+ override updated(changedProperties: Map<string, unknown>) {
235
+ super.updated(changedProperties);
236
+
237
+ // Sync props to child buttons
238
+ if (
239
+ changedProperties.has('type') ||
240
+ changedProperties.has('name') ||
241
+ changedProperties.has('theme') ||
242
+ changedProperties.has('size') ||
243
+ changedProperties.has('shape') ||
244
+ changedProperties.has('disabled') ||
245
+ changedProperties.has('value') ||
246
+ changedProperties.has('values') ||
247
+ changedProperties.has('_internalSelectedValues')
248
+ ) {
249
+ this._syncChildButtons();
250
+ }
251
+
252
+ // FACE: sync for programmatic value/values changes
253
+ if (
254
+ changedProperties.has('value') ||
255
+ changedProperties.has('values') ||
256
+ changedProperties.has('_internalSelectedValues')
257
+ ) {
258
+ this._syncFormValue();
259
+ this._syncValidity();
260
+ } else if (changedProperties.has('required')) {
261
+ this._syncValidity();
262
+ }
263
+ }
264
+
265
+ override firstUpdated() {
266
+ this._syncChildButtons();
267
+ this._syncFormValue();
268
+ this._syncValidity();
269
+ }
270
+
271
+ private _getButtons(): AgSelectionButton[] {
272
+ const slot = this.shadowRoot?.querySelector('slot');
273
+ if (!slot) return [];
274
+
275
+ return slot
276
+ .assignedElements({ flatten: true })
277
+ .filter((el): el is AgSelectionButton => el.tagName.toLowerCase() === 'ag-selection-button');
278
+ }
279
+
280
+ private _syncChildButtons() {
281
+ const buttons = this._getButtons();
282
+ const selectedValues = this._getSelectedValues();
283
+
284
+ buttons.forEach((button) => {
285
+ button._type = this.type;
286
+ button._name = this.name;
287
+ button._theme = this.theme;
288
+ button._size = this.size;
289
+ button._shape = this.shape;
290
+ button.checked = selectedValues.includes(button.value);
291
+ if (this.disabled) {
292
+ button.disabled = true;
293
+ }
294
+ });
295
+ }
296
+
297
+ private _handleButtonChange = (e: CustomEvent<{ value: string; checked: boolean }>) => {
298
+ e.stopPropagation();
299
+
300
+ const { value, checked } = e.detail;
301
+ let newSelectedValues: string[];
302
+
303
+ if (this.type === 'radio') {
304
+ // Radio: only one selected
305
+ newSelectedValues = checked ? [value] : [];
306
+ } else {
307
+ // Checkbox: toggle in list - use current selected values
308
+ const current = [...this._getSelectedValues()];
309
+ if (checked) {
310
+ if (!current.includes(value)) {
311
+ current.push(value);
312
+ }
313
+ } else {
314
+ const index = current.indexOf(value);
315
+ if (index > -1) {
316
+ current.splice(index, 1);
317
+ }
318
+ }
319
+ newSelectedValues = current;
320
+ }
321
+
322
+ // Update internal state (for uncontrolled mode)
323
+ this._internalSelectedValues = newSelectedValues;
324
+
325
+ // FACE: sync form value and validity on user interaction
326
+ this._syncFormValue();
327
+ this._syncValidity();
328
+
329
+ // Dispatch event
330
+ const changeEvent = new CustomEvent<SelectionButtonChangeEventDetail>('selection-change', {
331
+ detail: {
332
+ value,
333
+ checked,
334
+ selectedValues: newSelectedValues,
335
+ },
336
+ bubbles: true,
337
+ composed: true,
338
+ });
339
+
340
+ this.dispatchEvent(changeEvent);
341
+
342
+ if (this.onSelectionChange) {
343
+ this.onSelectionChange(changeEvent);
344
+ }
345
+ };
346
+
347
+ private _handleKeyDown = (e: KeyboardEvent) => {
348
+ const buttons = this._getButtons().filter((button) => !button.disabled);
349
+ if (buttons.length === 0) return;
350
+
351
+ // Find currently focused button (check shadowRoot for focus)
352
+ const focusedButton = buttons.find(button => {
353
+ try {
354
+ return button.shadowRoot?.activeElement || button === document.activeElement;
355
+ } catch {
356
+ return button === document.activeElement;
357
+ }
358
+ });
359
+ const currentIndex = focusedButton ? buttons.indexOf(focusedButton) : -1;
360
+
361
+ let nextIndex: number | null = null;
362
+
363
+ switch (e.key) {
364
+ case 'ArrowDown':
365
+ case 'ArrowRight':
366
+ e.preventDefault();
367
+ nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % buttons.length;
368
+ break;
369
+ case 'ArrowUp':
370
+ case 'ArrowLeft':
371
+ e.preventDefault();
372
+ nextIndex = currentIndex === -1 ? buttons.length - 1 : (currentIndex - 1 + buttons.length) % buttons.length;
373
+ break;
374
+ case 'Home':
375
+ e.preventDefault();
376
+ nextIndex = 0;
377
+ break;
378
+ case 'End':
379
+ e.preventDefault();
380
+ nextIndex = buttons.length - 1;
381
+ break;
382
+ }
383
+
384
+ if (nextIndex !== null) {
385
+ const nextButton = buttons[nextIndex];
386
+ nextButton.focus();
387
+
388
+ // For radio groups, arrow keys also select
389
+ if (this.type === 'radio') {
390
+ this._handleButtonChange(new CustomEvent('selection-button-change', {
391
+ detail: { value: nextButton.value, checked: true },
392
+ }));
393
+ }
394
+ }
395
+ };
396
+
397
+ private _handleSlotChange() {
398
+ this._syncChildButtons();
399
+ }
400
+
401
+ override render() {
402
+ const legendClasses = [
403
+ 'selection-button-group__legend',
404
+ this.legendHidden ? 'selection-button-group__legend--hidden' : '',
405
+ ].filter(Boolean).join(' ');
406
+
407
+ return html`
408
+ <fieldset
409
+ class="selection-button-group"
410
+ part="ag-selection-button-group-fieldset"
411
+ role="${this.type === 'radio' ? 'radiogroup' : 'group'}"
412
+ aria-disabled="${this.disabled ? 'true' : 'false'}"
413
+ >
414
+ ${this.legend
415
+ ? html`<legend class="${legendClasses}" part="ag-selection-button-group-legend">${this.legend}</legend>`
416
+ : nothing}
417
+ <div class="selection-button-group__content" part="ag-selection-button-group-content">
418
+ <slot @slotchange="${this._handleSlotChange}"></slot>
419
+ </div>
420
+ </fieldset>
421
+ `;
422
+ }
423
+ }
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ import { createComponent, type EventName } from '@lit/react';
3
+ import {
4
+ AgSelectionButtonGroup,
5
+ type SelectionButtonGroupProps,
6
+ type SelectionButtonChangeEvent,
7
+ } from '../core/SelectionButtonGroup';
8
+
9
+ export interface ReactSelectionButtonGroupProps extends SelectionButtonGroupProps {
10
+ children?: React.ReactNode;
11
+ className?: string;
12
+ onSelectionChange?: (event: SelectionButtonChangeEvent) => void;
13
+ }
14
+
15
+ export const ReactSelectionButtonGroup = createComponent({
16
+ tagName: 'ag-selection-button-group',
17
+ elementClass: AgSelectionButtonGroup,
18
+ react: React,
19
+ events: {
20
+ onSelectionChange: 'selection-change' as EventName<SelectionButtonChangeEvent>,
21
+ },
22
+ });
23
+
24
+ export type {
25
+ SelectionButtonGroupProps,
26
+ SelectionButtonChangeEvent,
27
+ SelectionButtonChangeEventDetail,
28
+ SelectionButtonType,
29
+ } from '../core/SelectionButtonGroup';
@@ -0,0 +1,9 @@
1
+ export { ReactSelectionButtonGroup, type ReactSelectionButtonGroupProps } from './ReactSelectionButtonGroup';
2
+
3
+ // Re-export types from core for convenience
4
+ export type {
5
+ SelectionButtonGroupProps,
6
+ SelectionButtonChangeEvent,
7
+ SelectionButtonChangeEventDetail,
8
+ SelectionButtonType,
9
+ } from '../core/SelectionButtonGroup';
@@ -0,0 +1,89 @@
1
+ <template>
2
+ <ag-selection-button-group
3
+ :type="type"
4
+ :name="name"
5
+ :legend="legend"
6
+ :legend-hidden="legendHidden"
7
+ :theme="theme"
8
+ :size="size"
9
+ :shape="shape"
10
+ :value="value"
11
+ :values="values"
12
+ .disabled="disabled"
13
+ .required="required"
14
+ .validationMessages="validationMessages"
15
+ @selection-change="handleSelectionChange"
16
+ v-bind="$attrs"
17
+ >
18
+ <slot />
19
+ </ag-selection-button-group>
20
+ </template>
21
+
22
+ <script setup lang="ts">
23
+ import '../core/SelectionButtonGroup';
24
+ import type {
25
+ SelectionButtonType,
26
+ SelectionButtonChangeEventDetail,
27
+ SelectionButtonGroupTheme,
28
+ SelectionButtonGroupSize,
29
+ SelectionButtonGroupShape,
30
+ } from '../core/SelectionButtonGroup';
31
+ import type { ValidationMessages } from '../../../shared/face-mixin';
32
+
33
+ export interface VueSelectionButtonGroupProps {
34
+ /** Selection mode: 'radio' (single) or 'checkbox' (multiple) */
35
+ type?: SelectionButtonType;
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 buttons */
43
+ theme?: SelectionButtonGroupTheme;
44
+ /** Size variant for buttons */
45
+ size?: SelectionButtonGroupSize;
46
+ /** Shape variant for buttons */
47
+ shape?: SelectionButtonGroupShape;
48
+ /** Controlled value for radio mode */
49
+ value?: string;
50
+ /** Controlled values for checkbox mode */
51
+ values?: string[];
52
+ /** Disable all buttons in the group */
53
+ disabled?: boolean;
54
+ /** Require at least one selection before the form can be submitted */
55
+ required?: boolean;
56
+ validationMessages?: ValidationMessages;
57
+ }
58
+
59
+ withDefaults(defineProps<VueSelectionButtonGroupProps>(), {
60
+ type: 'radio',
61
+ name: '',
62
+ legend: '',
63
+ legendHidden: false,
64
+ theme: '',
65
+ size: 'md',
66
+ shape: '',
67
+ value: '',
68
+ values: () => [],
69
+ disabled: false,
70
+ required: false,
71
+ });
72
+
73
+ const emit = defineEmits<{
74
+ 'selection-change': [detail: SelectionButtonChangeEventDetail];
75
+ 'update:value': [value: string];
76
+ 'update:values': [values: string[]];
77
+ }>();
78
+
79
+ const handleSelectionChange = (event: Event) => {
80
+ const detail = (event as CustomEvent<SelectionButtonChangeEventDetail>).detail;
81
+ emit('selection-change', detail);
82
+ // Support v-model:value for radio
83
+ if (detail.selectedValues.length <= 1) {
84
+ emit('update:value', detail.selectedValues[0] || '');
85
+ }
86
+ // Support v-model:values for checkbox
87
+ emit('update:values', detail.selectedValues);
88
+ };
89
+ </script>
@@ -0,0 +1,5 @@
1
+ import VueSelectionButtonGroup from './VueSelectionButtonGroup.vue';
2
+ import type { SelectionButtonGroupProps as VueSelectionButtonGroupProps } from '../core/_SelectionButtonGroup';
3
+
4
+ export { VueSelectionButtonGroup };
5
+ export type { VueSelectionButtonGroupProps };
@@ -0,0 +1,13 @@
1
+ import { AgSelectionCard } from './_SelectionCard.js';
2
+
3
+ if (!customElements.get('ag-selection-card')) {
4
+ customElements.define('ag-selection-card', AgSelectionCard);
5
+ }
6
+
7
+ declare global {
8
+ interface HTMLElementTagNameMap {
9
+ 'ag-selection-card': AgSelectionCard;
10
+ }
11
+ }
12
+
13
+ export * from './_SelectionCard.js';