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
@@ -5,6 +5,7 @@ import {
5
5
  createFormControlIds,
6
6
  buildAriaDescribedBy,
7
7
  } from '../../../shared/form-control-utils';
8
+ import { FaceMixin } from '../../../shared/face-mixin';
8
9
 
9
10
 
10
11
  export type RadioSize = 'small' | 'medium' | 'large';
@@ -29,35 +30,35 @@ export interface RadioProps {
29
30
  /**
30
31
  * Name attribute for the radio input (required for grouping)
31
32
  */
32
- name: string;
33
+ name?: string;
33
34
  /**
34
35
  * Value of the radio input
35
36
  */
36
- value: string;
37
+ value?: string;
37
38
  /**
38
39
  * Whether the radio is checked
39
40
  */
40
- checked: boolean;
41
+ checked?: boolean;
41
42
  /**
42
43
  * Whether the radio is disabled
43
44
  */
44
- disabled: boolean;
45
+ disabled?: boolean;
45
46
  /**
46
47
  * Size of the radio button
47
48
  */
48
- size: RadioSize;
49
+ size?: RadioSize;
49
50
  /**
50
51
  * Color theme variant
51
52
  */
52
- theme: RadioTheme;
53
+ theme?: RadioTheme;
53
54
  /**
54
55
  * Label text for the radio button (internal label that wraps the radio)
55
56
  */
56
- labelText: string;
57
+ labelText?: string;
57
58
  /**
58
59
  * Position of labelText relative to radio (end = after radio, start = before radio)
59
60
  */
60
- labelPosition: 'end' | 'start';
61
+ labelPosition?: 'end' | 'start';
61
62
  /**
62
63
  * Optional external label displayed above the radio (useful for groups or standalone with context)
63
64
  */
@@ -96,7 +97,7 @@ export interface RadioProps {
96
97
  onChange?: (event: RadioChangeEvent) => void;
97
98
  }
98
99
 
99
- export class AgRadio extends LitElement implements RadioProps {
100
+ export class AgRadio extends FaceMixin(LitElement) implements RadioProps {
100
101
  static override styles = [
101
102
  formControlStyles,
102
103
  css`
@@ -286,9 +287,6 @@ export class AgRadio extends LitElement implements RadioProps {
286
287
  `,
287
288
  ];
288
289
 
289
- @property({ type: String, reflect: true })
290
- name = '';
291
-
292
290
  @property({ type: String, reflect: true })
293
291
  value = '';
294
292
 
@@ -336,6 +334,8 @@ export class AgRadio extends LitElement implements RadioProps {
336
334
  // Stable IDs for form control elements (created once)
337
335
  private _ids = createFormControlIds('ag-radio');
338
336
 
337
+ private inputRef?: HTMLInputElement;
338
+
339
339
  // Event callback props
340
340
  @property({ attribute: false })
341
341
  onClick?: (event: MouseEvent) => void;
@@ -343,6 +343,111 @@ export class AgRadio extends LitElement implements RadioProps {
343
343
  @property({ attribute: false })
344
344
  onChange?: (event: RadioChangeEvent) => void;
345
345
 
346
+ // ─── FACE ─────────────────────────────────────────────────────────────────
347
+
348
+ /**
349
+ * Sync the form value to ElementInternals.
350
+ * Submits this radio's value when checked, or null when unchecked.
351
+ * Each radio in the group reports independently; only the checked one
352
+ * contributes a value, matching native radio behavior.
353
+ */
354
+ private _syncFormValue(): void {
355
+ this._internals.setFormValue(this.checked ? this.value : null);
356
+ }
357
+
358
+ /**
359
+ * Returns true if any ag-radio in this named group is checked.
360
+ * Uses the same DOM-traversal logic as uncheckOtherRadiosInGroup so it
361
+ * works whether the radios are in the document or nested inside a shadow root.
362
+ */
363
+ private _isGroupChecked(): boolean {
364
+ if (this.checked) return true;
365
+ // Query from the immediate root node. If the radios live inside a shadow root
366
+ // (e.g. a Lit host component), getRootNode() returns that shadow root and
367
+ // querySelectorAll can reach them. If they're in the document's light DOM
368
+ // (React/Vue), getRootNode() returns the document. Traversing all the way up
369
+ // to document would bypass shadow roots and miss the siblings.
370
+ const root = this.getRootNode() as Document | ShadowRoot;
371
+ return Array.from(root.querySelectorAll(`ag-radio[name="${this.name}"]`)).some(
372
+ (el) => (el as AgRadio).checked
373
+ );
374
+ }
375
+
376
+ /**
377
+ * Sync validity to ElementInternals.
378
+ *
379
+ * Shadow DOM isolation prevents the inner <input type="radio"> from seeing
380
+ * sibling ag-radio elements in separate shadow trees, so native delegation
381
+ * would report each unchecked required radio as invalid individually.
382
+ * Instead we query the DOM directly: a required radio group is valid when
383
+ * ANY radio with the same name is checked.
384
+ */
385
+ private _syncValidity(): void {
386
+ if (!this.required) {
387
+ this._internals.setValidity({});
388
+ return;
389
+ }
390
+ if (this._isGroupChecked()) {
391
+ this._internals.setValidity({});
392
+ } else {
393
+ this._internals.setValidity({ valueMissing: true }, 'Please select one of these options.');
394
+ }
395
+ }
396
+
397
+ /**
398
+ * FACE lifecycle: called when the parent form is reset.
399
+ * Restores checked to false and clears the form value.
400
+ */
401
+ override formResetCallback(): void {
402
+ this.checked = false;
403
+ this._internals.setFormValue(null);
404
+ this._internals.setValidity({});
405
+ this._syncStates();
406
+ }
407
+
408
+ /**
409
+ * Sync CustomStateSet states so :state() pseudo-classes work from external CSS.
410
+ *
411
+ * Must be called AFTER _syncValidity() so that :state(invalid) reads the
412
+ * freshly-updated _internals.validity.valid value.
413
+ *
414
+ * Exposed states:
415
+ * :state(checked) — this radio is selected
416
+ * :state(disabled) — radio is disabled
417
+ * :state(required) — radio is required
418
+ * :state(invalid) — FACE constraint validation is failing
419
+ */
420
+ private _syncStates(): void {
421
+ this._setState('checked', this.checked);
422
+ this._setState('disabled', this.disabled);
423
+ this._setState('required', this.required);
424
+ this._setState('invalid', !this._internals.validity.valid);
425
+ }
426
+
427
+ // ─── End FACE ─────────────────────────────────────────────────────────────
428
+
429
+ override firstUpdated() {
430
+ this.inputRef = this.shadowRoot?.querySelector('.radio-input') as HTMLInputElement;
431
+
432
+ // FACE: set initial form value and sync validity after first render
433
+ this._syncFormValue();
434
+ this._syncValidity();
435
+ this._syncStates();
436
+ }
437
+
438
+ override updated(changedProperties: Map<string, unknown>) {
439
+ super.updated(changedProperties);
440
+
441
+ // FACE: sync form value and validity for programmatic changes to checked.
442
+ // This fires when uncheckOtherRadiosInGroup() sets sibling.checked = false,
443
+ // so group FACE state stays synchronized without any explicit coordination.
444
+ if (changedProperties.has('checked')) {
445
+ this._syncFormValue();
446
+ this._syncValidity();
447
+ this._syncStates();
448
+ }
449
+ }
450
+
346
451
  private handleClick(e: MouseEvent) {
347
452
  if (this.onClick) {
348
453
  this.onClick(e);
@@ -415,22 +520,8 @@ export class AgRadio extends LitElement implements RadioProps {
415
520
 
416
521
  private getRadiosInGroup(): AgRadio[] {
417
522
  if (!this.name) return [];
418
-
419
- // Find the root document (traverse up from shadow roots if needed)
420
- let root: Node = this.getRootNode();
421
- while (root && 'host' in root) {
422
- const parent = (root as ShadowRoot).host?.getRootNode();
423
- if (parent && parent !== root) {
424
- root = parent;
425
- } else {
426
- break;
427
- }
428
- }
429
-
430
- const doc = root instanceof Document ? root : document;
431
- const allRadios = doc.querySelectorAll(`ag-radio[name="${this.name}"]`);
432
-
433
- // Filter to only enabled radios and return as array
523
+ const root = this.getRootNode() as Document | ShadowRoot;
524
+ const allRadios = root.querySelectorAll(`ag-radio[name="${this.name}"]`);
434
525
  return Array.from(allRadios).filter((radio): radio is AgRadio => {
435
526
  return radio instanceof AgRadio && !radio.disabled;
436
527
  });
@@ -446,6 +537,11 @@ export class AgRadio extends LitElement implements RadioProps {
446
537
  const wasChecked = this.checked;
447
538
  this.checked = input.checked;
448
539
 
540
+ // FACE: sync form value and validity on user interaction
541
+ this._syncFormValue();
542
+ this._syncValidity();
543
+ this._syncStates();
544
+
449
545
  // Radio group coordination: When this radio is checked, uncheck all other radios with the same name
450
546
  // This is necessary because native radios in separate shadow DOMs don't coordinate automatically
451
547
  if (this.checked && !wasChecked && this.name) {
@@ -474,23 +570,17 @@ export class AgRadio extends LitElement implements RadioProps {
474
570
  }
475
571
 
476
572
  private uncheckOtherRadiosInGroup() {
477
- // Find the root document (traverse up from shadow roots if needed)
478
- let root: Node = this.getRootNode();
479
- while (root && 'host' in root) {
480
- const parent = (root as ShadowRoot).host?.getRootNode();
481
- if (parent && parent !== root) {
482
- root = parent;
483
- } else {
484
- break;
485
- }
486
- }
487
-
488
- const doc = root instanceof Document ? root : document;
489
- const allRadios = doc.querySelectorAll(`ag-radio[name="${this.name}"]`);
573
+ const root = this.getRootNode() as Document | ShadowRoot;
574
+ const allRadios = root.querySelectorAll(`ag-radio[name="${this.name}"]`);
490
575
 
491
576
  allRadios.forEach((radio) => {
492
577
  if (radio !== this && radio instanceof AgRadio) {
493
578
  radio.checked = false;
579
+ // If checked didn't actually change (was already false), Lit's updated() won't
580
+ // fire on the sibling, so _syncValidity() wouldn't be called. Force it so
581
+ // unchecked siblings correctly reflect the group's new validity state.
582
+ radio._syncValidity();
583
+ radio._syncStates();
494
584
  }
495
585
  });
496
586
  }
@@ -1,6 +1,5 @@
1
1
  <template>
2
2
  <ag-radio
3
- ref="radioRef"
4
3
  .checked="checked"
5
4
  .disabled="disabled"
6
5
  .required="required"
@@ -25,7 +24,6 @@
25
24
  </template>
26
25
 
27
26
  <script setup lang="ts">
28
- import { ref } from "vue";
29
27
  import type { RadioSize, RadioTheme } from "../core/Radio";
30
28
  import "../core/Radio";
31
29
 
@@ -47,7 +45,7 @@ export interface VueRadioProps {
47
45
  helpText?: string;
48
46
  }
49
47
 
50
- const props = withDefaults(defineProps<VueRadioProps>(), {
48
+ withDefaults(defineProps<VueRadioProps>(), {
51
49
  name: "",
52
50
  value: "",
53
51
  checked: false,
@@ -71,8 +69,6 @@ const emit = defineEmits<{
71
69
  "update:checked": [checked: boolean];
72
70
  }>();
73
71
 
74
- const radioRef = ref<HTMLElement>();
75
-
76
72
  const handleClick = (event: MouseEvent) => {
77
73
  emit("click", event);
78
74
  };
@@ -8,6 +8,7 @@ import {
8
8
  type LabelPosition,
9
9
  } from '../../../shared/form-control-utils';
10
10
  import { formControlStyles } from '../../../shared/form-control-styles';
11
+ import { FaceMixin, type ValidationMessages } from '../../../shared/face-mixin';
11
12
 
12
13
  // Event detail interfaces
13
14
  export interface RatingChangeEventDetail {
@@ -46,6 +47,7 @@ export interface RatingProps {
46
47
  invalid?: boolean;
47
48
  errorMessage?: string;
48
49
  helpText?: string;
50
+ validationMessages?: ValidationMessages;
49
51
  // Event handlers
50
52
  onRatingChange?: (event: RatingChangeEvent) => void;
51
53
  onRatingHover?: (event: RatingHoverEvent) => void;
@@ -53,7 +55,7 @@ export interface RatingProps {
53
55
 
54
56
  let uniqueIdCounter = 0;
55
57
 
56
- export class AgRating extends LitElement {
58
+ export class AgRating extends FaceMixin(LitElement) {
57
59
  private uniqueId = ++uniqueIdCounter; // Unique ID for clip paths in half-star rendering
58
60
 
59
61
  // Form control IDs
@@ -84,9 +86,6 @@ export class AgRating extends LitElement {
84
86
  @property({ type: String, reflect: true })
85
87
  declare size: RatingSize; // Size: small, medium, large
86
88
 
87
- @property({ type: String })
88
- declare name: string; // Form integration name
89
-
90
89
  // Form control properties
91
90
  @property({ type: String })
92
91
  declare label: string;
@@ -112,6 +111,9 @@ export class AgRating extends LitElement {
112
111
  @property({ type: String, attribute: 'help-text' })
113
112
  declare helpText: string;
114
113
 
114
+ @property({ attribute: false })
115
+ declare validationMessages: ValidationMessages | undefined;
116
+
115
117
  // Event handlers
116
118
  @property({ attribute: false })
117
119
  declare onRatingChange?: (event: RatingChangeEvent) => void;
@@ -141,7 +143,6 @@ export class AgRating extends LitElement {
141
143
  this.allowClear = false;
142
144
  this.variant = '';
143
145
  this.size = 'md';
144
- this.name = '';
145
146
  this.label = '';
146
147
  this.labelHidden = false;
147
148
  this.noLabel = false;
@@ -149,11 +150,62 @@ export class AgRating extends LitElement {
149
150
  this.invalid = false;
150
151
  this.errorMessage = '';
151
152
  this.helpText = '';
153
+ this.validationMessages = undefined;
152
154
  this.handlePointerMove = this.handlePointerMove.bind(this);
153
155
  this.handlePointerUp = this.handlePointerUp.bind(this);
154
156
  this.handleKeyDown = this.handleKeyDown.bind(this);
155
157
  }
156
158
 
159
+ // ─── FACE ─────────────────────────────────────────────────────────────────
160
+
161
+ /**
162
+ * Sync the form value to ElementInternals.
163
+ * Submits the numeric rating as a string, or null when value is 0 (no rating).
164
+ */
165
+ private _syncFormValue(): void {
166
+ this._internals.setFormValue(this.value > 0 ? String(this.value) : null);
167
+ }
168
+
169
+ /**
170
+ * Sync validity. No inner input to delegate to, so we implement required
171
+ * directly: a rating of 0 with required=true is valueMissing.
172
+ */
173
+ private _syncValidity(): void {
174
+ if (this.required && this.value === 0) {
175
+ this._internals.setValidity(
176
+ { valueMissing: true },
177
+ this.validationMessages?.valueMissing ?? 'Please select a rating.'
178
+ );
179
+ } else {
180
+ this._internals.setValidity({});
181
+ }
182
+ }
183
+
184
+ override firstUpdated() {
185
+ this._syncFormValue();
186
+ this._syncValidity();
187
+ }
188
+
189
+ override updated(changedProperties: Map<string, unknown>) {
190
+ super.updated(changedProperties);
191
+ if (changedProperties.has('value')) {
192
+ this._syncFormValue();
193
+ this._syncValidity();
194
+ }
195
+ }
196
+
197
+ /**
198
+ * FACE lifecycle: called when the parent form is reset.
199
+ * Restores rating to 0 (no selection).
200
+ */
201
+ override formResetCallback(): void {
202
+ this.value = 0;
203
+ this._internals.setFormValue(null);
204
+ this._internals.setValidity({});
205
+ }
206
+
207
+ // ─── End FACE ─────────────────────────────────────────────────────────────
208
+
157
209
  connectedCallback() {
158
210
  super.connectedCallback();
159
211
  this.addEventListener('keydown', this.handleKeyDown);
@@ -558,6 +610,11 @@ export class AgRating extends LitElement {
558
610
  private commitValue(newValue: number, oldValue: number) {
559
611
  const normalized = this.roundToPrecision(newValue);
560
612
  this.value = normalized;
613
+
614
+ // FACE: sync form value and validity on user interaction
615
+ this._syncFormValue();
616
+ this._syncValidity();
617
+
561
618
  const changeEvent = new CustomEvent<RatingChangeEventDetail>('rating-change', {
562
619
  detail: { oldValue, newValue: normalized },
563
620
  bubbles: true,
@@ -6,6 +6,7 @@
6
6
  .allowClear="allowClear"
7
7
  .required="required"
8
8
  .invalid="invalid"
9
+ .validationMessages="validationMessages"
9
10
  :max="max"
10
11
  :precision="precision"
11
12
  :variant="variant"
@@ -28,6 +29,7 @@
28
29
  <script setup lang="ts">
29
30
  import { ref } from "vue";
30
31
  import "../core/Rating";
32
+ import type { ValidationMessages } from "../../../shared/face-mixin";
31
33
 
32
34
  /**
33
35
  * Vue Rating Props
@@ -59,6 +61,7 @@ export interface VueRatingProps {
59
61
  invalid?: boolean;
60
62
  errorMessage?: string;
61
63
  helpText?: string;
64
+ validationMessages?: ValidationMessages;
62
65
  }
63
66
 
64
67
  const props = withDefaults(defineProps<VueRatingProps>(), {
@@ -7,6 +7,7 @@ import {
7
7
  type LabelPosition,
8
8
  } from '../../../shared/form-control-utils';
9
9
  import { formControlStyles } from '../../../shared/form-control-styles';
10
+ import { FaceMixin, syncInnerInputValidity } from '../../../shared/face-mixin';
10
11
 
11
12
  export type SelectSize = 'small' | 'large' | '';
12
13
 
@@ -47,7 +48,7 @@ export interface SelectProps {
47
48
  *
48
49
  * @fires change - Emitted when selection changes
49
50
  */
50
- export class Select extends LitElement implements SelectProps {
51
+ export class Select extends FaceMixin(LitElement) implements SelectProps {
51
52
  @property({ type: String, reflect: true })
52
53
  public size: SelectSize = '';
53
54
 
@@ -57,9 +58,6 @@ export class Select extends LitElement implements SelectProps {
57
58
  @property({ type: Boolean, reflect: true })
58
59
  public disabled = false;
59
60
 
60
- @property({ type: String })
61
- public name = '';
62
-
63
61
  @property({ type: Number, attribute: 'multiple-size' })
64
62
  public multipleSize?: number;
65
63
 
@@ -103,6 +101,49 @@ export class Select extends LitElement implements SelectProps {
103
101
  @query('select')
104
102
  private selectElement!: HTMLSelectElement;
105
103
 
104
+ // ─── FACE ─────────────────────────────────────────────────────────────────
105
+
106
+ /**
107
+ * FACE lifecycle: called when the parent form is reset.
108
+ * Restores each option to its defaultSelected state (the `selected`
109
+ * attribute from the original HTML), then re-syncs the form value.
110
+ */
111
+ override formResetCallback(): void {
112
+ if (this.selectElement) {
113
+ Array.from(this.selectElement.options).forEach(opt => (opt.selected = opt.defaultSelected));
114
+ }
115
+ this._syncFormValue();
116
+ this._internals.setValidity({});
117
+ }
118
+
119
+ /**
120
+ * Sync the form value to ElementInternals.
121
+ * Single select: submits the selected value as a string.
122
+ * Multi-select: uses the FormData overload to submit all selected values
123
+ * under the same key (matching native <select multiple> behavior).
124
+ */
125
+ private _syncFormValue(): void {
126
+ if (!this.selectElement) return;
127
+ if (this.multiple) {
128
+ const formData = new FormData();
129
+ Array.from(this.selectElement.selectedOptions).forEach(opt => {
130
+ formData.append(this.name, opt.value);
131
+ });
132
+ this._internals.setFormValue(formData);
133
+ } else {
134
+ this._internals.setFormValue(this.selectElement.value || '');
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Sync validity to ElementInternals by delegating to the inner <select>.
140
+ */
141
+ private _syncValidity(): void {
142
+ syncInnerInputValidity(this._internals, this.selectElement);
143
+ }
144
+
145
+ // ─── End FACE ─────────────────────────────────────────────────────────────
146
+
106
147
  protected firstUpdated() {
107
148
  // Ensure options are moved after first render
108
149
  this.handleSlotChange();
@@ -112,6 +153,10 @@ export class Select extends LitElement implements SelectProps {
112
153
  if (slotElement) {
113
154
  slotElement.addEventListener('slotchange', () => this.handleSlotChange());
114
155
  }
156
+
157
+ // FACE: set initial form value and sync validity after options are in place
158
+ this._syncFormValue();
159
+ this._syncValidity();
115
160
  }
116
161
 
117
162
  private handleSlotChange() {
@@ -162,7 +207,7 @@ export class Select extends LitElement implements SelectProps {
162
207
  /* Base styling */
163
208
  padding: var(--ag-space-2) var(--ag-space-8) var(--ag-space-2) var(--ag-space-3);
164
209
  -moz-padding-start: calc(var(--ag-space-3) - 3px);
165
- font-size: var(--ag-font-size-base);
210
+ font-size: var(--ag-font-size-sm);
166
211
  font-weight: 400;
167
212
  line-height: 1.5;
168
213
  font-family: inherit;
@@ -212,7 +257,7 @@ export class Select extends LitElement implements SelectProps {
212
257
  padding-block-start: var(--ag-space-1);
213
258
  padding-block-end: var(--ag-space-1);
214
259
  padding-inline-start: var(--ag-space-2);
215
- font-size: var(--ag-font-size-small);
260
+ font-size: var(--ag-font-size-sm);
216
261
  }
217
262
 
218
263
  /* Large size variant */
@@ -276,6 +321,10 @@ export class Select extends LitElement implements SelectProps {
276
321
  value = select.value;
277
322
  }
278
323
 
324
+ // FACE: sync form value and validity on every selection change
325
+ this._syncFormValue();
326
+ this._syncValidity();
327
+
279
328
  // Dual-dispatch: dispatchEvent + callback
280
329
  const changeEvent = new CustomEvent<SelectChangeEventDetail>('change', {
281
330
  detail: { value },
@@ -0,0 +1,13 @@
1
+ import { AgSelectionButton } from './_SelectionButton.js';
2
+
3
+ if (!customElements.get('ag-selection-button')) {
4
+ customElements.define('ag-selection-button', AgSelectionButton);
5
+ }
6
+
7
+ declare global {
8
+ interface HTMLElementTagNameMap {
9
+ 'ag-selection-button': AgSelectionButton;
10
+ }
11
+ }
12
+
13
+ export * from './_SelectionButton.js';