@tcn/ui 0.17.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. package/dist/actions/index.d.ts +0 -1
  2. package/dist/actions/index.d.ts.map +1 -1
  3. package/dist/actions/index.js +6 -8
  4. package/dist/actions/index.js.map +1 -1
  5. package/dist/draggable.css +1 -1
  6. package/dist/draggable.module-DFYR5n3n.js +5 -0
  7. package/dist/draggable.module-DFYR5n3n.js.map +1 -0
  8. package/dist/field_set.css +1 -1
  9. package/dist/field_set.module-BpJTFCi4.js +5 -0
  10. package/dist/field_set.module-BpJTFCi4.js.map +1 -0
  11. package/dist/form/field/field.js +11 -10
  12. package/dist/form/field/field.js.map +1 -1
  13. package/dist/form/field_set/field_set.d.ts +6 -10
  14. package/dist/form/field_set/field_set.d.ts.map +1 -1
  15. package/dist/form/field_set/field_set.js +33 -61
  16. package/dist/form/field_set/field_set.js.map +1 -1
  17. package/dist/form/field_set/legend.d.ts +20 -0
  18. package/dist/form/field_set/legend.d.ts.map +1 -0
  19. package/dist/form/field_set/legend.js +28 -0
  20. package/dist/form/field_set/legend.js.map +1 -0
  21. package/dist/form/index.d.ts +2 -1
  22. package/dist/form/index.d.ts.map +1 -1
  23. package/dist/form/index.js +24 -22
  24. package/dist/form/index.js.map +1 -1
  25. package/dist/inputs/color_input/color_input.js +2 -3
  26. package/dist/inputs/color_input/color_input.js.map +1 -1
  27. package/dist/inputs/color_input/color_picker.js +11 -10
  28. package/dist/inputs/color_input/color_picker.js.map +1 -1
  29. package/dist/inputs/combo_box/combo_box.js +11 -10
  30. package/dist/inputs/combo_box/combo_box.js.map +1 -1
  31. package/dist/inputs/date_picker/date_picker.js +11 -10
  32. package/dist/inputs/date_picker/date_picker.js.map +1 -1
  33. package/dist/inputs/date_picker/date_picker_header.d.ts.map +1 -1
  34. package/dist/inputs/date_picker/date_picker_header.js +15 -14
  35. package/dist/inputs/date_picker/date_picker_header.js.map +1 -1
  36. package/dist/inputs/date_picker/date_picker_input.js +9 -9
  37. package/dist/inputs/date_picker/date_picker_time_selector.js +2 -3
  38. package/dist/inputs/date_picker/date_picker_time_selector.js.map +1 -1
  39. package/dist/inputs/date_picker/date_picker_year_input.js +2 -3
  40. package/dist/inputs/date_picker/date_picker_year_input.js.map +1 -1
  41. package/dist/inputs/date_picker/date_picker_year_selector.js +22 -22
  42. package/dist/inputs/date_picker/date_picker_year_selector.js.map +1 -1
  43. package/dist/inputs/mask_input/key_capture_input.js +21 -20
  44. package/dist/inputs/mask_input/key_capture_input.js.map +1 -1
  45. package/dist/inputs/mask_input/mask_input.js +18 -17
  46. package/dist/inputs/mask_input/mask_input.js.map +1 -1
  47. package/dist/inputs/multiselect/multiselect.js +11 -10
  48. package/dist/inputs/multiselect/multiselect.js.map +1 -1
  49. package/dist/inputs/multiselect/multiselect_inline_values.d.ts.map +1 -1
  50. package/dist/inputs/multiselect/multiselect_inline_values.js +15 -15
  51. package/dist/inputs/multiselect/multiselect_inline_values.js.map +1 -1
  52. package/dist/inputs/multiselect/multiselect_values.js +16 -17
  53. package/dist/inputs/multiselect/multiselect_values.js.map +1 -1
  54. package/dist/inputs/phone_number_input/phone_number_context.js +13 -12
  55. package/dist/inputs/phone_number_input/phone_number_context.js.map +1 -1
  56. package/dist/inputs/phone_number_input/phone_number_input_adapter.js +2 -3
  57. package/dist/inputs/phone_number_input/phone_number_input_adapter.js.map +1 -1
  58. package/dist/inputs/phone_number_input/sip_input.js +8 -9
  59. package/dist/inputs/phone_number_input/sip_input.js.map +1 -1
  60. package/dist/inputs/select/select.js +9 -9
  61. package/dist/inputs/slider/slider.js +21 -20
  62. package/dist/inputs/slider/slider.js.map +1 -1
  63. package/dist/inputs/suggestions/suggestion_list.js +9 -9
  64. package/dist/inputs/switch/switch.js +16 -15
  65. package/dist/inputs/switch/switch.js.map +1 -1
  66. package/dist/inputs/unit_input/unit_input.js +11 -10
  67. package/dist/inputs/unit_input/unit_input.js.map +1 -1
  68. package/dist/mobile/inputs/date_picker/mobile_date_picker_header.js +11 -10
  69. package/dist/mobile/inputs/date_picker/mobile_date_picker_header.js.map +1 -1
  70. package/dist/mobile/inputs/date_picker/mobile_date_picker_input.js +11 -10
  71. package/dist/mobile/inputs/date_picker/mobile_date_picker_input.js.map +1 -1
  72. package/dist/mobile/inputs/date_picker/mobile_date_picker_year_selector.js +11 -10
  73. package/dist/mobile/inputs/date_picker/mobile_date_picker_year_selector.js.map +1 -1
  74. package/dist/multiselect_values.css +1 -1
  75. package/dist/navigation/tabs/state/link/tab_link.js +11 -10
  76. package/dist/navigation/tabs/state/link/tab_link.js.map +1 -1
  77. package/dist/overlay/frame/frame.d.ts.map +1 -1
  78. package/dist/overlay/frame/frame.js +117 -76
  79. package/dist/overlay/frame/frame.js.map +1 -1
  80. package/dist/overlay/menu/menu.js +21 -20
  81. package/dist/overlay/menu/menu.js.map +1 -1
  82. package/dist/overlay/popper/base/dismissal_decorator.js +3 -3
  83. package/dist/overlay/popper/base/dismissal_decorator.js.map +1 -1
  84. package/dist/overlay/popper/context_popper.js +11 -10
  85. package/dist/overlay/popper/context_popper.js.map +1 -1
  86. package/dist/overlay/popper/element_popper.js +11 -10
  87. package/dist/overlay/popper/element_popper.js.map +1 -1
  88. package/dist/overlay/popper/legacy/popper.js +28 -27
  89. package/dist/overlay/popper/legacy/popper.js.map +1 -1
  90. package/dist/overlay/popper/preview_popper.js +11 -10
  91. package/dist/overlay/popper/preview_popper.js.map +1 -1
  92. package/dist/overlay/tethered/tethered.js +11 -10
  93. package/dist/overlay/tethered/tethered.js.map +1 -1
  94. package/dist/resizable.css +1 -1
  95. package/dist/resizable.module-ur5FBfxo.js +5 -0
  96. package/dist/resizable.module-ur5FBfxo.js.map +1 -0
  97. package/dist/resize_handle.css +1 -1
  98. package/dist/stacks/box/box.d.ts +14 -0
  99. package/dist/stacks/box/box.d.ts.map +1 -1
  100. package/dist/stacks/box/box.js +98 -99
  101. package/dist/stacks/box/box.js.map +1 -1
  102. package/dist/stacks/box/end_resize_handle.js +5 -5
  103. package/dist/stacks/box/end_resize_handle.js.map +1 -1
  104. package/dist/stacks/box/resize_handlers.d.ts.map +1 -1
  105. package/dist/stacks/box/resize_handlers.js +12 -12
  106. package/dist/stacks/box/resize_handlers.js.map +1 -1
  107. package/dist/stacks/box/start_resize_handle.js +7 -7
  108. package/dist/stacks/box/start_resize_handle.js.map +1 -1
  109. package/dist/stacks/box/types.d.ts +3 -2
  110. package/dist/stacks/box/types.d.ts.map +1 -1
  111. package/dist/stacks/h_collapsible_box.js +14 -13
  112. package/dist/stacks/h_collapsible_box.js.map +1 -1
  113. package/dist/stacks/v_collapsible_box.js +14 -13
  114. package/dist/stacks/v_collapsible_box.js.map +1 -1
  115. package/dist/surfaces/alert/alert.js +7 -8
  116. package/dist/surfaces/alert/alert.js.map +1 -1
  117. package/dist/themes/stories/button_showcase.d.ts.map +1 -1
  118. package/dist/themes/stories/controls_fieldset.d.ts.map +1 -1
  119. package/dist/themes/stories/menu_showcase.d.ts.map +1 -1
  120. package/dist/themes/themes/ergo/ergo_theme.css +1 -1
  121. package/dist/themes/themes/ergo/ergo_theme.d.ts.map +1 -1
  122. package/dist/themes/themes/ergo/ergo_theme.js +336 -294
  123. package/dist/themes/themes/ergo/ergo_theme.js.map +1 -1
  124. package/dist/themes/themes/ergo/parts/actions.css +1 -0
  125. package/dist/themes/themes/ergo/parts/base.css +1 -0
  126. package/dist/themes/themes/ergo/parts/form.css +1 -0
  127. package/dist/themes/themes/ergo/parts/inputs.css +1 -0
  128. package/dist/themes/themes/ergo/parts/navigation.css +1 -0
  129. package/dist/themes/themes/windows_98/windows_98.css +1 -1
  130. package/dist/themes/themes/windows_98/windows_98_theme.js +32 -43
  131. package/dist/themes/themes/windows_98/windows_98_theme.js.map +1 -1
  132. package/dist/utils/decorators/clone_with_decorator.d.ts +21 -0
  133. package/dist/utils/decorators/clone_with_decorator.d.ts.map +1 -0
  134. package/dist/utils/decorators/clone_with_decorator.js +16 -0
  135. package/dist/utils/decorators/clone_with_decorator.js.map +1 -0
  136. package/dist/utils/decorators/draggable/context.d.ts.map +1 -0
  137. package/dist/utils/decorators/draggable/context.js.map +1 -0
  138. package/dist/utils/{dnd/handle.d.ts → decorators/draggable/drag_handle.d.ts} +1 -1
  139. package/dist/utils/decorators/draggable/drag_handle.d.ts.map +1 -0
  140. package/dist/utils/{dnd/handle.js → decorators/draggable/drag_handle.js} +2 -2
  141. package/dist/utils/decorators/draggable/drag_handle.js.map +1 -0
  142. package/dist/utils/decorators/draggable/draggable.d.ts.map +1 -0
  143. package/dist/utils/{dnd → decorators}/draggable/draggable.js +3 -3
  144. package/dist/utils/decorators/draggable/draggable.js.map +1 -0
  145. package/dist/utils/decorators/draggable/index.d.ts +11 -0
  146. package/dist/utils/decorators/draggable/index.d.ts.map +1 -0
  147. package/dist/utils/decorators/draggable/index.js +14 -0
  148. package/dist/utils/{dnd → decorators/draggable}/types.d.ts +1 -1
  149. package/dist/utils/decorators/draggable/types.d.ts.map +1 -0
  150. package/dist/utils/{dnd/hooks → decorators/draggable}/use_drag_container.d.ts +2 -2
  151. package/dist/utils/decorators/draggable/use_drag_container.d.ts.map +1 -0
  152. package/dist/utils/decorators/draggable/use_drag_container.js.map +1 -0
  153. package/dist/utils/decorators/draggable/use_draggable.d.ts.map +1 -0
  154. package/dist/utils/decorators/draggable/use_draggable.js.map +1 -0
  155. package/dist/utils/decorators/index.d.ts +3 -0
  156. package/dist/utils/decorators/index.d.ts.map +1 -0
  157. package/dist/utils/decorators/index.js +27 -0
  158. package/dist/utils/decorators/index.js.map +1 -0
  159. package/dist/utils/decorators/resizable/context.d.ts.map +1 -0
  160. package/dist/utils/{resize → decorators/resizable}/context.js +1 -1
  161. package/dist/utils/decorators/resizable/context.js.map +1 -0
  162. package/dist/utils/decorators/resizable/handle_config.d.ts.map +1 -0
  163. package/dist/utils/decorators/resizable/handle_config.js +62 -0
  164. package/dist/utils/decorators/resizable/handle_config.js.map +1 -0
  165. package/dist/utils/decorators/resizable/index.d.ts.map +1 -0
  166. package/dist/utils/decorators/resizable/index.js.map +1 -0
  167. package/dist/utils/decorators/resizable/resizable.d.ts.map +1 -0
  168. package/dist/utils/{resize → decorators/resizable}/resizable.js +2 -2
  169. package/dist/utils/decorators/resizable/resizable.js.map +1 -0
  170. package/dist/utils/decorators/resizable/resize_handle.d.ts.map +1 -0
  171. package/dist/utils/{resize → decorators/resizable}/resize_handle.js +2 -2
  172. package/dist/utils/decorators/resizable/resize_handle.js.map +1 -0
  173. package/dist/utils/{resize → decorators/resizable}/resize_strategy.d.ts +1 -1
  174. package/dist/utils/decorators/resizable/resize_strategy.d.ts.map +1 -0
  175. package/dist/utils/decorators/resizable/resize_strategy.js.map +1 -0
  176. package/dist/utils/{resize → decorators/resizable}/types.d.ts +2 -2
  177. package/dist/utils/decorators/resizable/types.d.ts.map +1 -0
  178. package/dist/utils/hooks/labelled_by_context.d.ts +21 -0
  179. package/dist/utils/hooks/labelled_by_context.d.ts.map +1 -0
  180. package/dist/utils/hooks/labelled_by_context.js +12 -0
  181. package/dist/utils/hooks/labelled_by_context.js.map +1 -0
  182. package/dist/utils/index.d.ts +8 -8
  183. package/dist/utils/index.d.ts.map +1 -1
  184. package/dist/utils/index.js +44 -40
  185. package/dist/utils/index.js.map +1 -1
  186. package/dist/utils/listeners/click_away_listener.d.ts.map +1 -0
  187. package/dist/utils/{click_away_listener.js → listeners/click_away_listener.js} +1 -1
  188. package/dist/utils/listeners/click_away_listener.js.map +1 -0
  189. package/dist/utils/listeners/focus_redirect.d.ts.map +1 -0
  190. package/dist/utils/listeners/focus_redirect.js.map +1 -0
  191. package/dist/utils/listeners/index.d.ts +4 -0
  192. package/dist/utils/listeners/index.d.ts.map +1 -0
  193. package/dist/utils/listeners/index.js +10 -0
  194. package/dist/utils/listeners/index.js.map +1 -0
  195. package/dist/utils/listeners/mouse_leave_region.d.ts.map +1 -0
  196. package/dist/utils/listeners/mouse_leave_region.js.map +1 -0
  197. package/dist/utils/listeners/scroll_away_listener.d.ts.map +1 -0
  198. package/dist/utils/{scroll_away_listener.js → listeners/scroll_away_listener.js} +1 -1
  199. package/dist/utils/listeners/scroll_away_listener.js.map +1 -0
  200. package/dist/utils/system/index.d.ts +2 -0
  201. package/dist/utils/system/index.d.ts.map +1 -0
  202. package/dist/utils/system/index.js +2 -0
  203. package/dist/utils/system/index.js.map +1 -0
  204. package/dist/utils/system/variations.d.ts.map +1 -0
  205. package/dist/utils/system/variations.js +2 -0
  206. package/dist/utils/system/variations.js.map +1 -0
  207. package/dist/utils/types/sides.d.ts +3 -0
  208. package/dist/utils/types/sides.d.ts.map +1 -0
  209. package/package.json +2 -8
  210. package/src/actions/button/__stories__/button_group.stories.tsx +23 -24
  211. package/src/actions/index.ts +0 -1
  212. package/src/form/field/field.stories.tsx +2 -2
  213. package/src/form/field/h_field/h_field.stories.tsx +1 -1
  214. package/src/form/field/v_field/v_field.stories.tsx +1 -1
  215. package/src/form/field_set/field_set.module.css +0 -14
  216. package/src/form/field_set/field_set.stories.tsx +101 -1
  217. package/src/form/field_set/field_set.tsx +43 -57
  218. package/src/form/field_set/legend.tsx +44 -0
  219. package/src/form/index.ts +6 -1
  220. package/src/inputs/date_picker/date_picker_header.tsx +7 -5
  221. package/src/inputs/date_picker/date_picker_year_selector.tsx +5 -5
  222. package/src/inputs/multiselect/multiselect_inline_values.tsx +4 -3
  223. package/src/inputs/multiselect/multiselect_values.module.css +1 -0
  224. package/src/inputs/multiselect/multiselect_values.tsx +4 -4
  225. package/src/overlay/frame/frame.stories.tsx +2 -1
  226. package/src/overlay/frame/frame.tsx +68 -20
  227. package/src/overlay/popper/base/dismissal_decorator.tsx +3 -3
  228. package/src/overlay/slide/slide.stories.tsx +1 -1
  229. package/src/stacks/box/box.tsx +29 -4
  230. package/src/stacks/box/end_resize_handle.tsx +1 -1
  231. package/src/stacks/box/resize_handlers.ts +1 -1
  232. package/src/stacks/box/start_resize_handle.tsx +1 -1
  233. package/src/stacks/box/types.ts +3 -2
  234. package/src/stacks/collapsible_box.stories.tsx +5 -5
  235. package/src/stacks/demo.stories.tsx +7 -7
  236. package/src/surfaces/page/page.stories.tsx +4 -4
  237. package/src/surfaces/window/window.stories.tsx +1 -1
  238. package/src/themes/stories/button_showcase.tsx +3 -1
  239. package/src/themes/stories/controls_fieldset.tsx +3 -1
  240. package/src/themes/stories/menu_showcase.tsx +3 -1
  241. package/src/themes/themes/ergo/INTERACTIVE.md +89 -0
  242. package/src/themes/themes/ergo/ROADMAP.md +116 -0
  243. package/src/themes/themes/ergo/ergo_theme.css +22 -717
  244. package/src/themes/themes/ergo/ergo_theme.ts +15 -1
  245. package/src/themes/themes/ergo/parts/actions.css +287 -0
  246. package/src/themes/themes/ergo/parts/base.css +62 -0
  247. package/src/themes/themes/ergo/parts/form.css +23 -0
  248. package/src/themes/themes/ergo/parts/inputs.css +252 -0
  249. package/src/themes/themes/ergo/parts/navigation.css +104 -0
  250. package/src/themes/themes/windows_98/windows_98.css +32 -43
  251. package/src/tokens/chip/chip.stories.tsx +5 -5
  252. package/src/utils/decorators/DECORATOR_PATTERN.md +86 -0
  253. package/src/utils/decorators/clone_with_decorator.ts +47 -0
  254. package/src/utils/{dnd → decorators/draggable}/__stories__/draggable.stories.tsx +7 -7
  255. package/src/utils/{dnd → decorators/draggable}/__stories__/use_draggable.stories.tsx +2 -2
  256. package/src/utils/{dnd/handle.tsx → decorators/draggable/drag_handle.tsx} +1 -1
  257. package/src/utils/{dnd → decorators}/draggable/draggable.tsx +2 -2
  258. package/src/utils/decorators/draggable/index.ts +15 -0
  259. package/src/utils/{dnd → decorators/draggable}/types.ts +1 -1
  260. package/src/utils/{dnd/hooks → decorators/draggable}/use_drag_container.ts +2 -2
  261. package/src/utils/decorators/index.ts +2 -0
  262. package/src/utils/{resize → decorators/resizable}/__stories__/resizable.stories.tsx +23 -23
  263. package/src/utils/{resize → decorators/resizable}/__tests__/handle_config.test.ts +19 -97
  264. package/src/utils/{resize → decorators/resizable}/__tests__/resize_strategy.test.ts +20 -20
  265. package/src/utils/{resize → decorators/resizable}/context.ts +1 -1
  266. package/src/utils/{resize → decorators/resizable}/handle_config.ts +7 -31
  267. package/src/utils/{resize → decorators/resizable}/resizable.tsx +1 -1
  268. package/src/utils/{resize → decorators/resizable}/resize_handle.module.css +1 -41
  269. package/src/utils/{resize → decorators/resizable}/resize_handle.tsx +1 -1
  270. package/src/utils/{resize → decorators/resizable}/resize_strategy.ts +1 -1
  271. package/src/utils/{resize → decorators/resizable}/types.ts +1 -7
  272. package/src/utils/hooks/labelled_by_context.ts +27 -0
  273. package/src/utils/index.ts +8 -8
  274. package/src/utils/{click_away_listener.tsx → listeners/click_away_listener.tsx} +1 -1
  275. package/src/utils/listeners/index.ts +3 -0
  276. package/src/utils/{scroll_away_listener.tsx → listeners/scroll_away_listener.tsx} +1 -1
  277. package/src/utils/system/index.ts +1 -0
  278. package/src/utils/types/sides.ts +2 -0
  279. package/dist/actions/button/slim_button/slim_button.d.ts +0 -9
  280. package/dist/actions/button/slim_button/slim_button.d.ts.map +0 -1
  281. package/dist/actions/button/slim_button/slim_button.js +0 -18
  282. package/dist/actions/button/slim_button/slim_button.js.map +0 -1
  283. package/dist/draggable.module-BgelQsuJ.js +0 -5
  284. package/dist/draggable.module-BgelQsuJ.js.map +0 -1
  285. package/dist/frame.css +0 -1
  286. package/dist/left_resize_handle.css +0 -1
  287. package/dist/resizable.module-I6iyBAvM.js +0 -5
  288. package/dist/resizable.module-I6iyBAvM.js.map +0 -1
  289. package/dist/right_resize_handle.css +0 -1
  290. package/dist/slim_button.css +0 -1
  291. package/dist/stacks/box/left_resize_handle.d.ts +0 -4
  292. package/dist/stacks/box/left_resize_handle.d.ts.map +0 -1
  293. package/dist/stacks/box/left_resize_handle.js +0 -36
  294. package/dist/stacks/box/left_resize_handle.js.map +0 -1
  295. package/dist/stacks/box/right_resize_handle.d.ts +0 -4
  296. package/dist/stacks/box/right_resize_handle.d.ts.map +0 -1
  297. package/dist/stacks/box/right_resize_handle.js +0 -36
  298. package/dist/stacks/box/right_resize_handle.js.map +0 -1
  299. package/dist/utils/click_away_listener.d.ts.map +0 -1
  300. package/dist/utils/click_away_listener.js.map +0 -1
  301. package/dist/utils/dnd/context.d.ts.map +0 -1
  302. package/dist/utils/dnd/context.js.map +0 -1
  303. package/dist/utils/dnd/draggable/draggable.d.ts.map +0 -1
  304. package/dist/utils/dnd/draggable/draggable.js.map +0 -1
  305. package/dist/utils/dnd/handle.d.ts.map +0 -1
  306. package/dist/utils/dnd/handle.js.map +0 -1
  307. package/dist/utils/dnd/hooks/use_drag_container.d.ts.map +0 -1
  308. package/dist/utils/dnd/hooks/use_drag_container.js.map +0 -1
  309. package/dist/utils/dnd/hooks/use_draggable.d.ts.map +0 -1
  310. package/dist/utils/dnd/hooks/use_draggable.js.map +0 -1
  311. package/dist/utils/dnd/types.d.ts.map +0 -1
  312. package/dist/utils/focus_redirect.d.ts.map +0 -1
  313. package/dist/utils/focus_redirect.js.map +0 -1
  314. package/dist/utils/mouse_leave_region.d.ts.map +0 -1
  315. package/dist/utils/mouse_leave_region.js.map +0 -1
  316. package/dist/utils/resize/context.d.ts.map +0 -1
  317. package/dist/utils/resize/context.js.map +0 -1
  318. package/dist/utils/resize/handle_config.d.ts.map +0 -1
  319. package/dist/utils/resize/handle_config.js +0 -85
  320. package/dist/utils/resize/handle_config.js.map +0 -1
  321. package/dist/utils/resize/index.d.ts.map +0 -1
  322. package/dist/utils/resize/resizable.d.ts.map +0 -1
  323. package/dist/utils/resize/resizable.js.map +0 -1
  324. package/dist/utils/resize/resize_handle.d.ts.map +0 -1
  325. package/dist/utils/resize/resize_handle.js.map +0 -1
  326. package/dist/utils/resize/resize_strategy.d.ts.map +0 -1
  327. package/dist/utils/resize/resize_strategy.js.map +0 -1
  328. package/dist/utils/resize/types.d.ts.map +0 -1
  329. package/dist/utils/scroll_away_listener.d.ts.map +0 -1
  330. package/dist/utils/scroll_away_listener.js.map +0 -1
  331. package/dist/utils/types/variations.d.ts.map +0 -1
  332. package/src/actions/button/__stories__/slim_button.stories.tsx +0 -274
  333. package/src/actions/button/slim_button/slim_button.module.css +0 -9
  334. package/src/actions/button/slim_button/slim_button.tsx +0 -26
  335. package/src/overlay/frame/frame.module.css +0 -5
  336. package/src/stacks/box/left_resize_handle.module.css +0 -12
  337. package/src/stacks/box/left_resize_handle.tsx +0 -39
  338. package/src/stacks/box/right_resize_handle.module.css +0 -12
  339. package/src/stacks/box/right_resize_handle.tsx +0 -38
  340. /package/dist/utils/{dnd → decorators/draggable}/context.d.ts +0 -0
  341. /package/dist/utils/{dnd → decorators/draggable}/context.js +0 -0
  342. /package/dist/utils/{dnd → decorators}/draggable/draggable.d.ts +0 -0
  343. /package/dist/utils/{resize → decorators/draggable}/index.js.map +0 -0
  344. /package/dist/utils/{dnd → decorators/draggable}/types.js +0 -0
  345. /package/dist/utils/{dnd → decorators/draggable}/types.js.map +0 -0
  346. /package/dist/utils/{dnd/hooks → decorators/draggable}/use_drag_container.js +0 -0
  347. /package/dist/utils/{dnd/hooks → decorators/draggable}/use_draggable.d.ts +0 -0
  348. /package/dist/utils/{dnd/hooks → decorators/draggable}/use_draggable.js +0 -0
  349. /package/dist/utils/{resize → decorators/resizable}/context.d.ts +0 -0
  350. /package/dist/utils/{resize → decorators/resizable}/handle_config.d.ts +0 -0
  351. /package/dist/utils/{resize → decorators/resizable}/index.d.ts +0 -0
  352. /package/dist/utils/{resize → decorators/resizable}/index.js +0 -0
  353. /package/dist/utils/{resize → decorators/resizable}/resizable.d.ts +0 -0
  354. /package/dist/utils/{resize → decorators/resizable}/resize_handle.d.ts +0 -0
  355. /package/dist/utils/{resize → decorators/resizable}/resize_strategy.js +0 -0
  356. /package/dist/utils/{resize → decorators/resizable}/types.js +0 -0
  357. /package/dist/utils/{resize → decorators/resizable}/types.js.map +0 -0
  358. /package/dist/utils/{click_away_listener.d.ts → listeners/click_away_listener.d.ts} +0 -0
  359. /package/dist/utils/{focus_redirect.d.ts → listeners/focus_redirect.d.ts} +0 -0
  360. /package/dist/utils/{focus_redirect.js → listeners/focus_redirect.js} +0 -0
  361. /package/dist/utils/{mouse_leave_region.d.ts → listeners/mouse_leave_region.d.ts} +0 -0
  362. /package/dist/utils/{mouse_leave_region.js → listeners/mouse_leave_region.js} +0 -0
  363. /package/dist/utils/{scroll_away_listener.d.ts → listeners/scroll_away_listener.d.ts} +0 -0
  364. /package/dist/utils/{types → system}/variations.d.ts +0 -0
  365. /package/src/utils/{dnd → decorators/draggable}/__stories__/draggable_stories.module.css +0 -0
  366. /package/src/utils/{dnd → decorators/draggable}/context.ts +0 -0
  367. /package/src/utils/{dnd → decorators}/draggable/draggable.module.css +0 -0
  368. /package/src/utils/{dnd/hooks → decorators/draggable}/use_draggable.ts +0 -0
  369. /package/src/utils/{resize → decorators/resizable}/__stories__/resizable_stories.module.css +0 -0
  370. /package/src/utils/{resize → decorators/resizable}/index.ts +0 -0
  371. /package/src/utils/{resize → decorators/resizable}/resizable.module.css +0 -0
  372. /package/src/utils/{click_away_listener.stories.tsx → listeners/click_away_listener.stories.tsx} +0 -0
  373. /package/src/utils/{focus_redirect.tsx → listeners/focus_redirect.tsx} +0 -0
  374. /package/src/utils/{mouse_leave_region.tsx → listeners/mouse_leave_region.tsx} +0 -0
  375. /package/src/utils/{scroll_away_listener.stories.tsx → listeners/scroll_away_listener.stories.tsx} +0 -0
  376. /package/src/utils/{types → system}/variations.ts +0 -0
@@ -1,6 +1,10 @@
1
1
  import { Divider } from '../../layouts/divider/divider.js';
2
+ import { BodyText } from '../../typography/index.js';
3
+ import { HStack } from '../../stacks/h_stack.js';
4
+ import { VStack } from '../../stacks/v_stack.js';
2
5
  import React, { useState } from 'react';
3
6
  import { FieldSet } from './field_set.js';
7
+ import { Legend } from './legend.js';
4
8
  import {
5
9
  Input,
6
10
  MaskInput,
@@ -8,11 +12,13 @@ import {
8
12
  Multiselect,
9
13
  PhoneNumberInput,
10
14
  Select,
15
+ Switch,
11
16
  Textarea,
12
17
  UnitInput,
13
18
  Option,
14
19
  } from '../../inputs/index.js';
15
20
  import { HField } from '../field/h_field/h_field.js';
21
+ import { Field } from '../field/field.js';
16
22
 
17
23
  export default {
18
24
  title: 'Form/Field Set',
@@ -34,7 +40,8 @@ export function Baseline() {
34
40
  );
35
41
 
36
42
  return (
37
- <FieldSet maxWidth="600px" minWidth="300px" legend="Fieldset" gap="8px" padding="8px">
43
+ <FieldSet maxWidth="600px" minWidth="300px">
44
+ <Legend>Fieldset</Legend>
38
45
  <HField label="Input" id="field-1">
39
46
  <Input />
40
47
  </HField>
@@ -109,3 +116,96 @@ export function Baseline() {
109
116
  </FieldSet>
110
117
  );
111
118
  }
119
+
120
+ export function Composition() {
121
+ return (
122
+ <FieldSet maxWidth="600px" minWidth="300px">
123
+ <Legend>Personal Information</Legend>
124
+ <HField label="Name" id="comp-field-1">
125
+ <Input />
126
+ </HField>
127
+ <HField label="Email" id="comp-field-2">
128
+ <Input />
129
+ </HField>
130
+ </FieldSet>
131
+ );
132
+ }
133
+
134
+ export function Disabled() {
135
+ return (
136
+ <FieldSet maxWidth="600px" minWidth="300px" disabled>
137
+ <Legend>Locked Section</Legend>
138
+ <HField label="Name" id="disabled-field-1">
139
+ <Input />
140
+ </HField>
141
+ <HField label="Email" id="disabled-field-2">
142
+ <Input placeholder="Field in disabled FieldSet..." />
143
+ </HField>
144
+ </FieldSet>
145
+ );
146
+ }
147
+
148
+ const HOLIDAYS = [
149
+ { name: "New Year's Day", date: 'January 1, 2026', day: 'Thursday' },
150
+ { name: 'Martin Luther King Jr. Day', date: 'January 19, 2026', day: 'Monday' },
151
+ { name: "Presidents' Day", date: 'February 16, 2026', day: 'Monday' },
152
+ { name: 'Memorial Day', date: 'May 25, 2026', day: 'Monday' },
153
+ { name: 'Independence Day', date: 'July 4, 2026', day: 'Saturday' },
154
+ { name: 'Labor Day', date: 'September 7, 2026', day: 'Monday' },
155
+ { name: 'Columbus Day', date: 'October 12, 2026', day: 'Monday' },
156
+ { name: 'Veterans Day', date: 'November 11, 2026', day: 'Wednesday' },
157
+ { name: 'Thanksgiving Day', date: 'November 26, 2026', day: 'Thursday' },
158
+ { name: 'Christmas Day', date: 'December 25, 2026', day: 'Friday' },
159
+ ];
160
+
161
+ export function CustomLegend() {
162
+ const [year, setYear] = useState('2026');
163
+ const [markAll, setMarkAll] = useState(false);
164
+ const [enabled, setEnabled] = useState<Record<string, boolean>>({});
165
+
166
+ return (
167
+ <FieldSet maxWidth="400px" minWidth="300px">
168
+ <Legend>
169
+ {/* TODO: https://git.tcncloud.net/blackcat-ui/blackcat/-/issues/321 — Replace VStack + hardcoded gap with a semantic container
170
+ (e.g. Rows) that has thematic context for direction shifts in smaller layouts */}
171
+ <VStack gap="8px" hAlign="start">
172
+ <HStack width="100%" hAlign="start">
173
+ <BodyText size="lg">Suggested Federal Holidays</BodyText>
174
+ </HStack>
175
+ <BodyText emphasis="faint">
176
+ Based on your selected timezone, the following U.S. federal holidays occur in{' '}
177
+ {year}. Enable the toggle to mark a holiday as a non-working day.
178
+ </BodyText>
179
+ <Field label="Year" id="holiday-year">
180
+ <Select value={year} onChange={setYear}>
181
+ <Option value="2025" label="2025">
182
+ 2025
183
+ </Option>
184
+ <Option value="2026" label="2026">
185
+ 2026
186
+ </Option>
187
+ <Option value="2027" label="2027">
188
+ 2027
189
+ </Option>
190
+ </Select>
191
+ </Field>
192
+ <HField label="Mark all holidays as non-working days" id="holiday-mark-all">
193
+ <Switch checked={markAll} onChange={setMarkAll} />
194
+ </HField>
195
+ </VStack>
196
+ </Legend>
197
+ {HOLIDAYS.map(holiday => (
198
+ <HField
199
+ key={holiday.name}
200
+ label={`${holiday.name} - ${holiday.date} (${holiday.day})`}
201
+ id={`holiday-${holiday.name.toLowerCase().replace(/\s+/g, '-')}`}
202
+ >
203
+ <Switch
204
+ checked={markAll || !!enabled[holiday.name]}
205
+ onChange={value => setEnabled(prev => ({ ...prev, [holiday.name]: value }))}
206
+ />
207
+ </HField>
208
+ ))}
209
+ </FieldSet>
210
+ );
211
+ }
@@ -1,67 +1,53 @@
1
- import { BodyText } from '../../typography/index.js';
2
- import { HStack } from '../../stacks/h_stack.js';
3
- import { Spacer } from '../../stacks/spacer.js';
4
1
  import { VStack } from '../../stacks/v_stack.js';
5
2
  import type { VStackProps } from '../../stacks/v_stack.js';
6
3
  import { clsx } from 'clsx';
7
- import React, { useMemo } from 'react';
4
+ import React, { type FieldsetHTMLAttributes } from 'react';
5
+ import { LabelledByContext } from '../../utils/hooks/labelled_by_context.js';
6
+ import { useLabelledById } from '../../utils/hooks/labelled_by_context.js';
8
7
  import styles from './field_set.module.css';
9
8
 
10
- let fieldsetIdCount = 0;
11
-
12
- export type FieldSetProps = VStackProps<HTMLFieldSetElement> & {
13
- legend?: string;
14
- startAdornments?: React.ReactNode;
15
- endAdornments?: React.ReactNode;
9
+ export type FieldSetOwnProps = {
10
+ disabled?: boolean;
11
+ name?: string;
16
12
  };
17
13
 
18
- export const FieldSet = React.forwardRef(function FieldSet(
19
- {
20
- legend,
21
- startAdornments,
22
- endAdornments,
23
- className,
24
- children,
25
- ...props
26
- }: FieldSetProps,
27
- ref: React.Ref<HTMLFieldSetElement>
28
- ) {
29
- const id = useMemo(() => {
30
- return fieldsetIdCount++;
31
- }, []);
14
+ export type FieldSetProps = VStackProps<HTMLFieldSetElement> &
15
+ FieldSetOwnProps &
16
+ FieldsetHTMLAttributes<HTMLFieldSetElement>;
32
17
 
33
- const labelId = `field-set-${id}`;
18
+ export const FieldSet = React.forwardRef<HTMLFieldSetElement, FieldSetProps>(
19
+ function FieldSet(
20
+ {
21
+ className,
22
+ id,
23
+ children,
24
+ 'aria-labelledby': ariaLabelledBy,
25
+ ...props
26
+ }: FieldSetProps,
27
+ ref
28
+ ) {
29
+ const { labelId } = useLabelledById(id, ariaLabelledBy);
34
30
 
35
- return (
36
- <VStack
37
- as="fieldset"
38
- aria-labelledby={labelId}
39
- ref={ref}
40
- className={clsx(styles['field-set'], className, 'tcn-field-set')}
41
- {...props}
42
- >
43
- {legend && (
44
- <HStack
45
- id={labelId}
46
- className={clsx('tcn-legend', 'tcn-field-set-legend')}
47
- hAlign="start"
48
- height={props.height}
31
+ return (
32
+ <LabelledByContext.Provider value={{ labelId }}>
33
+ <VStack
34
+ as="fieldset"
35
+ aria-labelledby={labelId}
36
+ ref={ref}
37
+ id={id}
38
+ data-is-disabled={props.disabled ? 'true' : 'false'}
39
+ className={clsx(styles['field-set'], className, 'tcn-field-set')}
40
+ {...props}
49
41
  >
50
- {startAdornments}
51
- {startAdornments && <Spacer width="8px" />}
52
- <BodyText className="tcn-field-set-legend-text" size="lg">
53
- {legend}
54
- </BodyText>
55
- {endAdornments && <Spacer />}
56
- {endAdornments}
57
- </HStack>
58
- )}
59
- <VStack
60
- className={clsx('tcn-field-set-body', styles['tcn-field-set-body'])}
61
- {...props}
62
- >
63
- {children}
64
- </VStack>
65
- </VStack>
66
- );
67
- });
42
+ {/* TODO: may want to ensure Legend is rendered before rest of children.
43
+ Search over children if a match is found for legend would pop it off the children array
44
+ and manually render it in the correct slot.
45
+ Before doing this however, may want to build Slot and Slottable util to generalize the problem/solution for re-useability.
46
+ */}
47
+ {children}
48
+ <fieldset disabled></fieldset>
49
+ </VStack>
50
+ </LabelledByContext.Provider>
51
+ );
52
+ }
53
+ );
@@ -0,0 +1,44 @@
1
+ import { clsx } from 'clsx';
2
+ import { HStack, type HStackProps } from '../../stacks/h_stack.js';
3
+ import { BodyText } from '../../typography/index.js';
4
+ import { useLabelledBy } from '../../utils/hooks/labelled_by_context.js';
5
+ import styles from './field_set.module.css';
6
+
7
+ export interface LegendOwnProps extends HStackProps {
8
+ id?: string;
9
+ className?: string;
10
+ children: React.ReactNode;
11
+ }
12
+
13
+ /**
14
+ * Composable legend for FieldSet. Renders as a div (HStack) with
15
+ * aria-labelledby wiring handled automatically via context.
16
+ *
17
+ * String children are automatically wrapped in BodyText with the
18
+ * `tcn-field-set-legend-text` class for consistent theme styling.
19
+ * Non-string children (e.g. icons, custom typography) render as-is.
20
+ *
21
+ * If a custom `id` is provided, it takes precedence over the context value.
22
+ * When overriding `id`, also provide a matching `aria-labelledby` to the
23
+ * parent FieldSet so the association remains correct.
24
+ */
25
+ export const Legend = ({ id, children, className, ...props }: LegendOwnProps) => {
26
+ const ctx = useLabelledBy();
27
+ const resolvedId = id ?? ctx?.labelId;
28
+
29
+ return (
30
+ <HStack
31
+ id={resolvedId}
32
+ className={clsx(className, styles.legend, 'tcn-legend', 'tcn-field-set-legend')}
33
+ {...props}
34
+ >
35
+ {typeof children === 'string' ? (
36
+ <BodyText className="tcn-field-set-legend-text" size="lg">
37
+ {children}
38
+ </BodyText>
39
+ ) : (
40
+ children
41
+ )}
42
+ </HStack>
43
+ );
44
+ };
package/src/form/index.ts CHANGED
@@ -46,5 +46,10 @@ export {
46
46
  type OptionsFieldState,
47
47
  type OptionsFieldOptions,
48
48
  } from './field_presenters/options_field_presenter.js';
49
- export { FieldSet, type FieldSetProps } from './field_set/field_set.js';
49
+ export {
50
+ FieldSet,
51
+ type FieldSetProps,
52
+ type FieldSetOwnProps,
53
+ } from './field_set/field_set.js';
54
+ export { Legend, type LegendOwnProps } from './field_set/legend.js';
50
55
  export { FormField } from './form_field.js';
@@ -2,7 +2,7 @@ import { useSignalValue, useSignalValueEffect } from '@tcn/state';
2
2
  import { HStack } from '../../stacks/h_stack.js';
3
3
  import { Spacer } from '../../stacks/spacer.js';
4
4
  import React, { useMemo, useRef } from 'react';
5
- import { SlimButton } from '../../actions/index.js';
5
+ import { Button } from '../../actions/index.js';
6
6
  import { getMonthsOfYear } from '../../utils/calendar/get_months_of_year.js';
7
7
  import { DatePickerPresenter } from './date_picker_presenter.js';
8
8
  import { Select } from '../select/select.js';
@@ -65,13 +65,14 @@ export function DatePickerHeader({ presenter, countryCode }: DatePickerHeaderPro
65
65
  minWidth="35px"
66
66
  width="100%"
67
67
  >
68
- <SlimButton
68
+ <Button
69
+ utility
69
70
  disabled={!state.canNavigateToPreviousMonth}
70
71
  hierarchy="tertiary"
71
72
  onClick={previous}
72
73
  >
73
74
  <ChevronLeftIcon flipOnRtl size="md" />
74
- </SlimButton>
75
+ </Button>
75
76
  <Spacer />
76
77
  <HStack hAlign="center" gap="4px" width="auto">
77
78
  <Select
@@ -86,13 +87,14 @@ export function DatePickerHeader({ presenter, countryCode }: DatePickerHeaderPro
86
87
  <DatePickerYearInput presenter={presenter} />
87
88
  </HStack>
88
89
  <Spacer />
89
- <SlimButton
90
+ <Button
91
+ utility
90
92
  disabled={!state.canNavigateToNextMonth}
91
93
  hierarchy="tertiary"
92
94
  onClick={next}
93
95
  >
94
96
  <ChevronRightIcon flipOnRtl size="md" />
95
- </SlimButton>
97
+ </Button>
96
98
  </HStack>
97
99
  );
98
100
  }
@@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from 'react';
2
2
  import { ChevronLeftIcon } from '@tcn/icons/chevron_left_icon.js';
3
3
  import { ChevronRightIcon } from '@tcn/icons/chevron_right_icon.js';
4
4
  import { useSignalValue } from '@tcn/state';
5
- import { SlimButton } from '../../actions/index.js';
5
+ import { Button } from '../../actions/index.js';
6
6
  import { HStack } from '../../stacks/h_stack.js';
7
7
  import { Spacer } from '../../stacks/spacer.js';
8
8
  import { VStack } from '../../stacks/v_stack.js';
@@ -102,9 +102,9 @@ export function DatePickerYearSelector({
102
102
  gap="4px"
103
103
  >
104
104
  <HStack gap="4px">
105
- <SlimButton onClick={prev} hierarchy="tertiary">
105
+ <Button utility onClick={prev} hierarchy="tertiary">
106
106
  <ChevronLeftIcon flipOnRtl size="md" />
107
- </SlimButton>
107
+ </Button>
108
108
  <Spacer />
109
109
  <Headline
110
110
  selectable={false}
@@ -112,9 +112,9 @@ export function DatePickerYearSelector({
112
112
  hierarchy="tertiary"
113
113
  >{`${firstYear}-${lastYear}`}</Headline>
114
114
  <Spacer />
115
- <SlimButton hierarchy="tertiary" onClick={next}>
115
+ <Button utility hierarchy="tertiary" onClick={next}>
116
116
  <ChevronRightIcon size="md" />
117
- </SlimButton>
117
+ </Button>
118
118
  </HStack>
119
119
  <HStack gap="4px">{firstRow}</HStack>
120
120
  <HStack gap="4px">{secondRow}</HStack>
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import styles from './multiselect_values.module.css';
3
3
  import { CrossIcon } from '@tcn/icons/cross_icon.js';
4
- import { SlimButton } from '../../actions/index.js';
4
+ import { Button } from '../../actions/index.js';
5
5
  import { OptionProps } from '../options/option.js';
6
6
  import { Chip } from '../../tokens/index.js';
7
7
  import clsx from 'clsx';
@@ -27,7 +27,8 @@ export function MultiselectInlineValues({
27
27
  width="auto"
28
28
  >
29
29
  <span>{v.props.label}</span>
30
- <SlimButton
30
+ <Button
31
+ utility
31
32
  disabled={disabled}
32
33
  size="sm"
33
34
  hierarchy="tertiary"
@@ -37,7 +38,7 @@ export function MultiselectInlineValues({
37
38
  }}
38
39
  >
39
40
  <CrossIcon size="xs" />
40
- </SlimButton>
41
+ </Button>
41
42
  </Chip>
42
43
  );
43
44
  });
@@ -12,6 +12,7 @@
12
12
  }
13
13
 
14
14
  :where(.item-container) {
15
+ box-sizing: border-box;
15
16
  background-color: #fff;
16
17
  border-radius: 4px;
17
18
  padding: 4px;
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import styles from './multiselect_values.module.css';
4
4
  import { CrossIcon } from '@tcn/icons/cross_icon.js';
5
5
  import { OptionProps } from '../options/option.js';
6
- import { SlimButton } from '../../actions/index.js';
6
+ import { Button } from '../../actions/index.js';
7
7
  import { Chip } from '../../tokens/index.js';
8
8
 
9
9
  export interface MultiselectValueProps {
@@ -23,13 +23,13 @@ export function MultiselectValues({
23
23
  return (
24
24
  <Chip
25
25
  hAlign="start"
26
- color="rgb(57, 85, 120)"
27
26
  className={clsx(styles.chip, 'tcn-multiselect-chip')}
28
27
  key={index}
29
28
  paddingInlineStart="8px"
30
29
  >
31
30
  <span>{v.props.label}</span>
32
- <SlimButton
31
+ <Button
32
+ utility
33
33
  disabled={disabled}
34
34
  size="sm"
35
35
  hierarchy="tertiary"
@@ -39,7 +39,7 @@ export function MultiselectValues({
39
39
  }}
40
40
  >
41
41
  <CrossIcon size="xs" />
42
- </SlimButton>
42
+ </Button>
43
43
  </Chip>
44
44
  );
45
45
  });
@@ -2,7 +2,7 @@ import { Header, Scaffold } from '../../layouts/index.js';
2
2
  import { ZStack } from '../../stacks/z_stack.js';
3
3
  import { BodyText } from '../../typography/index.js';
4
4
  import { Title } from '../../typography/title/title.js';
5
- import { DragHandle } from '../../utils/dnd/handle.js';
5
+ import { DragHandle } from '../../utils/decorators/draggable/drag_handle.js';
6
6
  import { Frame, type FrameOwnProps } from './frame.js';
7
7
  import styles from './frame_stories.module.css';
8
8
  export default {
@@ -24,6 +24,7 @@ export const FrameStory = (args: Omit<FrameOwnProps, 'children'>) => {
24
24
  <Frame
25
25
  width="300px"
26
26
  height="300px"
27
+ minWidth="100px"
27
28
  className={styles['sb-frame-container']}
28
29
  {...args}
29
30
  >
@@ -1,5 +1,5 @@
1
1
  import { clsx } from 'clsx';
2
- import React, { useCallback } from 'react';
2
+ import React, { useCallback, useRef } from 'react';
3
3
  import { flushSync } from 'react-dom';
4
4
  import {
5
5
  Box,
@@ -8,12 +8,14 @@ import {
8
8
  type OnHeightResizePayload,
9
9
  type OnWidthResizePayload,
10
10
  } from '../../stacks/index.js';
11
- import { useDragContainer } from '../../utils/dnd/context.js';
12
- import { Draggable } from '../../utils/dnd/draggable/draggable.js';
11
+ import { useDragContainer } from '../../utils/decorators/draggable/context.js';
12
+ import { Draggable } from '../../utils/decorators/draggable/draggable.js';
13
+ import { Resizable } from '../../utils/decorators/resizable/resizable.js';
14
+ import { ResizeHandle } from '../../utils/decorators/resizable/resize_handle.js';
13
15
  import { Portal } from '../portal/portal.js';
14
16
 
15
17
  // Styles
16
- import styles from './frame.module.css';
18
+
17
19
  export interface FrameOwnProps {
18
20
  isOpen?: boolean;
19
21
  draggable?: boolean;
@@ -37,6 +39,8 @@ export const Frame = React.forwardRef<HTMLElement, FrameProps>(function Frame(
37
39
  enableResizeOnEnd = true,
38
40
  enableResizeOnLeft = false,
39
41
  enableResizeOnRight = false,
42
+ minWidth = 1,
43
+ minHeight = 1,
40
44
  ...rest
41
45
  }: FrameProps,
42
46
  ref
@@ -56,6 +60,8 @@ export const Frame = React.forwardRef<HTMLElement, FrameProps>(function Frame(
56
60
  enableResizeOnRight={resizable && enableResizeOnRight}
57
61
  enableResizeOnLeft={resizable && enableResizeOnLeft}
58
62
  draggable={draggable}
63
+ minWidth={minWidth}
64
+ minHeight={minHeight}
59
65
  {...rest}
60
66
  >
61
67
  {children}
@@ -77,18 +83,36 @@ export const FrameDialog = React.forwardRef<HTMLElement, FrameDialogProps>(
77
83
  draggable,
78
84
  onWidthResize,
79
85
  onHeightResize,
86
+ onWidthResizeEnd,
87
+ onHeightResizeEnd,
88
+ enableResizeOnTop,
89
+ enableResizeOnBottom,
90
+ enableResizeOnStart,
91
+ enableResizeOnEnd,
92
+ enableResizeOnLeft,
93
+ enableResizeOnRight,
80
94
  ...rest
81
95
  }: FrameDialogProps,
82
96
  ref: React.Ref<HTMLElement>
83
97
  ) {
84
98
  const drag = useDragContainer();
99
+ const prevWidthRef = useRef<number | null>(null);
100
+ const prevHeightRef = useRef<number | null>(null);
85
101
 
86
102
  const handleWidthResize = React.useCallback(
87
103
  (payload: OnWidthResizePayload) => {
88
- if (!draggable) return;
89
- if (payload.currentDelta === 0) return;
90
- const sign = payload.origin === 'right' ? 1 : -1;
91
- const dx = (payload.currentDelta / 2) * sign;
104
+ const actualDelta =
105
+ prevWidthRef.current !== null
106
+ ? payload.width - prevWidthRef.current
107
+ : payload.currentDelta;
108
+ prevWidthRef.current = payload.width;
109
+
110
+ if (!draggable || actualDelta === 0) {
111
+ onWidthResize?.(payload);
112
+ return;
113
+ }
114
+ const sign = payload.origin === 'end' ? 1 : -1;
115
+ const dx = (actualDelta / 2) * sign;
92
116
  flushSync(() => {
93
117
  drag.setPosition(prev => ({
94
118
  x: prev.x + dx,
@@ -103,11 +127,18 @@ export const FrameDialog = React.forwardRef<HTMLElement, FrameDialogProps>(
103
127
 
104
128
  const handleHeightResize = useCallback(
105
129
  (payload: OnHeightResizePayload) => {
106
- if (!draggable) return;
107
- if (payload.currentDelta === 0) return;
130
+ const actualDelta =
131
+ prevHeightRef.current !== null
132
+ ? payload.height - prevHeightRef.current
133
+ : payload.currentDelta;
134
+ prevHeightRef.current = payload.height;
135
+
136
+ if (!draggable || actualDelta === 0) {
137
+ onHeightResize?.(payload);
138
+ return;
139
+ }
108
140
  const sign = payload.origin === 'bottom' ? 1 : -1;
109
- const half = payload.currentDelta / 2;
110
- const dy = half * sign;
141
+ const dy = (actualDelta / 2) * sign;
111
142
  flushSync(() => {
112
143
  drag.setPosition(prev => ({
113
144
  x: prev.x,
@@ -120,17 +151,34 @@ export const FrameDialog = React.forwardRef<HTMLElement, FrameDialogProps>(
120
151
  );
121
152
 
122
153
  return (
123
- <Box
124
- className={clsx(styles['frame-dialog'], 'tcn-frame-dialog', className)}
125
- ref={ref}
154
+ <Resizable
126
155
  onWidthResize={handleWidthResize}
127
156
  onHeightResize={handleHeightResize}
128
- as={as}
129
- role={role}
130
- {...rest}
157
+ onWidthResizeEnd={(width, origin) => {
158
+ prevWidthRef.current = null;
159
+ onWidthResizeEnd?.(width, origin);
160
+ }}
161
+ onHeightResizeEnd={(height, origin) => {
162
+ prevHeightRef.current = null;
163
+ onHeightResizeEnd?.(height, origin);
164
+ }}
131
165
  >
132
- {children}
133
- </Box>
166
+ <Box
167
+ className={clsx('tcn-frame', 'tcn-frame-dialog', className)}
168
+ ref={ref}
169
+ as={as}
170
+ role={role}
171
+ {...rest}
172
+ >
173
+ {children}
174
+ </Box>
175
+ {enableResizeOnTop && <ResizeHandle position="top" />}
176
+ {enableResizeOnBottom && <ResizeHandle position="bottom" />}
177
+ {enableResizeOnStart && <ResizeHandle position="start" />}
178
+ {enableResizeOnEnd && <ResizeHandle position="end" />}
179
+ {enableResizeOnLeft && <ResizeHandle position="start" />}
180
+ {enableResizeOnRight && <ResizeHandle position="end" />}
181
+ </Resizable>
134
182
  );
135
183
  }
136
184
  );
@@ -1,7 +1,7 @@
1
1
  import { forwardRef, type PropsWithChildren } from 'react';
2
- import { ClickAwayListener } from '../../../utils/click_away_listener.js';
3
- import { ScrollAwayListener } from '../../../utils/scroll_away_listener.js';
4
- import { MouseLeaveRegion } from '../../../utils/mouse_leave_region.js';
2
+ import { ClickAwayListener } from '../../../utils/listeners/click_away_listener.js';
3
+ import { ScrollAwayListener } from '../../../utils/listeners/scroll_away_listener.js';
4
+ import { MouseLeaveRegion } from '../../../utils/listeners/mouse_leave_region.js';
5
5
 
6
6
  export enum PopperDismissal {
7
7
  CLICK_AWAY = 'clickAway',
@@ -3,7 +3,7 @@ import { ZStack } from '../../stacks/z_stack.js';
3
3
  import { BodyText } from '../../typography/index.js';
4
4
  import { Title } from '../../typography/title/title.js';
5
5
  import { Slide, type SlideProps } from './slide.js';
6
- import { DragHandle } from '../../utils/dnd/handle.js';
6
+ import { DragHandle } from '../../utils/decorators/draggable/drag_handle.js';
7
7
 
8
8
  export default {
9
9
  title: 'Overlays/Floating/Slide',