@lattice-php/lattice 0.19.0 → 0.21.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 (343) hide show
  1. package/dist/action/components/action-form.d.ts +6 -1
  2. package/dist/action/components/action-form.js +34 -49
  3. package/dist/action/components/action-form.js.map +1 -1
  4. package/dist/action/components/action-trigger-provider.d.ts +1 -1
  5. package/dist/action/components/action-trigger-provider.js.map +1 -1
  6. package/dist/action/hooks/use-action.d.ts +1 -1
  7. package/dist/action/hooks/use-action.js +3 -1
  8. package/dist/action/hooks/use-action.js.map +1 -1
  9. package/dist/action/index.d.ts +0 -2
  10. package/dist/action/index.js +1 -2
  11. package/dist/chat/plugin.d.ts +0 -1
  12. package/dist/chat/plugin.js.map +1 -1
  13. package/dist/clipboard/index.d.ts +0 -4
  14. package/dist/clipboard/index.js +1 -15
  15. package/dist/{events → core}/event-names.js +1 -1
  16. package/dist/core/event-names.js.map +1 -0
  17. package/dist/core/hooks/use-window-event.d.ts +8 -0
  18. package/dist/core/hooks/use-window-event.js +22 -0
  19. package/dist/core/hooks/use-window-event.js.map +1 -0
  20. package/dist/core/index.js +1 -1
  21. package/dist/core/types.d.ts +8 -61
  22. package/dist/create-app.d.ts +31 -3
  23. package/dist/create-app.js +48 -10
  24. package/dist/create-app.js.map +1 -1
  25. package/dist/effects/dispatch.js +1 -1
  26. package/dist/effects/dispatch.js.map +1 -1
  27. package/dist/effects/registry.d.ts +2 -18
  28. package/dist/effects/registry.js +5 -9
  29. package/dist/effects/registry.js.map +1 -1
  30. package/dist/event-bridge.js +10 -23
  31. package/dist/event-bridge.js.map +1 -1
  32. package/dist/form/components/base/field.d.ts +2 -2
  33. package/dist/form/components/base/field.js +2 -2
  34. package/dist/form/components/base/field.js.map +1 -1
  35. package/dist/form/components/fields/color-picker-field.d.ts +2 -0
  36. package/dist/form/components/fields/color-picker-field.js +57 -0
  37. package/dist/form/components/fields/color-picker-field.js.map +1 -0
  38. package/dist/form/components/fields/date-input.js +1 -1
  39. package/dist/form/components/fields/date-time-input.js +1 -1
  40. package/dist/form/components/fields/file-upload.js +11 -18
  41. package/dist/form/components/fields/file-upload.js.map +1 -1
  42. package/dist/form/components/fields/number-input.js +1 -1
  43. package/dist/form/components/fields/rich-editor-field.js +35 -276
  44. package/dist/form/components/fields/rich-editor-field.js.map +1 -1
  45. package/dist/form/components/fields/row-action-menu.js +2 -2
  46. package/dist/form/components/fields/row-action-menu.js.map +1 -1
  47. package/dist/form/components/fields/row-actions.js +3 -1
  48. package/dist/form/components/fields/row-actions.js.map +1 -1
  49. package/dist/form/components/fields/select.js +60 -17
  50. package/dist/form/components/fields/select.js.map +1 -1
  51. package/dist/form/components/fields/table-rows.js +5 -17
  52. package/dist/form/components/fields/table-rows.js.map +1 -1
  53. package/dist/form/components/fields/text-input.js +8 -1
  54. package/dist/form/components/fields/text-input.js.map +1 -1
  55. package/dist/form/components/fields/time-input.js +1 -1
  56. package/dist/form/components/form.js +8 -23
  57. package/dist/form/components/form.js.map +1 -1
  58. package/dist/form/components/index.d.ts +1 -0
  59. package/dist/form/components/index.js +2 -1
  60. package/dist/form/embed.d.ts +5 -0
  61. package/dist/form/embed.js +4 -1
  62. package/dist/form/hooks/use-form-resolver.js.map +1 -1
  63. package/dist/form/index.js +2 -1
  64. package/dist/form/lib/collect-fields.d.ts +7 -0
  65. package/dist/form/lib/collect-fields.js +19 -0
  66. package/dist/form/lib/collect-fields.js.map +1 -0
  67. package/dist/form/lib/conditions.d.ts +4 -10
  68. package/dist/form/lib/conditions.js.map +1 -1
  69. package/dist/form/lib/field-errors.d.ts +3 -0
  70. package/dist/form/lib/field-errors.js +11 -0
  71. package/dist/form/lib/field-errors.js.map +1 -0
  72. package/dist/form/lib/field-props.d.ts +4 -18
  73. package/dist/form/lib/field-props.js.map +1 -1
  74. package/dist/form/plugin.js +2 -0
  75. package/dist/form/plugin.js.map +1 -1
  76. package/dist/form/rich-editor/builtins.d.ts +6 -0
  77. package/dist/form/rich-editor/builtins.js +400 -0
  78. package/dist/form/rich-editor/builtins.js.map +1 -0
  79. package/dist/form/rich-editor/index.d.ts +7 -0
  80. package/dist/form/rich-editor/index.js +3 -0
  81. package/dist/form/rich-editor/registry.d.ts +67 -0
  82. package/dist/form/rich-editor/registry.js +79 -0
  83. package/dist/form/rich-editor/registry.js.map +1 -0
  84. package/dist/form/rich-editor/toolbar-button.d.ts +12 -0
  85. package/dist/form/rich-editor/toolbar-button.js +28 -0
  86. package/dist/form/rich-editor/toolbar-button.js.map +1 -0
  87. package/dist/form/types.d.ts +1 -6
  88. package/dist/format/date-time.d.ts +3 -2
  89. package/dist/format/date-time.js.map +1 -1
  90. package/dist/format/format-context.d.ts +6 -0
  91. package/dist/format/format-context.js +17 -0
  92. package/dist/format/format-context.js.map +1 -0
  93. package/dist/i18n/date-time.d.ts +3 -2
  94. package/dist/i18n/date-time.js.map +1 -1
  95. package/dist/i18n/index.js +3 -2
  96. package/dist/i18n/locale-reload.d.ts +1 -1
  97. package/dist/i18n/locale-reload.js +7 -6
  98. package/dist/i18n/locale-reload.js.map +1 -1
  99. package/dist/i18n/locale.js +1 -1
  100. package/dist/i18n/locale.js.map +1 -1
  101. package/dist/i18n/page-props.d.ts +3 -2
  102. package/dist/i18n/page-props.js +1 -15
  103. package/dist/i18n/page-props.js.map +1 -1
  104. package/dist/i18n/shared-props.d.ts +7 -0
  105. package/dist/i18n/shared-props.js +23 -0
  106. package/dist/i18n/shared-props.js.map +1 -0
  107. package/dist/i18n/timezone.js +1 -1
  108. package/dist/i18n/timezone.js.map +1 -1
  109. package/dist/index.d.ts +11 -10
  110. package/dist/index.js +5 -5
  111. package/dist/lattice.css +212 -47
  112. package/dist/layout/components/breadcrumbs.js +3 -1
  113. package/dist/layout/components/breadcrumbs.js.map +1 -1
  114. package/dist/layout/components/sidebar.js +15 -48
  115. package/dist/layout/components/sidebar.js.map +1 -1
  116. package/dist/layout/plugin.d.ts +0 -1
  117. package/dist/layout/plugin.js.map +1 -1
  118. package/dist/lib/color.d.ts +9 -0
  119. package/dist/lib/color.js +48 -0
  120. package/dist/lib/color.js.map +1 -0
  121. package/dist/lib/is-truthy.d.ts +2 -0
  122. package/dist/lib/is-truthy.js +9 -0
  123. package/dist/lib/is-truthy.js.map +1 -0
  124. package/dist/lib/use-debounced-callback.d.ts +10 -0
  125. package/dist/lib/use-debounced-callback.js +34 -0
  126. package/dist/lib/use-debounced-callback.js.map +1 -0
  127. package/dist/lib/use-media-query.d.ts +5 -0
  128. package/dist/lib/use-media-query.js +26 -0
  129. package/dist/lib/use-media-query.js.map +1 -0
  130. package/dist/lib/use-persistent-state.d.ts +13 -0
  131. package/dist/lib/use-persistent-state.js +62 -0
  132. package/dist/lib/use-persistent-state.js.map +1 -0
  133. package/dist/notifications/api.d.ts +6 -6
  134. package/dist/notifications/api.js.map +1 -1
  135. package/dist/notifications/components/notifications.js +3 -1
  136. package/dist/notifications/components/notifications.js.map +1 -1
  137. package/dist/notifications/plugin.d.ts +0 -1
  138. package/dist/notifications/plugin.js.map +1 -1
  139. package/dist/notifications/types.d.ts +2 -10
  140. package/dist/provider-base.js +1 -1
  141. package/dist/realtime/build-effects.js +5 -5
  142. package/dist/realtime/build-effects.js.map +1 -1
  143. package/dist/realtime/listeners.d.ts +2 -2
  144. package/dist/realtime/listeners.js +1 -1
  145. package/dist/realtime/listeners.js.map +1 -1
  146. package/dist/realtime/subscriptions.d.ts +2 -2
  147. package/dist/realtime/subscriptions.js.map +1 -1
  148. package/dist/registry.d.ts +5 -0
  149. package/dist/registry.js.map +1 -1
  150. package/dist/remote/components/data-list.js +1 -1
  151. package/dist/remote/plugin.d.ts +0 -1
  152. package/dist/remote/plugin.js.map +1 -1
  153. package/dist/table/components/bulk-bar.js +7 -5
  154. package/dist/table/components/bulk-bar.js.map +1 -1
  155. package/dist/table/components/cells/badge-cell.js +4 -1
  156. package/dist/table/components/cells/badge-cell.js.map +1 -1
  157. package/dist/table/components/cells/boolean-cell.js +4 -4
  158. package/dist/table/components/cells/boolean-cell.js.map +1 -1
  159. package/dist/table/components/cells/copyable-cell.d.ts +9 -0
  160. package/dist/table/components/cells/copyable-cell.js +17 -0
  161. package/dist/table/components/cells/copyable-cell.js.map +1 -0
  162. package/dist/table/components/cells/icon-cell.js +5 -2
  163. package/dist/table/components/cells/icon-cell.js.map +1 -1
  164. package/dist/table/components/cells/image-cell.js +8 -9
  165. package/dist/table/components/cells/image-cell.js.map +1 -1
  166. package/dist/table/components/cells/money-cell.js +7 -10
  167. package/dist/table/components/cells/money-cell.js.map +1 -1
  168. package/dist/table/components/cells/number-cell.js +14 -19
  169. package/dist/table/components/cells/number-cell.js.map +1 -1
  170. package/dist/table/components/cells/numeric-cell.d.ts +10 -0
  171. package/dist/table/components/cells/numeric-cell.js +25 -0
  172. package/dist/table/components/cells/numeric-cell.js.map +1 -0
  173. package/dist/table/components/cells/stack-cell.js +1 -1
  174. package/dist/table/components/cells/text-cell.js +8 -6
  175. package/dist/table/components/cells/text-cell.js.map +1 -1
  176. package/dist/table/components/column-filter-control.js +25 -32
  177. package/dist/table/components/column-filter-control.js.map +1 -1
  178. package/dist/table/components/column-header.d.ts +3 -3
  179. package/dist/table/components/column-header.js +5 -3
  180. package/dist/table/components/column-header.js.map +1 -1
  181. package/dist/table/components/column-visibility-menu.js +6 -11
  182. package/dist/table/components/column-visibility-menu.js.map +1 -1
  183. package/dist/table/components/filter-bar.d.ts +2 -2
  184. package/dist/table/components/filter-bar.js +13 -22
  185. package/dist/table/components/filter-bar.js.map +1 -1
  186. package/dist/table/components/filter-controls.d.ts +2 -1
  187. package/dist/table/components/filter-controls.js +37 -38
  188. package/dist/table/components/filter-controls.js.map +1 -1
  189. package/dist/table/components/filter-value-input.d.ts +0 -1
  190. package/dist/table/components/filter-value-input.js +21 -20
  191. package/dist/table/components/filter-value-input.js.map +1 -1
  192. package/dist/table/components/pagination.js +16 -20
  193. package/dist/table/components/pagination.js.map +1 -1
  194. package/dist/table/components/sort-bar.d.ts +3 -3
  195. package/dist/table/components/sort-bar.js +11 -12
  196. package/dist/table/components/sort-bar.js.map +1 -1
  197. package/dist/table/components/table-cell.js.map +1 -1
  198. package/dist/table/components/table-search.d.ts +9 -0
  199. package/dist/table/components/table-search.js +72 -0
  200. package/dist/table/components/table-search.js.map +1 -0
  201. package/dist/table/components/table.js +73 -21
  202. package/dist/table/components/table.js.map +1 -1
  203. package/dist/table/hooks/use-column-visibility.js +29 -58
  204. package/dist/table/hooks/use-column-visibility.js.map +1 -1
  205. package/dist/table/hooks/use-expanded-rows.d.ts +8 -0
  206. package/dist/table/hooks/use-expanded-rows.js +24 -0
  207. package/dist/table/hooks/use-expanded-rows.js.map +1 -0
  208. package/dist/table/hooks/use-table.d.ts +5 -3
  209. package/dist/table/hooks/use-table.js +59 -55
  210. package/dist/table/hooks/use-table.js.map +1 -1
  211. package/dist/table/lib/bulk.d.ts +2 -0
  212. package/dist/table/lib/bulk.js +3 -1
  213. package/dist/table/lib/bulk.js.map +1 -1
  214. package/dist/table/lib/payload.d.ts +3 -2
  215. package/dist/table/lib/payload.js +16 -10
  216. package/dist/table/lib/payload.js.map +1 -1
  217. package/dist/table/lib/query.d.ts +5 -5
  218. package/dist/table/lib/query.js +21 -19
  219. package/dist/table/lib/query.js.map +1 -1
  220. package/dist/table/plugin.d.ts +0 -1
  221. package/dist/table/plugin.js.map +1 -1
  222. package/dist/table/types.d.ts +5 -81
  223. package/dist/toast/callout.js +2 -4
  224. package/dist/toast/callout.js.map +1 -1
  225. package/dist/toast/index.d.ts +1 -1
  226. package/dist/toast/index.js +2 -2
  227. package/dist/toast/toast.d.ts +1 -7
  228. package/dist/toast/toast.js +3 -15
  229. package/dist/toast/toast.js.map +1 -1
  230. package/dist/toast/toaster.js.map +1 -1
  231. package/dist/types/generated.d.ts +444 -225
  232. package/dist/types/index.d.ts +1 -1
  233. package/dist/ui/affix-group.d.ts +2 -1
  234. package/dist/ui/affix-group.js +9 -7
  235. package/dist/ui/affix-group.js.map +1 -1
  236. package/dist/ui/avatar.d.ts +3 -0
  237. package/dist/ui/avatar.js +52 -0
  238. package/dist/ui/avatar.js.map +1 -0
  239. package/dist/ui/button.d.ts +5 -3
  240. package/dist/ui/button.js +10 -3
  241. package/dist/ui/button.js.map +1 -1
  242. package/dist/ui/chart-view.js +155 -28
  243. package/dist/ui/chart-view.js.map +1 -1
  244. package/dist/ui/click-behavior.d.ts +4 -4
  245. package/dist/ui/click-behavior.js.map +1 -1
  246. package/dist/ui/collapsible.js +3 -15
  247. package/dist/ui/collapsible.js.map +1 -1
  248. package/dist/ui/color-picker.d.ts +8 -0
  249. package/dist/ui/color-picker.js +59 -0
  250. package/dist/ui/color-picker.js.map +1 -0
  251. package/dist/ui/combobox.d.ts +11 -2
  252. package/dist/ui/combobox.js +57 -11
  253. package/dist/ui/combobox.js.map +1 -1
  254. package/dist/ui/confirm-dialog.js +1 -1
  255. package/dist/ui/confirm-dialog.js.map +1 -1
  256. package/dist/ui/control.d.ts +1 -1
  257. package/dist/ui/copyable-text.d.ts +7 -0
  258. package/dist/ui/copyable-text.js +21 -13
  259. package/dist/ui/copyable-text.js.map +1 -1
  260. package/dist/ui/dialog.d.ts +6 -2
  261. package/dist/ui/dialog.js +29 -5
  262. package/dist/ui/dialog.js.map +1 -1
  263. package/dist/ui/fragment.js +1 -1
  264. package/dist/ui/fragment.js.map +1 -1
  265. package/dist/ui/heading.js +39 -21
  266. package/dist/ui/heading.js.map +1 -1
  267. package/dist/ui/icon-button.d.ts +22 -0
  268. package/dist/ui/icon-button.js +51 -0
  269. package/dist/ui/icon-button.js.map +1 -0
  270. package/dist/ui/icon.js +10 -11
  271. package/dist/ui/icon.js.map +1 -1
  272. package/dist/ui/image-preview.d.ts +12 -0
  273. package/dist/ui/image-preview.js +65 -0
  274. package/dist/ui/image-preview.js.map +1 -0
  275. package/dist/ui/image.d.ts +3 -0
  276. package/dist/ui/image.js +21 -0
  277. package/dist/ui/image.js.map +1 -0
  278. package/dist/ui/index.d.ts +2 -1
  279. package/dist/ui/index.js +4 -3
  280. package/dist/ui/info-tooltip.js +1 -1
  281. package/dist/ui/info-tooltip.js.map +1 -1
  282. package/dist/ui/input.d.ts +3 -1
  283. package/dist/ui/input.js +2 -2
  284. package/dist/ui/input.js.map +1 -1
  285. package/dist/ui/modal.js +17 -4
  286. package/dist/ui/modal.js.map +1 -1
  287. package/dist/ui/native-select.d.ts +10 -0
  288. package/dist/ui/native-select.js +23 -0
  289. package/dist/ui/native-select.js.map +1 -0
  290. package/dist/ui/pill.d.ts +2 -0
  291. package/dist/ui/pill.js +10 -0
  292. package/dist/ui/pill.js.map +1 -0
  293. package/dist/ui/plugin.js +11 -1
  294. package/dist/ui/plugin.js.map +1 -1
  295. package/dist/ui/progress.d.ts +3 -0
  296. package/dist/ui/progress.js +114 -0
  297. package/dist/ui/progress.js.map +1 -0
  298. package/dist/ui/section.js +2 -15
  299. package/dist/ui/section.js.map +1 -1
  300. package/dist/ui/segmented-pills.js +2 -1
  301. package/dist/ui/segmented-pills.js.map +1 -1
  302. package/dist/ui/separator.d.ts +3 -0
  303. package/dist/ui/separator.js +15 -0
  304. package/dist/ui/separator.js.map +1 -0
  305. package/dist/ui/tabs.js +12 -10
  306. package/dist/ui/tabs.js.map +1 -1
  307. package/dist/ui/text.js +5 -10
  308. package/dist/ui/text.js.map +1 -1
  309. package/dist/ui/tree-context.d.ts +33 -0
  310. package/dist/ui/tree-context.js +135 -0
  311. package/dist/ui/tree-context.js.map +1 -0
  312. package/dist/ui/tree.d.ts +19 -0
  313. package/dist/ui/tree.js +187 -0
  314. package/dist/ui/tree.js.map +1 -0
  315. package/dist/ui/use-collapsible-state.d.ts +7 -0
  316. package/dist/ui/use-collapsible-state.js +21 -0
  317. package/dist/ui/use-collapsible-state.js.map +1 -0
  318. package/dist-standalone/chunks/chart-view-C6R5iPra.js +36 -0
  319. package/dist-standalone/chunks/date-picker-field-DhhEB-Mh.js +1 -0
  320. package/dist-standalone/chunks/jsx-runtime-Drll_-DD.js +1 -0
  321. package/dist-standalone/chunks/locale-CXqr7LPR.js +1 -0
  322. package/dist-standalone/chunks/page-props-DOfg30l5.js +1 -0
  323. package/dist-standalone/chunks/rich-editor-field-DORXTHPw.js +154 -0
  324. package/dist-standalone/chunks/{subscriptions-B3UuDBmx.js → subscriptions-B_ISgA7V.js} +1 -1
  325. package/dist-standalone/chunks/use-effect-dispatcher-D1wPPwHj.js +97 -0
  326. package/dist-standalone/lattice.css +1 -1
  327. package/dist-standalone/lattice.js +15 -15
  328. package/dist-standalone/manifest.json +11 -9
  329. package/dist-standalone/sprite.svg +1 -1
  330. package/package.json +6 -1
  331. package/resources/icons/code-xml.svg +17 -0
  332. package/resources/icons/heading.svg +17 -0
  333. package/dist/clipboard/index.js.map +0 -1
  334. package/dist/events/event-names.js.map +0 -1
  335. package/dist/table/components/table-action-node.d.ts +0 -4
  336. package/dist/table/components/table-action-node.js +0 -24
  337. package/dist/table/components/table-action-node.js.map +0 -1
  338. package/dist-standalone/chunks/chart-view-CK5fKIkR.js +0 -36
  339. package/dist-standalone/chunks/date-picker-field-BlCPFhZd.js +0 -1
  340. package/dist-standalone/chunks/jsx-runtime-CJ_btYLc.js +0 -1
  341. package/dist-standalone/chunks/rich-editor-field-DH5dS5c1.js +0 -154
  342. package/dist-standalone/chunks/use-effect-dispatcher-k98Nzf9M.js +0 -97
  343. /package/dist/{events → core}/event-names.d.ts +0 -0
package/dist/ui/plugin.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { createPlugin, eagerComponent } from "../core/registry.js";
2
2
  import ButtonComponent from "./button.js";
3
+ import AvatarComponent from "./avatar.js";
3
4
  import BadgeComponent from "./badge.js";
4
5
  import CardComponent from "./card.js";
5
6
  import ChartComponent from "./chart.js";
@@ -9,18 +10,23 @@ import FragmentComponent from "./fragment.js";
9
10
  import GridComponent from "./grid.js";
10
11
  import HeadingComponent from "./heading.js";
11
12
  import IconComponent from "./icon.js";
13
+ import ImageComponent from "./image.js";
12
14
  import LinkComponent from "./link.js";
13
15
  import ModalComponent from "./modal.js";
16
+ import ProgressComponent from "./progress.js";
14
17
  import RawBlockComponent from "./raw-block.js";
15
18
  import SectionComponent from "./section.js";
16
19
  import SegmentedControlComponent from "./segmented-control.js";
20
+ import SeparatorComponent from "./separator.js";
17
21
  import StackComponent from "./stack.js";
18
22
  import TabComponent, { TabsComponent } from "./tabs.js";
19
23
  import TextComponent from "./text.js";
20
24
  import TooltipComponent from "./tooltip.js";
25
+ import TreeComponent from "./tree.js";
21
26
  //#region resources/js/ui/plugin.ts
22
27
  var uiComponents = createPlugin({
23
28
  components: {
29
+ avatar: eagerComponent(AvatarComponent),
24
30
  badge: eagerComponent(BadgeComponent),
25
31
  button: eagerComponent(ButtonComponent),
26
32
  card: eagerComponent(CardComponent),
@@ -31,16 +37,20 @@ var uiComponents = createPlugin({
31
37
  grid: eagerComponent(GridComponent),
32
38
  heading: eagerComponent(HeadingComponent),
33
39
  icon: eagerComponent(IconComponent),
40
+ image: eagerComponent(ImageComponent),
34
41
  link: eagerComponent(LinkComponent),
35
42
  modal: eagerComponent(ModalComponent),
43
+ progress: eagerComponent(ProgressComponent),
36
44
  "raw-block": eagerComponent(RawBlockComponent),
37
45
  section: eagerComponent(SectionComponent),
38
46
  "segmented-control": eagerComponent(SegmentedControlComponent),
47
+ separator: eagerComponent(SeparatorComponent),
39
48
  stack: eagerComponent(StackComponent),
40
49
  tab: eagerComponent(TabComponent),
41
50
  tabs: eagerComponent(TabsComponent),
42
51
  text: eagerComponent(TextComponent),
43
- tooltip: eagerComponent(TooltipComponent)
52
+ tooltip: eagerComponent(TooltipComponent),
53
+ tree: eagerComponent(TreeComponent)
44
54
  },
45
55
  name: "lattice/ui"
46
56
  });
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","names":[],"sources":["../../resources/js/ui/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n eagerComponent,\n type ComponentRegistryFor,\n} from \"@lattice-php/lattice/core/registry\";\nimport type { ActionNodeType, FormNodeType, NodeType } from \"@lattice-php/lattice/types/generated\";\nimport type { ChatComponentType } from \"@lattice-php/lattice/chat/plugin\";\nimport type { LayoutComponentType } from \"@lattice-php/lattice/layout/plugin\";\nimport type { NotificationsComponentType } from \"@lattice-php/lattice/notifications/plugin\";\nimport type { RemoteComponentType } from \"@lattice-php/lattice/remote/plugin\";\nimport type { TableComponentType } from \"@lattice-php/lattice/table/plugin\";\nimport BadgeComponent from \"./badge\";\nimport ButtonComponent from \"./button\";\nimport CardComponent from \"./card\";\nimport ChartComponent from \"./chart\";\nimport CollapsibleComponent from \"./collapsible\";\nimport FloatingPanelComponent from \"./floating-panel\";\nimport FragmentComponent from \"./fragment\";\nimport GridComponent from \"./grid\";\nimport HeadingComponent from \"./heading\";\nimport IconComponent from \"./icon\";\nimport LinkComponent from \"./link\";\nimport ModalComponent from \"./modal\";\nimport RawBlockComponent from \"./raw-block\";\nimport SectionComponent from \"./section\";\nimport SegmentedControlComponent from \"./segmented-control\";\nimport StackComponent from \"./stack\";\nimport TabComponent, { TabsComponent } from \"./tabs\";\nimport TextComponent from \"./text\";\nimport TooltipComponent from \"./tooltip\";\n\ntype NonUiComponentType =\n | ActionNodeType\n | ChatComponentType\n | FormNodeType\n | LayoutComponentType\n | NotificationsComponentType\n | RemoteComponentType\n | TableComponentType;\n\ntype UiComponentType = Exclude<NodeType, NonUiComponentType>;\n\nexport const uiComponents = createPlugin({\n components: {\n badge: eagerComponent(BadgeComponent),\n button: eagerComponent(ButtonComponent),\n card: eagerComponent(CardComponent),\n chart: eagerComponent(ChartComponent),\n collapsible: eagerComponent(CollapsibleComponent),\n \"floating-panel\": eagerComponent(FloatingPanelComponent),\n fragment: eagerComponent(FragmentComponent),\n grid: eagerComponent(GridComponent),\n heading: eagerComponent(HeadingComponent),\n icon: eagerComponent(IconComponent),\n link: eagerComponent(LinkComponent),\n modal: eagerComponent(ModalComponent),\n \"raw-block\": eagerComponent(RawBlockComponent),\n section: eagerComponent(SectionComponent),\n \"segmented-control\": eagerComponent(SegmentedControlComponent),\n stack: eagerComponent(StackComponent),\n tab: eagerComponent(TabComponent),\n tabs: eagerComponent(TabsComponent),\n text: eagerComponent(TextComponent),\n tooltip: eagerComponent(TooltipComponent),\n } satisfies ComponentRegistryFor<UiComponentType>,\n name: \"lattice/ui\",\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA0CA,IAAa,eAAe,aAAa;CACvC,YAAY;EACV,OAAO,eAAe,cAAc;EACpC,QAAQ,eAAe,eAAe;EACtC,MAAM,eAAe,aAAa;EAClC,OAAO,eAAe,cAAc;EACpC,aAAa,eAAe,oBAAoB;EAChD,kBAAkB,eAAe,sBAAsB;EACvD,UAAU,eAAe,iBAAiB;EAC1C,MAAM,eAAe,aAAa;EAClC,SAAS,eAAe,gBAAgB;EACxC,MAAM,eAAe,aAAa;EAClC,MAAM,eAAe,aAAa;EAClC,OAAO,eAAe,cAAc;EACpC,aAAa,eAAe,iBAAiB;EAC7C,SAAS,eAAe,gBAAgB;EACxC,qBAAqB,eAAe,yBAAyB;EAC7D,OAAO,eAAe,cAAc;EACpC,KAAK,eAAe,YAAY;EAChC,MAAM,eAAe,aAAa;EAClC,MAAM,eAAe,aAAa;EAClC,SAAS,eAAe,gBAAgB;CAC1C;CACA,MAAM;AACR,CAAC"}
1
+ {"version":3,"file":"plugin.js","names":[],"sources":["../../resources/js/ui/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n eagerComponent,\n type ComponentRegistryFor,\n} from \"@lattice-php/lattice/core/registry\";\nimport type { FragmentNodeType, UiNodeType } from \"@lattice-php/lattice/types/generated\";\nimport AvatarComponent from \"./avatar\";\nimport BadgeComponent from \"./badge\";\nimport ButtonComponent from \"./button\";\nimport CardComponent from \"./card\";\nimport ChartComponent from \"./chart\";\nimport CollapsibleComponent from \"./collapsible\";\nimport FloatingPanelComponent from \"./floating-panel\";\nimport FragmentComponent from \"./fragment\";\nimport GridComponent from \"./grid\";\nimport HeadingComponent from \"./heading\";\nimport IconComponent from \"./icon\";\nimport ImageComponent from \"./image\";\nimport LinkComponent from \"./link\";\nimport ModalComponent from \"./modal\";\nimport ProgressComponent from \"./progress\";\nimport RawBlockComponent from \"./raw-block\";\nimport SectionComponent from \"./section\";\nimport SegmentedControlComponent from \"./segmented-control\";\nimport SeparatorComponent from \"./separator\";\nimport StackComponent from \"./stack\";\nimport TabComponent, { TabsComponent } from \"./tabs\";\nimport TextComponent from \"./text\";\nimport TooltipComponent from \"./tooltip\";\nimport TreeComponent from \"./tree\";\n\ntype UiComponentType = UiNodeType | FragmentNodeType;\n\nexport const uiComponents = createPlugin({\n components: {\n avatar: eagerComponent(AvatarComponent),\n badge: eagerComponent(BadgeComponent),\n button: eagerComponent(ButtonComponent),\n card: eagerComponent(CardComponent),\n chart: eagerComponent(ChartComponent),\n collapsible: eagerComponent(CollapsibleComponent),\n \"floating-panel\": eagerComponent(FloatingPanelComponent),\n fragment: eagerComponent(FragmentComponent),\n grid: eagerComponent(GridComponent),\n heading: eagerComponent(HeadingComponent),\n icon: eagerComponent(IconComponent),\n image: eagerComponent(ImageComponent),\n link: eagerComponent(LinkComponent),\n modal: eagerComponent(ModalComponent),\n progress: eagerComponent(ProgressComponent),\n \"raw-block\": eagerComponent(RawBlockComponent),\n section: eagerComponent(SectionComponent),\n \"segmented-control\": eagerComponent(SegmentedControlComponent),\n separator: eagerComponent(SeparatorComponent),\n stack: eagerComponent(StackComponent),\n tab: eagerComponent(TabComponent),\n tabs: eagerComponent(TabsComponent),\n text: eagerComponent(TextComponent),\n tooltip: eagerComponent(TooltipComponent),\n tree: eagerComponent(TreeComponent),\n } satisfies ComponentRegistryFor<UiComponentType>,\n name: \"lattice/ui\",\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAa,eAAe,aAAa;CACvC,YAAY;EACV,QAAQ,eAAe,eAAe;EACtC,OAAO,eAAe,cAAc;EACpC,QAAQ,eAAe,eAAe;EACtC,MAAM,eAAe,aAAa;EAClC,OAAO,eAAe,cAAc;EACpC,aAAa,eAAe,oBAAoB;EAChD,kBAAkB,eAAe,sBAAsB;EACvD,UAAU,eAAe,iBAAiB;EAC1C,MAAM,eAAe,aAAa;EAClC,SAAS,eAAe,gBAAgB;EACxC,MAAM,eAAe,aAAa;EAClC,OAAO,eAAe,cAAc;EACpC,MAAM,eAAe,aAAa;EAClC,OAAO,eAAe,cAAc;EACpC,UAAU,eAAe,iBAAiB;EAC1C,aAAa,eAAe,iBAAiB;EAC7C,SAAS,eAAe,gBAAgB;EACxC,qBAAqB,eAAe,yBAAyB;EAC7D,WAAW,eAAe,kBAAkB;EAC5C,OAAO,eAAe,cAAc;EACpC,KAAK,eAAe,YAAY;EAChC,MAAM,eAAe,aAAa;EAClC,MAAM,eAAe,aAAa;EAClC,SAAS,eAAe,gBAAgB;EACxC,MAAM,eAAe,aAAa;CACpC;CACA,MAAM;AACR,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { RendererComponent } from '../core/types.js';
2
+ declare const ProgressComponent: RendererComponent<"progress">;
3
+ export default ProgressComponent;
@@ -0,0 +1,114 @@
1
+ import { useLocale } from "../i18n/locale.js";
2
+ import { cn } from "../lib/utils.js";
3
+ import { coerceColor, colorValue, namedColor } from "../lib/color.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ //#region resources/js/ui/progress.tsx
6
+ var barHeights = {
7
+ xs: "h-1",
8
+ sm: "h-1.5",
9
+ md: "h-2.5",
10
+ lg: "h-3",
11
+ xl: "h-4",
12
+ "2xl": "h-5",
13
+ "3xl": "h-6",
14
+ "4xl": "h-8"
15
+ };
16
+ var circleDiameters = {
17
+ xs: 24,
18
+ sm: 32,
19
+ md: 40,
20
+ lg: 48,
21
+ xl: 64,
22
+ "2xl": 80,
23
+ "3xl": 96,
24
+ "4xl": 128
25
+ };
26
+ var circleReadouts = {
27
+ xs: "text-[0.5rem]",
28
+ sm: "text-[0.625rem]",
29
+ md: "text-xs",
30
+ lg: "text-sm",
31
+ xl: "text-base",
32
+ "2xl": "text-lg",
33
+ "3xl": "text-xl",
34
+ "4xl": "text-2xl"
35
+ };
36
+ var ProgressComponent = ({ node }) => {
37
+ const { value, max, variant, showValue, color, size } = node.props;
38
+ const { locale } = useLocale();
39
+ const paint = colorValue(coerceColor(color) ?? namedColor("primary"));
40
+ const clamped = max > 0 ? Math.min(Math.max(value, 0), max) : 0;
41
+ const ratio = max > 0 ? clamped / max : 0;
42
+ const percent = new Intl.NumberFormat(locale, {
43
+ maximumFractionDigits: 0,
44
+ style: "percent"
45
+ }).format(ratio);
46
+ const aria = {
47
+ "aria-valuemax": max,
48
+ "aria-valuemin": 0,
49
+ "aria-valuenow": clamped,
50
+ "aria-valuetext": percent,
51
+ role: "progressbar"
52
+ };
53
+ if (variant === "circle") {
54
+ const diameter = circleDiameters[size];
55
+ const strokeWidth = Math.max(3, diameter / 10);
56
+ const radius = (diameter - strokeWidth) / 2;
57
+ const circumference = 2 * Math.PI * radius;
58
+ return /* @__PURE__ */ jsxs("div", {
59
+ ...aria,
60
+ className: "relative inline-flex",
61
+ "data-lattice-progress": "circle",
62
+ children: [/* @__PURE__ */ jsxs("svg", {
63
+ className: "-rotate-90",
64
+ height: diameter,
65
+ width: diameter,
66
+ children: [/* @__PURE__ */ jsx("circle", {
67
+ className: "text-lt-muted",
68
+ cx: diameter / 2,
69
+ cy: diameter / 2,
70
+ fill: "none",
71
+ r: radius,
72
+ stroke: "currentColor",
73
+ strokeWidth
74
+ }), /* @__PURE__ */ jsx("circle", {
75
+ cx: diameter / 2,
76
+ cy: diameter / 2,
77
+ fill: "none",
78
+ r: radius,
79
+ stroke: "currentColor",
80
+ strokeDasharray: circumference,
81
+ strokeDashoffset: circumference * (1 - ratio),
82
+ strokeLinecap: "round",
83
+ strokeWidth,
84
+ style: { color: paint }
85
+ })]
86
+ }), showValue && /* @__PURE__ */ jsx("span", {
87
+ className: cn("absolute inset-0 flex items-center justify-center font-medium text-lt-fg tabular-nums", circleReadouts[size]),
88
+ children: percent
89
+ })]
90
+ });
91
+ }
92
+ return /* @__PURE__ */ jsxs("div", {
93
+ className: "flex w-full items-center gap-2",
94
+ "data-lattice-progress": "bar",
95
+ children: [/* @__PURE__ */ jsx("div", {
96
+ ...aria,
97
+ className: cn("w-full overflow-hidden rounded-full bg-lt-muted", barHeights[size]),
98
+ children: /* @__PURE__ */ jsx("div", {
99
+ className: "h-full rounded-full",
100
+ style: {
101
+ background: paint,
102
+ width: `${ratio * 100}%`
103
+ }
104
+ })
105
+ }), showValue && /* @__PURE__ */ jsx("span", {
106
+ className: "shrink-0 text-lt-muted-fg text-sm tabular-nums",
107
+ children: percent
108
+ })]
109
+ });
110
+ };
111
+ //#endregion
112
+ export { ProgressComponent as default };
113
+
114
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","names":[],"sources":["../../resources/js/ui/progress.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { useLocale } from \"@lattice-php/lattice/i18n\";\nimport { coerceColor, colorValue, namedColor } from \"@lattice-php/lattice/lib/color\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { Size } from \"@lattice-php/lattice/types/generated\";\n\nconst barHeights: Record<Size, string> = {\n xs: \"h-1\",\n sm: \"h-1.5\",\n md: \"h-2.5\",\n lg: \"h-3\",\n xl: \"h-4\",\n \"2xl\": \"h-5\",\n \"3xl\": \"h-6\",\n \"4xl\": \"h-8\",\n};\n\nconst circleDiameters: Record<Size, number> = {\n xs: 24,\n sm: 32,\n md: 40,\n lg: 48,\n xl: 64,\n \"2xl\": 80,\n \"3xl\": 96,\n \"4xl\": 128,\n};\n\nconst circleReadouts: Record<Size, string> = {\n xs: \"text-[0.5rem]\",\n sm: \"text-[0.625rem]\",\n md: \"text-xs\",\n lg: \"text-sm\",\n xl: \"text-base\",\n \"2xl\": \"text-lg\",\n \"3xl\": \"text-xl\",\n \"4xl\": \"text-2xl\",\n};\n\nconst ProgressComponent: RendererComponent<\"progress\"> = ({ node }) => {\n const { value, max, variant, showValue, color, size } = node.props;\n const { locale } = useLocale();\n const paint = colorValue(coerceColor(color) ?? namedColor(\"primary\"));\n\n const clamped = max > 0 ? Math.min(Math.max(value, 0), max) : 0;\n const ratio = max > 0 ? clamped / max : 0;\n const percent = new Intl.NumberFormat(locale, {\n maximumFractionDigits: 0,\n style: \"percent\",\n }).format(ratio);\n\n const aria = {\n \"aria-valuemax\": max,\n \"aria-valuemin\": 0,\n \"aria-valuenow\": clamped,\n \"aria-valuetext\": percent,\n role: \"progressbar\",\n } as const;\n\n if (variant === \"circle\") {\n const diameter = circleDiameters[size];\n const strokeWidth = Math.max(3, diameter / 10);\n const radius = (diameter - strokeWidth) / 2;\n const circumference = 2 * Math.PI * radius;\n\n return (\n <div {...aria} className=\"relative inline-flex\" data-lattice-progress=\"circle\">\n <svg className=\"-rotate-90\" height={diameter} width={diameter}>\n <circle\n className=\"text-lt-muted\"\n cx={diameter / 2}\n cy={diameter / 2}\n fill=\"none\"\n r={radius}\n stroke=\"currentColor\"\n strokeWidth={strokeWidth}\n />\n <circle\n cx={diameter / 2}\n cy={diameter / 2}\n fill=\"none\"\n r={radius}\n stroke=\"currentColor\"\n strokeDasharray={circumference}\n strokeDashoffset={circumference * (1 - ratio)}\n strokeLinecap=\"round\"\n strokeWidth={strokeWidth}\n style={{ color: paint }}\n />\n </svg>\n {showValue && (\n <span\n className={cn(\n \"absolute inset-0 flex items-center justify-center font-medium text-lt-fg tabular-nums\",\n circleReadouts[size],\n )}\n >\n {percent}\n </span>\n )}\n </div>\n );\n }\n\n return (\n <div className=\"flex w-full items-center gap-2\" data-lattice-progress=\"bar\">\n <div\n {...aria}\n className={cn(\"w-full overflow-hidden rounded-full bg-lt-muted\", barHeights[size])}\n >\n <div\n className=\"h-full rounded-full\"\n style={{ background: paint, width: `${ratio * 100}%` }}\n />\n </div>\n {showValue && (\n <span className=\"shrink-0 text-lt-muted-fg text-sm tabular-nums\">{percent}</span>\n )}\n </div>\n );\n};\n\nexport default ProgressComponent;\n"],"mappings":";;;;;AAMA,IAAM,aAAmC;CACvC,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,OAAO;AACT;AAEA,IAAM,kBAAwC;CAC5C,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,OAAO;AACT;AAEA,IAAM,iBAAuC;CAC3C,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,OAAO;AACT;AAEA,IAAM,qBAAoD,EAAE,WAAW;CACrE,MAAM,EAAE,OAAO,KAAK,SAAS,WAAW,OAAO,SAAS,KAAK;CAC7D,MAAM,EAAE,WAAW,UAAU;CAC7B,MAAM,QAAQ,WAAW,YAAY,KAAK,KAAK,WAAW,SAAS,CAAC;CAEpE,MAAM,UAAU,MAAM,IAAI,KAAK,IAAI,KAAK,IAAI,OAAO,CAAC,GAAG,GAAG,IAAI;CAC9D,MAAM,QAAQ,MAAM,IAAI,UAAU,MAAM;CACxC,MAAM,UAAU,IAAI,KAAK,aAAa,QAAQ;EAC5C,uBAAuB;EACvB,OAAO;CACT,CAAC,EAAE,OAAO,KAAK;CAEf,MAAM,OAAO;EACX,iBAAiB;EACjB,iBAAiB;EACjB,iBAAiB;EACjB,kBAAkB;EAClB,MAAM;CACR;CAEA,IAAI,YAAY,UAAU;EACxB,MAAM,WAAW,gBAAgB;EACjC,MAAM,cAAc,KAAK,IAAI,GAAG,WAAW,EAAE;EAC7C,MAAM,UAAU,WAAW,eAAe;EAC1C,MAAM,gBAAgB,IAAI,KAAK,KAAK;EAEpC,OACE,qBAAC,OAAD;GAAK,GAAI;GAAM,WAAU;GAAuB,yBAAsB;aAAtE,CACE,qBAAC,OAAD;IAAK,WAAU;IAAa,QAAQ;IAAU,OAAO;cAArD,CACE,oBAAC,UAAD;KACE,WAAU;KACV,IAAI,WAAW;KACf,IAAI,WAAW;KACf,MAAK;KACL,GAAG;KACH,QAAO;KACM;IACd,CAAA,GACD,oBAAC,UAAD;KACE,IAAI,WAAW;KACf,IAAI,WAAW;KACf,MAAK;KACL,GAAG;KACH,QAAO;KACP,iBAAiB;KACjB,kBAAkB,iBAAiB,IAAI;KACvC,eAAc;KACD;KACb,OAAO,EAAE,OAAO,MAAM;IACvB,CAAA,CACE;OACJ,aACC,oBAAC,QAAD;IACE,WAAW,GACT,yFACA,eAAe,KACjB;cAEC;GACG,CAAA,CAEL;;CAET;CAEA,OACE,qBAAC,OAAD;EAAK,WAAU;EAAiC,yBAAsB;YAAtE,CACE,oBAAC,OAAD;GACE,GAAI;GACJ,WAAW,GAAG,mDAAmD,WAAW,KAAK;aAEjF,oBAAC,OAAD;IACE,WAAU;IACV,OAAO;KAAE,YAAY;KAAO,OAAO,GAAG,QAAQ,IAAI;IAAG;GACtD,CAAA;EACE,CAAA,GACJ,aACC,oBAAC,QAAD;GAAM,WAAU;aAAkD;EAAc,CAAA,CAE/E;;AAET"}
@@ -3,30 +3,17 @@ import { Icon } from "../icons/sprite.js";
3
3
  import { toNodes } from "../core/nodes.js";
4
4
  import { Renderer } from "../core/renderer.js";
5
5
  import { nodeIdentity, prefixedTestId } from "../core/test-id.js";
6
+ import { useCollapsibleState } from "./use-collapsible-state.js";
6
7
  import { InfoTooltip } from "./info-tooltip.js";
7
- import { useState } from "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  //#region resources/js/ui/section.tsx
10
- function readStored(key, remember, fallback) {
11
- if (!remember || typeof window === "undefined") return fallback;
12
- const stored = window.localStorage.getItem(key);
13
- return stored === null ? fallback : stored === "true";
14
- }
15
10
  var SectionComponent = ({ children, node }) => {
16
11
  const { title, description, tooltip } = node.props;
17
12
  const collapsible = node.props.collapsible === true;
18
13
  const rememberState = node.props.rememberState !== false;
19
14
  const headerActions = toNodes(node.props.headerActions);
20
15
  const identity = nodeIdentity(node);
21
- const storageKey = `lattice:section:${identity ?? "default"}`;
22
- const [collapsed, setCollapsed] = useState(() => readStored(storageKey, collapsible && rememberState, node.props.collapsed === true));
23
- function toggle() {
24
- setCollapsed((value) => {
25
- const next = !value;
26
- if (rememberState && typeof window !== "undefined") window.localStorage.setItem(storageKey, String(next));
27
- return next;
28
- });
29
- }
16
+ const [collapsed, toggle] = useCollapsibleState(`lattice:section:${identity ?? "default"}`, node.props.collapsed === true, collapsible && rememberState);
30
17
  const isCollapsed = collapsible && collapsed;
31
18
  return /* @__PURE__ */ jsxs("section", {
32
19
  "data-slot": "section",
@@ -1 +1 @@
1
- {"version":3,"file":"section.js","names":[],"sources":["../../resources/js/ui/section.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { Renderer } from \"@lattice-php/lattice/core/renderer\";\nimport { nodeIdentity, prefixedTestId } from \"@lattice-php/lattice/core/test-id\";\nimport { toNodes } from \"@lattice-php/lattice/core/nodes\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { InfoTooltip } from \"./info-tooltip\";\n\nfunction readStored(key: string, remember: boolean, fallback: boolean): boolean {\n if (!remember || typeof window === \"undefined\") {\n return fallback;\n }\n\n const stored = window.localStorage.getItem(key);\n\n return stored === null ? fallback : stored === \"true\";\n}\n\nconst SectionComponent: RendererComponent<\"section\"> = ({ children, node }) => {\n const { title, description, tooltip } = node.props;\n const collapsible = node.props.collapsible === true;\n const rememberState = node.props.rememberState !== false;\n const headerActions = toNodes(node.props.headerActions);\n const identity = nodeIdentity(node);\n const storageKey = `lattice:section:${identity ?? \"default\"}`;\n\n const [collapsed, setCollapsed] = useState(() =>\n readStored(storageKey, collapsible && rememberState, node.props.collapsed === true),\n );\n\n function toggle(): void {\n setCollapsed((value) => {\n const next = !value;\n\n if (rememberState && typeof window !== \"undefined\") {\n window.localStorage.setItem(storageKey, String(next));\n }\n\n return next;\n });\n }\n\n const isCollapsed = collapsible && collapsed;\n const hasHeader = Boolean(title || description || headerActions.length > 0 || collapsible);\n\n return (\n <section\n data-slot=\"section\"\n className=\"flex flex-col gap-6 rounded-lt border border-lt-border bg-lt-surface py-lt-gutter text-lt-surface-fg shadow-lt-sm\"\n data-lattice-component={identity}\n >\n {hasHeader && (\n <div className=\"flex items-start justify-between gap-4 px-lt-gutter\">\n <div className=\"flex min-w-0 items-start gap-2\">\n {collapsible && (\n <button\n aria-expanded={!isCollapsed}\n aria-label={isCollapsed ? \"Expand section\" : \"Collapse section\"}\n data-test={prefixedTestId(\"section-toggle\", identity) ?? \"section-toggle-default\"}\n className=\"mt-0.5 inline-flex shrink-0 items-center rounded-lt-sm p-0.5 text-lt-muted-fg transition-colors hover:bg-lt-muted hover:text-lt-fg\"\n onClick={toggle}\n type=\"button\"\n >\n <Icon\n name=\"chevron-down\"\n className={cn(\n \"size-lt-icon-md transition-transform\",\n isCollapsed && \"-rotate-90\",\n )}\n />\n </button>\n )}\n <div className=\"flex min-w-0 flex-col gap-1.5\">\n {title && (\n <div className=\"flex items-center\">\n <div className=\"font-semibold leading-none\">{title}</div>\n <InfoTooltip content={tooltip} />\n </div>\n )}\n {description && (\n <div className=\"flex items-center\">\n <div className=\"text-sm text-lt-muted-fg\">{description}</div>\n {!title && <InfoTooltip content={tooltip} />}\n </div>\n )}\n </div>\n </div>\n\n {headerActions.length > 0 && (\n <div className=\"flex shrink-0 items-center gap-2\">\n <Renderer nodes={headerActions} />\n </div>\n )}\n </div>\n )}\n\n {!isCollapsed && children && (\n <div className=\"flex flex-col gap-6 px-lt-gutter\">{children}</div>\n )}\n </section>\n );\n};\n\nexport default SectionComponent;\n"],"mappings":";;;;;;;;;AASA,SAAS,WAAW,KAAa,UAAmB,UAA4B;CAC9E,IAAI,CAAC,YAAY,OAAO,WAAW,aACjC,OAAO;CAGT,MAAM,SAAS,OAAO,aAAa,QAAQ,GAAG;CAE9C,OAAO,WAAW,OAAO,WAAW,WAAW;AACjD;AAEA,IAAM,oBAAkD,EAAE,UAAU,WAAW;CAC7E,MAAM,EAAE,OAAO,aAAa,YAAY,KAAK;CAC7C,MAAM,cAAc,KAAK,MAAM,gBAAgB;CAC/C,MAAM,gBAAgB,KAAK,MAAM,kBAAkB;CACnD,MAAM,gBAAgB,QAAQ,KAAK,MAAM,aAAa;CACtD,MAAM,WAAW,aAAa,IAAI;CAClC,MAAM,aAAa,mBAAmB,YAAY;CAElD,MAAM,CAAC,WAAW,gBAAgB,eAChC,WAAW,YAAY,eAAe,eAAe,KAAK,MAAM,cAAc,IAAI,CACpF;CAEA,SAAS,SAAe;EACtB,cAAc,UAAU;GACtB,MAAM,OAAO,CAAC;GAEd,IAAI,iBAAiB,OAAO,WAAW,aACrC,OAAO,aAAa,QAAQ,YAAY,OAAO,IAAI,CAAC;GAGtD,OAAO;EACT,CAAC;CACH;CAEA,MAAM,cAAc,eAAe;CAGnC,OACE,qBAAC,WAAD;EACE,aAAU;EACV,WAAU;EACV,0BAAwB;YAH1B,CAHgB,QAAQ,SAAS,eAAe,cAAc,SAAS,KAAK,WAQzE,KACC,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,qBAAC,OAAD;IAAK,WAAU;cAAf,CACG,eACC,oBAAC,UAAD;KACE,iBAAe,CAAC;KAChB,cAAY,cAAc,mBAAmB;KAC7C,aAAW,eAAe,kBAAkB,QAAQ,KAAK;KACzD,WAAU;KACV,SAAS;KACT,MAAK;eAEL,oBAAC,MAAD;MACE,MAAK;MACL,WAAW,GACT,wCACA,eAAe,YACjB;KACD,CAAA;IACK,CAAA,GAEV,qBAAC,OAAD;KAAK,WAAU;eAAf,CACG,SACC,qBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,oBAAC,OAAD;OAAK,WAAU;iBAA8B;MAAW,CAAA,GACxD,oBAAC,aAAD,EAAa,SAAS,QAAU,CAAA,CAC7B;SAEN,eACC,qBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,oBAAC,OAAD;OAAK,WAAU;iBAA4B;MAAiB,CAAA,GAC3D,CAAC,SAAS,oBAAC,aAAD,EAAa,SAAS,QAAU,CAAA,CACxC;OAEJ;MACF;OAEJ,cAAc,SAAS,KACtB,oBAAC,OAAD;IAAK,WAAU;cACb,oBAAC,UAAD,EAAU,OAAO,cAAgB,CAAA;GAC9B,CAAA,CAEJ;MAGN,CAAC,eAAe,YACf,oBAAC,OAAD;GAAK,WAAU;GAAoC;EAAc,CAAA,CAE5D;;AAEb"}
1
+ {"version":3,"file":"section.js","names":[],"sources":["../../resources/js/ui/section.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { Renderer } from \"@lattice-php/lattice/core/renderer\";\nimport { nodeIdentity, prefixedTestId } from \"@lattice-php/lattice/core/test-id\";\nimport { toNodes } from \"@lattice-php/lattice/core/nodes\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { InfoTooltip } from \"./info-tooltip\";\nimport { useCollapsibleState } from \"./use-collapsible-state\";\n\nconst SectionComponent: RendererComponent<\"section\"> = ({ children, node }) => {\n const { title, description, tooltip } = node.props;\n const collapsible = node.props.collapsible === true;\n const rememberState = node.props.rememberState !== false;\n const headerActions = toNodes(node.props.headerActions);\n const identity = nodeIdentity(node);\n const storageKey = `lattice:section:${identity ?? \"default\"}`;\n\n const [collapsed, toggle] = useCollapsibleState(\n storageKey,\n node.props.collapsed === true,\n collapsible && rememberState,\n );\n\n const isCollapsed = collapsible && collapsed;\n const hasHeader = Boolean(title || description || headerActions.length > 0 || collapsible);\n\n return (\n <section\n data-slot=\"section\"\n className=\"flex flex-col gap-6 rounded-lt border border-lt-border bg-lt-surface py-lt-gutter text-lt-surface-fg shadow-lt-sm\"\n data-lattice-component={identity}\n >\n {hasHeader && (\n <div className=\"flex items-start justify-between gap-4 px-lt-gutter\">\n <div className=\"flex min-w-0 items-start gap-2\">\n {collapsible && (\n <button\n aria-expanded={!isCollapsed}\n aria-label={isCollapsed ? \"Expand section\" : \"Collapse section\"}\n data-test={prefixedTestId(\"section-toggle\", identity) ?? \"section-toggle-default\"}\n className=\"mt-0.5 inline-flex shrink-0 items-center rounded-lt-sm p-0.5 text-lt-muted-fg transition-colors hover:bg-lt-muted hover:text-lt-fg\"\n onClick={toggle}\n type=\"button\"\n >\n <Icon\n name=\"chevron-down\"\n className={cn(\n \"size-lt-icon-md transition-transform\",\n isCollapsed && \"-rotate-90\",\n )}\n />\n </button>\n )}\n <div className=\"flex min-w-0 flex-col gap-1.5\">\n {title && (\n <div className=\"flex items-center\">\n <div className=\"font-semibold leading-none\">{title}</div>\n <InfoTooltip content={tooltip} />\n </div>\n )}\n {description && (\n <div className=\"flex items-center\">\n <div className=\"text-sm text-lt-muted-fg\">{description}</div>\n {!title && <InfoTooltip content={tooltip} />}\n </div>\n )}\n </div>\n </div>\n\n {headerActions.length > 0 && (\n <div className=\"flex shrink-0 items-center gap-2\">\n <Renderer nodes={headerActions} />\n </div>\n )}\n </div>\n )}\n\n {!isCollapsed && children && (\n <div className=\"flex flex-col gap-6 px-lt-gutter\">{children}</div>\n )}\n </section>\n );\n};\n\nexport default SectionComponent;\n"],"mappings":";;;;;;;;;AASA,IAAM,oBAAkD,EAAE,UAAU,WAAW;CAC7E,MAAM,EAAE,OAAO,aAAa,YAAY,KAAK;CAC7C,MAAM,cAAc,KAAK,MAAM,gBAAgB;CAC/C,MAAM,gBAAgB,KAAK,MAAM,kBAAkB;CACnD,MAAM,gBAAgB,QAAQ,KAAK,MAAM,aAAa;CACtD,MAAM,WAAW,aAAa,IAAI;CAGlC,MAAM,CAAC,WAAW,UAAU,oBAC1B,mBAHoC,YAAY,aAIhD,KAAK,MAAM,cAAc,MACzB,eAAe,aACjB;CAEA,MAAM,cAAc,eAAe;CAGnC,OACE,qBAAC,WAAD;EACE,aAAU;EACV,WAAU;EACV,0BAAwB;YAH1B,CAHgB,QAAQ,SAAS,eAAe,cAAc,SAAS,KAAK,WAQzE,KACC,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,qBAAC,OAAD;IAAK,WAAU;cAAf,CACG,eACC,oBAAC,UAAD;KACE,iBAAe,CAAC;KAChB,cAAY,cAAc,mBAAmB;KAC7C,aAAW,eAAe,kBAAkB,QAAQ,KAAK;KACzD,WAAU;KACV,SAAS;KACT,MAAK;eAEL,oBAAC,MAAD;MACE,MAAK;MACL,WAAW,GACT,wCACA,eAAe,YACjB;KACD,CAAA;IACK,CAAA,GAEV,qBAAC,OAAD;KAAK,WAAU;eAAf,CACG,SACC,qBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,oBAAC,OAAD;OAAK,WAAU;iBAA8B;MAAW,CAAA,GACxD,oBAAC,aAAD,EAAa,SAAS,QAAU,CAAA,CAC7B;SAEN,eACC,qBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,oBAAC,OAAD;OAAK,WAAU;iBAA4B;MAAiB,CAAA,GAC3D,CAAC,SAAS,oBAAC,aAAD,EAAa,SAAS,QAAU,CAAA,CACxC;OAEJ;MACF;OAEJ,cAAc,SAAS,KACtB,oBAAC,OAAD;IAAK,WAAU;cACb,oBAAC,UAAD,EAAU,OAAO,cAAgB,CAAA;GAC9B,CAAA,CAEJ;MAGN,CAAC,eAAe,YACf,oBAAC,OAAD;GAAK,WAAU;GAAoC;EAAc,CAAA,CAE5D;;AAEb"}
@@ -1,4 +1,5 @@
1
1
  import { cn } from "../lib/utils.js";
2
+ import { pillClassName } from "./pill.js";
2
3
  import { useEffect, useRef } from "react";
3
4
  import { jsx } from "react/jsx-runtime";
4
5
  //#region resources/js/ui/segmented-pills.tsx
@@ -23,7 +24,7 @@ function SegmentedPills({ ariaLabel, autoFocus = false, disabled = false, name,
23
24
  return /* @__PURE__ */ jsx("button", {
24
25
  "aria-checked": isSelected,
25
26
  "data-test": `${name ?? "segment"}-${option.value}`,
26
- className: cn("whitespace-nowrap rounded-lt-sm px-3 py-1.5 text-sm font-medium transition-colors", isSelected ? "bg-lt-bg text-lt-fg shadow-lt-xs" : "text-lt-muted-fg hover:bg-lt-bg/60 hover:text-lt-fg", disabled && "cursor-not-allowed opacity-60"),
27
+ className: cn(pillClassName(isSelected), disabled && "cursor-not-allowed opacity-60"),
27
28
  disabled,
28
29
  onClick: () => onSelect(option.value),
29
30
  role: "radio",
@@ -1 +1 @@
1
- {"version":3,"file":"segmented-pills.js","names":[],"sources":["../../resources/js/ui/segmented-pills.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport type { Option } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\n\n/**\n * Presentational segmented pill group. Used by the form choice field (bound to a\n * form value) and the core segmented control (standalone, emits an event).\n */\nexport function SegmentedPills({\n ariaLabel,\n autoFocus = false,\n disabled = false,\n name,\n onSelect,\n options,\n tabIndex,\n value,\n}: {\n ariaLabel?: string;\n autoFocus?: boolean;\n disabled?: boolean;\n name?: string;\n onSelect: (value: string) => void;\n options: Option[];\n tabIndex?: number;\n value: string;\n}) {\n const groupRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!autoFocus) {\n return;\n }\n\n const group = groupRef.current;\n const target =\n group?.querySelector<HTMLButtonElement>('button[aria-checked=\"true\"]') ??\n group?.querySelector<HTMLButtonElement>(\"button\");\n\n target?.focus();\n }, [autoFocus]);\n\n return (\n <div\n aria-label={ariaLabel}\n className=\"inline-flex w-fit max-w-full gap-1 overflow-x-auto rounded-lt bg-lt-muted p-1\"\n ref={groupRef}\n role=\"radiogroup\"\n >\n {options.map((option) => {\n const isSelected = value === option.value;\n\n return (\n <button\n aria-checked={isSelected}\n data-test={`${name ?? \"segment\"}-${option.value}`}\n className={cn(\n \"whitespace-nowrap rounded-lt-sm px-3 py-1.5 text-sm font-medium transition-colors\",\n isSelected\n ? \"bg-lt-bg text-lt-fg shadow-lt-xs\"\n : \"text-lt-muted-fg hover:bg-lt-bg/60 hover:text-lt-fg\",\n disabled && \"cursor-not-allowed opacity-60\",\n )}\n disabled={disabled}\n key={option.value}\n onClick={() => onSelect(option.value)}\n role=\"radio\"\n tabIndex={tabIndex}\n type=\"button\"\n >\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;;;AAQA,SAAgB,eAAe,EAC7B,WACA,YAAY,OACZ,WAAW,OACX,MACA,UACA,SACA,UACA,SAUC;CACD,MAAM,WAAW,OAAuB,IAAI;CAE5C,gBAAgB;EACd,IAAI,CAAC,WACH;EAGF,MAAM,QAAQ,SAAS;EAKvB,CAHE,OAAO,cAAiC,+BAA6B,KACrE,OAAO,cAAiC,QAAQ,IAE1C,MAAM;CAChB,GAAG,CAAC,SAAS,CAAC;CAEd,OACE,oBAAC,OAAD;EACE,cAAY;EACZ,WAAU;EACV,KAAK;EACL,MAAK;YAEJ,QAAQ,KAAK,WAAW;GACvB,MAAM,aAAa,UAAU,OAAO;GAEpC,OACE,oBAAC,UAAD;IACE,gBAAc;IACd,aAAW,GAAG,QAAQ,UAAU,GAAG,OAAO;IAC1C,WAAW,GACT,qFACA,aACI,qCACA,uDACJ,YAAY,+BACd;IACU;IAEV,eAAe,SAAS,OAAO,KAAK;IACpC,MAAK;IACK;IACV,MAAK;cAEJ,OAAO;GACF,GAPD,OAAO,KAON;EAEZ,CAAC;CACE,CAAA;AAET"}
1
+ {"version":3,"file":"segmented-pills.js","names":[],"sources":["../../resources/js/ui/segmented-pills.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport type { Option } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { pillClassName } from \"./pill\";\n\n/**\n * Presentational segmented pill group. Used by the form choice field (bound to a\n * form value) and the core segmented control (standalone, emits an event).\n */\nexport function SegmentedPills({\n ariaLabel,\n autoFocus = false,\n disabled = false,\n name,\n onSelect,\n options,\n tabIndex,\n value,\n}: {\n ariaLabel?: string;\n autoFocus?: boolean;\n disabled?: boolean;\n name?: string;\n onSelect: (value: string) => void;\n options: Option[];\n tabIndex?: number;\n value: string;\n}) {\n const groupRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!autoFocus) {\n return;\n }\n\n const group = groupRef.current;\n const target =\n group?.querySelector<HTMLButtonElement>('button[aria-checked=\"true\"]') ??\n group?.querySelector<HTMLButtonElement>(\"button\");\n\n target?.focus();\n }, [autoFocus]);\n\n return (\n <div\n aria-label={ariaLabel}\n className=\"inline-flex w-fit max-w-full gap-1 overflow-x-auto rounded-lt bg-lt-muted p-1\"\n ref={groupRef}\n role=\"radiogroup\"\n >\n {options.map((option) => {\n const isSelected = value === option.value;\n\n return (\n <button\n aria-checked={isSelected}\n data-test={`${name ?? \"segment\"}-${option.value}`}\n className={cn(pillClassName(isSelected), disabled && \"cursor-not-allowed opacity-60\")}\n disabled={disabled}\n key={option.value}\n onClick={() => onSelect(option.value)}\n role=\"radio\"\n tabIndex={tabIndex}\n type=\"button\"\n >\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AASA,SAAgB,eAAe,EAC7B,WACA,YAAY,OACZ,WAAW,OACX,MACA,UACA,SACA,UACA,SAUC;CACD,MAAM,WAAW,OAAuB,IAAI;CAE5C,gBAAgB;EACd,IAAI,CAAC,WACH;EAGF,MAAM,QAAQ,SAAS;EAKvB,CAHE,OAAO,cAAiC,+BAA6B,KACrE,OAAO,cAAiC,QAAQ,IAE1C,MAAM;CAChB,GAAG,CAAC,SAAS,CAAC;CAEd,OACE,oBAAC,OAAD;EACE,cAAY;EACZ,WAAU;EACV,KAAK;EACL,MAAK;YAEJ,QAAQ,KAAK,WAAW;GACvB,MAAM,aAAa,UAAU,OAAO;GAEpC,OACE,oBAAC,UAAD;IACE,gBAAc;IACd,aAAW,GAAG,QAAQ,UAAU,GAAG,OAAO;IAC1C,WAAW,GAAG,cAAc,UAAU,GAAG,YAAY,+BAA+B;IAC1E;IAEV,eAAe,SAAS,OAAO,KAAK;IACpC,MAAK;IACK;IACV,MAAK;cAEJ,OAAO;GACF,GAPD,OAAO,KAON;EAEZ,CAAC;CACE,CAAA;AAET"}
@@ -0,0 +1,3 @@
1
+ import { RendererComponent } from '../core/types.js';
2
+ declare const SeparatorComponent: RendererComponent<"separator">;
3
+ export default SeparatorComponent;
@@ -0,0 +1,15 @@
1
+ import { cn } from "../lib/utils.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ //#region resources/js/ui/separator.tsx
4
+ var SeparatorComponent = ({ node }) => {
5
+ const horizontal = node.props.orientation === "horizontal";
6
+ return /* @__PURE__ */ jsx("div", {
7
+ role: "separator",
8
+ "aria-orientation": node.props.orientation,
9
+ className: cn("shrink-0 bg-lt-border", horizontal ? "h-px w-full" : "h-full w-px self-stretch")
10
+ });
11
+ };
12
+ //#endregion
13
+ export { SeparatorComponent as default };
14
+
15
+ //# sourceMappingURL=separator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"separator.js","names":[],"sources":["../../resources/js/ui/separator.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\n\nconst SeparatorComponent: RendererComponent<\"separator\"> = ({ node }) => {\n const horizontal = node.props.orientation === \"horizontal\";\n\n return (\n <div\n role=\"separator\"\n aria-orientation={node.props.orientation}\n className={cn(\n \"shrink-0 bg-lt-border\",\n horizontal ? \"h-px w-full\" : \"h-full w-px self-stretch\",\n )}\n />\n );\n};\n\nexport default SeparatorComponent;\n"],"mappings":";;;AAGA,IAAM,sBAAsD,EAAE,WAAW;CACvE,MAAM,aAAa,KAAK,MAAM,gBAAgB;CAE9C,OACE,oBAAC,OAAD;EACE,MAAK;EACL,oBAAkB,KAAK,MAAM;EAC7B,WAAW,GACT,yBACA,aAAa,gBAAgB,0BAC/B;CACD,CAAA;AAEL"}
package/dist/ui/tabs.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { cn } from "../lib/utils.js";
2
2
  import { useT } from "../i18n/instance.js";
3
+ import { pillClassName } from "./pill.js";
3
4
  import { router } from "@inertiajs/react";
4
- import { createContext, useContext, useEffect, useMemo, useRef, useState } from "react";
5
+ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
6
7
  //#region resources/js/ui/tabs.tsx
7
8
  var TabsContext = createContext(null);
@@ -54,18 +55,22 @@ var TabsComponent = ({ children, node }) => {
54
55
  const defaultValue = node.props.defaultValue ?? firstValue;
55
56
  const tablistRef = useRef(null);
56
57
  const [activeValue, setActiveTabValue] = useState(() => serverActiveValue || (queryValue(queryKey, tabs) ?? defaultValue) || firstValue);
57
- function selectTab(tab) {
58
+ const selectTab = useCallback((tab) => {
58
59
  if (tab.confirm?.required) {
59
60
  router.visit(queryUrl(queryKey, tab.value), { preserveScroll: true });
60
61
  return;
61
62
  }
62
63
  setActiveTabValue(tab.value);
63
64
  replaceQueryValue(queryKey, tab.value);
64
- }
65
- function selectTabValue(value) {
65
+ }, [queryKey]);
66
+ const selectTabValue = useCallback((value) => {
66
67
  const tab = tabs.find((item) => item.value === value);
67
68
  if (tab) selectTab(tab);
68
- }
69
+ }, [selectTab, tabs]);
70
+ const contextValue = useMemo(() => ({
71
+ activeValue,
72
+ setActiveValue: selectTabValue
73
+ }), [activeValue, selectTabValue]);
69
74
  function onTablistKeyDown(event) {
70
75
  const nextKey = isVertical ? "ArrowDown" : "ArrowRight";
71
76
  const prevKey = isVertical ? "ArrowUp" : "ArrowLeft";
@@ -84,10 +89,7 @@ var TabsComponent = ({ children, node }) => {
84
89
  buttons[index]?.focus();
85
90
  }
86
91
  return /* @__PURE__ */ jsx(TabsContext.Provider, {
87
- value: {
88
- activeValue,
89
- setActiveValue: selectTabValue
90
- },
92
+ value: contextValue,
91
93
  children: /* @__PURE__ */ jsxs("div", {
92
94
  className: cn("gap-6", isVertical ? cn("flex", alignment === "end" && "flex-row-reverse") : "grid"),
93
95
  "data-lattice-tabs": node.key ?? node.id,
@@ -106,7 +108,7 @@ var TabsComponent = ({ children, node }) => {
106
108
  "aria-controls": `${tab.value}-panel`,
107
109
  "aria-selected": isActive,
108
110
  "data-test": `tab-${tab.value}`,
109
- className: cn("whitespace-nowrap rounded-lt-sm px-3 py-1.5 text-sm font-medium transition-colors", isActive ? "bg-lt-bg text-lt-fg shadow-lt-xs" : "text-lt-muted-fg hover:bg-lt-bg/60 hover:text-lt-fg", isVertical && "text-left", isStretched && "flex-1"),
111
+ className: cn(pillClassName(isActive), isVertical && "text-left", isStretched && "flex-1"),
110
112
  id: `${tab.value}-tab`,
111
113
  onClick: () => selectTab(tab),
112
114
  onKeyDown: onTablistKeyDown,
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.js","names":[],"sources":["../../resources/js/ui/tabs.tsx"],"sourcesContent":["import { router } from \"@inertiajs/react\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { KeyboardEvent, ReactNode } from \"react\";\nimport type { Node, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport type { Tab } from \"@lattice-php/lattice/types/generated\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\n\ntype TabsContextValue = {\n activeValue: string;\n setActiveValue: (value: string) => void;\n};\n\nconst TabsContext = createContext<TabsContextValue | null>(null);\n\nfunction useTabsContext(): TabsContextValue {\n const context = useContext(TabsContext);\n\n if (!context) {\n return {\n activeValue: \"\",\n setActiveValue: () => {},\n };\n }\n\n return context;\n}\n\ntype TabItem = {\n confirm?: {\n required?: boolean;\n };\n label: string;\n value: string;\n};\n\nfunction getTabs(node: Node): TabItem[] {\n return (node.schema ?? [])\n .filter((child) => child.type === \"tab\")\n .map((child) => {\n const props = child.props as unknown as Tab;\n\n return {\n confirm: props.confirm ? { required: props.confirm.required } : undefined,\n label: props.label,\n value: props.value,\n };\n })\n .filter((tab) => tab.value !== \"\");\n}\n\nfunction queryValue(queryKey: string, tabs: Array<{ value: string }>): string | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n const value = new URLSearchParams(window.location.search).get(queryKey);\n\n if (!value || !tabs.some((tab) => tab.value === value)) {\n return null;\n }\n\n return value;\n}\n\nfunction replaceQueryValue(queryKey: string, value: string): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n const url = new URL(window.location.href);\n url.searchParams.set(queryKey, value);\n window.history.replaceState(window.history.state, \"\", `${url.pathname}${url.search}${url.hash}`);\n}\n\nfunction queryUrl(queryKey: string, value: string): string {\n if (typeof window === \"undefined\") {\n return \"\";\n }\n\n const url = new URL(window.location.href);\n url.searchParams.set(queryKey, value);\n\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nexport const TabsComponent: RendererComponent<\"tabs\"> = ({ children, node }) => {\n const { t } = useT(\"lattice\");\n const tabs = useMemo(() => getTabs(node), [node]);\n const firstValue = tabs[0]?.value ?? \"\";\n const queryKey = node.props.queryKey;\n const orientation = node.props.orientation;\n const isVertical = orientation === \"vertical\";\n const alignment = node.props.alignment;\n const isStretched = !isVertical && alignment === \"stretch\";\n const serverActiveValue = node.props.activeValue;\n const defaultValue = node.props.defaultValue ?? firstValue;\n const tablistRef = useRef<HTMLDivElement>(null);\n const [activeValue, setActiveTabValue] = useState(\n () => serverActiveValue || (queryValue(queryKey, tabs) ?? defaultValue) || firstValue,\n );\n\n function selectTab(tab: TabItem): void {\n if (tab.confirm?.required) {\n router.visit(queryUrl(queryKey, tab.value), {\n preserveScroll: true,\n });\n\n return;\n }\n\n setActiveTabValue(tab.value);\n replaceQueryValue(queryKey, tab.value);\n }\n\n function selectTabValue(value: string): void {\n const tab = tabs.find((item) => item.value === value);\n\n if (tab) {\n selectTab(tab);\n }\n }\n\n function onTablistKeyDown(event: KeyboardEvent<HTMLButtonElement>): void {\n const nextKey = isVertical ? \"ArrowDown\" : \"ArrowRight\";\n const prevKey = isVertical ? \"ArrowUp\" : \"ArrowLeft\";\n\n if (\n event.key !== nextKey &&\n event.key !== prevKey &&\n event.key !== \"Home\" &&\n event.key !== \"End\"\n ) {\n return;\n }\n\n const buttons = Array.from(\n tablistRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]') ?? [],\n );\n\n if (buttons.length === 0) {\n return;\n }\n\n event.preventDefault();\n const current = buttons.indexOf(document.activeElement as HTMLButtonElement);\n\n let index: number;\n if (event.key === \"Home\") {\n index = 0;\n } else if (event.key === \"End\") {\n index = buttons.length - 1;\n } else {\n const delta = event.key === nextKey ? 1 : -1;\n const base = current < 0 ? 0 : current;\n index = (base + delta + buttons.length) % buttons.length;\n }\n\n buttons[index]?.focus();\n }\n\n return (\n <TabsContext.Provider value={{ activeValue, setActiveValue: selectTabValue }}>\n <div\n className={cn(\n \"gap-6\",\n isVertical ? cn(\"flex\", alignment === \"end\" && \"flex-row-reverse\") : \"grid\",\n )}\n data-lattice-tabs={node.key ?? node.id}\n >\n <div\n aria-label={t(\"common.tabs\", \"Tabs\")}\n aria-orientation={orientation}\n className={cn(\n \"gap-1 rounded-lt bg-lt-muted p-1\",\n isVertical && \"flex flex-col\",\n isStretched && \"flex w-full\",\n !isVertical &&\n !isStretched &&\n cn(\"inline-flex w-fit max-w-full overflow-x-auto\", {\n \"justify-self-center\": alignment === \"center\",\n \"justify-self-end\": alignment === \"end\",\n }),\n )}\n ref={tablistRef}\n role=\"tablist\"\n >\n {tabs.map((tab) => {\n const isActive = activeValue === tab.value;\n\n return (\n <button\n aria-controls={`${tab.value}-panel`}\n aria-selected={isActive}\n data-test={`tab-${tab.value}`}\n className={cn(\n \"whitespace-nowrap rounded-lt-sm px-3 py-1.5 text-sm font-medium transition-colors\",\n isActive\n ? \"bg-lt-bg text-lt-fg shadow-lt-xs\"\n : \"text-lt-muted-fg hover:bg-lt-bg/60 hover:text-lt-fg\",\n isVertical && \"text-left\",\n isStretched && \"flex-1\",\n )}\n id={`${tab.value}-tab`}\n key={tab.value}\n onClick={() => selectTab(tab)}\n onKeyDown={onTablistKeyDown}\n role=\"tab\"\n tabIndex={isActive ? 0 : -1}\n type=\"button\"\n >\n {tab.label}\n </button>\n );\n })}\n </div>\n\n <div className={cn(\"min-w-0\", isVertical && \"flex-1\")}>{children}</div>\n </div>\n </TabsContext.Provider>\n );\n};\n\nconst TabComponent: RendererComponent<\"tab\"> = ({ children, node }) => {\n const { activeValue } = useTabsContext();\n const value = node.props.value;\n const isActive = activeValue === value;\n const [hasOpened, setHasOpened] = useState(isActive);\n\n useEffect(() => {\n if (isActive) {\n setHasOpened(true);\n }\n }, [isActive]);\n\n return (\n <section\n aria-labelledby={`${value}-tab`}\n className={cn(\"space-y-8\", !isActive && \"hidden\")}\n hidden={!isActive}\n id={`${value}-panel`}\n role=\"tabpanel\"\n tabIndex={0}\n >\n {hasOpened ? (children as ReactNode) : null}\n </section>\n );\n};\n\nexport default TabComponent;\n"],"mappings":"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"}
1
+ {"version":3,"file":"tabs.js","names":[],"sources":["../../resources/js/ui/tabs.tsx"],"sourcesContent":["import { router } from \"@inertiajs/react\";\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { KeyboardEvent, ReactNode } from \"react\";\nimport type { Node, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport type { Tab } from \"@lattice-php/lattice/types/generated\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { pillClassName } from \"./pill\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\n\ntype TabsContextValue = {\n activeValue: string;\n setActiveValue: (value: string) => void;\n};\n\nconst TabsContext = createContext<TabsContextValue | null>(null);\n\nfunction useTabsContext(): TabsContextValue {\n const context = useContext(TabsContext);\n\n if (!context) {\n return {\n activeValue: \"\",\n setActiveValue: () => {},\n };\n }\n\n return context;\n}\n\ntype TabItem = {\n confirm?: {\n required?: boolean;\n };\n label: string;\n value: string;\n};\n\nfunction getTabs(node: Node): TabItem[] {\n return (node.schema ?? [])\n .filter((child) => child.type === \"tab\")\n .map((child) => {\n const props = child.props as unknown as Tab;\n\n return {\n confirm: props.confirm ? { required: props.confirm.required } : undefined,\n label: props.label,\n value: props.value,\n };\n })\n .filter((tab) => tab.value !== \"\");\n}\n\nfunction queryValue(queryKey: string, tabs: Array<{ value: string }>): string | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n const value = new URLSearchParams(window.location.search).get(queryKey);\n\n if (!value || !tabs.some((tab) => tab.value === value)) {\n return null;\n }\n\n return value;\n}\n\nfunction replaceQueryValue(queryKey: string, value: string): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n const url = new URL(window.location.href);\n url.searchParams.set(queryKey, value);\n window.history.replaceState(window.history.state, \"\", `${url.pathname}${url.search}${url.hash}`);\n}\n\nfunction queryUrl(queryKey: string, value: string): string {\n if (typeof window === \"undefined\") {\n return \"\";\n }\n\n const url = new URL(window.location.href);\n url.searchParams.set(queryKey, value);\n\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nexport const TabsComponent: RendererComponent<\"tabs\"> = ({ children, node }) => {\n const { t } = useT(\"lattice\");\n const tabs = useMemo(() => getTabs(node), [node]);\n const firstValue = tabs[0]?.value ?? \"\";\n const queryKey = node.props.queryKey;\n const orientation = node.props.orientation;\n const isVertical = orientation === \"vertical\";\n const alignment = node.props.alignment;\n const isStretched = !isVertical && alignment === \"stretch\";\n const serverActiveValue = node.props.activeValue;\n const defaultValue = node.props.defaultValue ?? firstValue;\n const tablistRef = useRef<HTMLDivElement>(null);\n const [activeValue, setActiveTabValue] = useState(\n () => serverActiveValue || (queryValue(queryKey, tabs) ?? defaultValue) || firstValue,\n );\n\n const selectTab = useCallback(\n (tab: TabItem): void => {\n if (tab.confirm?.required) {\n router.visit(queryUrl(queryKey, tab.value), {\n preserveScroll: true,\n });\n\n return;\n }\n\n setActiveTabValue(tab.value);\n replaceQueryValue(queryKey, tab.value);\n },\n [queryKey],\n );\n\n const selectTabValue = useCallback(\n (value: string): void => {\n const tab = tabs.find((item) => item.value === value);\n\n if (tab) {\n selectTab(tab);\n }\n },\n [selectTab, tabs],\n );\n\n const contextValue = useMemo(\n () => ({ activeValue, setActiveValue: selectTabValue }),\n [activeValue, selectTabValue],\n );\n\n function onTablistKeyDown(event: KeyboardEvent<HTMLButtonElement>): void {\n const nextKey = isVertical ? \"ArrowDown\" : \"ArrowRight\";\n const prevKey = isVertical ? \"ArrowUp\" : \"ArrowLeft\";\n\n if (\n event.key !== nextKey &&\n event.key !== prevKey &&\n event.key !== \"Home\" &&\n event.key !== \"End\"\n ) {\n return;\n }\n\n const buttons = Array.from(\n tablistRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"tab\"]') ?? [],\n );\n\n if (buttons.length === 0) {\n return;\n }\n\n event.preventDefault();\n const current = buttons.indexOf(document.activeElement as HTMLButtonElement);\n\n let index: number;\n if (event.key === \"Home\") {\n index = 0;\n } else if (event.key === \"End\") {\n index = buttons.length - 1;\n } else {\n const delta = event.key === nextKey ? 1 : -1;\n const base = current < 0 ? 0 : current;\n index = (base + delta + buttons.length) % buttons.length;\n }\n\n buttons[index]?.focus();\n }\n\n return (\n <TabsContext.Provider value={contextValue}>\n <div\n className={cn(\n \"gap-6\",\n isVertical ? cn(\"flex\", alignment === \"end\" && \"flex-row-reverse\") : \"grid\",\n )}\n data-lattice-tabs={node.key ?? node.id}\n >\n <div\n aria-label={t(\"common.tabs\", \"Tabs\")}\n aria-orientation={orientation}\n className={cn(\n \"gap-1 rounded-lt bg-lt-muted p-1\",\n isVertical && \"flex flex-col\",\n isStretched && \"flex w-full\",\n !isVertical &&\n !isStretched &&\n cn(\"inline-flex w-fit max-w-full overflow-x-auto\", {\n \"justify-self-center\": alignment === \"center\",\n \"justify-self-end\": alignment === \"end\",\n }),\n )}\n ref={tablistRef}\n role=\"tablist\"\n >\n {tabs.map((tab) => {\n const isActive = activeValue === tab.value;\n\n return (\n <button\n aria-controls={`${tab.value}-panel`}\n aria-selected={isActive}\n data-test={`tab-${tab.value}`}\n className={cn(\n pillClassName(isActive),\n isVertical && \"text-left\",\n isStretched && \"flex-1\",\n )}\n id={`${tab.value}-tab`}\n key={tab.value}\n onClick={() => selectTab(tab)}\n onKeyDown={onTablistKeyDown}\n role=\"tab\"\n tabIndex={isActive ? 0 : -1}\n type=\"button\"\n >\n {tab.label}\n </button>\n );\n })}\n </div>\n\n <div className={cn(\"min-w-0\", isVertical && \"flex-1\")}>{children}</div>\n </div>\n </TabsContext.Provider>\n );\n};\n\nconst TabComponent: RendererComponent<\"tab\"> = ({ children, node }) => {\n const { activeValue } = useTabsContext();\n const value = node.props.value;\n const isActive = activeValue === value;\n const [hasOpened, setHasOpened] = useState(isActive);\n\n useEffect(() => {\n if (isActive) {\n setHasOpened(true);\n }\n }, [isActive]);\n\n return (\n <section\n aria-labelledby={`${value}-tab`}\n className={cn(\"space-y-8\", !isActive && \"hidden\")}\n hidden={!isActive}\n id={`${value}-panel`}\n role=\"tabpanel\"\n tabIndex={0}\n >\n {hasOpened ? (children as ReactNode) : null}\n </section>\n );\n};\n\nexport default TabComponent;\n"],"mappings":"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"}
package/dist/ui/text.js CHANGED
@@ -1,20 +1,12 @@
1
1
  import { cn } from "../lib/utils.js";
2
2
  import { CopyableText } from "./copyable-text.js";
3
+ import { coerceColor, colorValue, namedColor } from "../lib/color.js";
3
4
  import { jsx } from "react/jsx-runtime";
4
5
  //#region resources/js/ui/text.tsx
5
6
  var textAlignments = {
6
7
  center: "text-center",
7
8
  left: "text-left"
8
9
  };
9
- var textColors = {
10
- default: "text-lt-fg",
11
- muted: "text-lt-muted-fg",
12
- primary: "text-lt-primary",
13
- success: "text-lt-success",
14
- info: "text-lt-info",
15
- warning: "text-lt-warning",
16
- danger: "text-lt-danger"
17
- };
18
10
  var textSizes = {
19
11
  xs: "text-xs leading-5",
20
12
  sm: "text-sm leading-6",
@@ -26,8 +18,11 @@ var textSizes = {
26
18
  "4xl": "text-4xl leading-none"
27
19
  };
28
20
  var TextComponent = ({ node }) => {
21
+ const align = node.props.align ?? "left";
22
+ const color = colorValue(coerceColor(node.props.color) ?? namedColor("muted"));
29
23
  const text = /* @__PURE__ */ jsx("p", {
30
- className: cn("m-0", "max-w-2xl", textAlignments[node.props.align ?? "left"] ?? textAlignments.left, textColors[node.props.color ?? "muted"], textSizes[node.props.size]),
24
+ className: cn("m-0", "max-w-2xl", textAlignments[align] ?? textAlignments.left, textSizes[node.props.size]),
25
+ style: { color },
31
26
  children: node.props.text
32
27
  });
33
28
  if (!node.props.copyable) return text;
@@ -1 +1 @@
1
- {"version":3,"file":"text.js","names":[],"sources":["../../resources/js/ui/text.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { Color, Size } from \"@lattice-php/lattice/types/generated\";\nimport { CopyableText } from \"./copyable-text\";\n\nconst textAlignments: Record<string, string> = {\n center: \"text-center\",\n left: \"text-left\",\n};\n\nconst textColors: Record<Color, string> = {\n default: \"text-lt-fg\",\n muted: \"text-lt-muted-fg\",\n primary: \"text-lt-primary\",\n success: \"text-lt-success\",\n info: \"text-lt-info\",\n warning: \"text-lt-warning\",\n danger: \"text-lt-danger\",\n};\n\nconst textSizes: Record<Size, string> = {\n xs: \"text-xs leading-5\",\n sm: \"text-sm leading-6\",\n md: \"text-base leading-7\",\n lg: \"text-lg leading-8\",\n xl: \"text-xl leading-8\",\n \"2xl\": \"text-2xl leading-9\",\n \"3xl\": \"text-3xl leading-10\",\n \"4xl\": \"text-4xl leading-none\",\n};\n\nconst TextComponent: RendererComponent<\"text\"> = ({ node }) => {\n const align = node.props.align ?? \"left\";\n\n const text = (\n <p\n className={cn(\n \"m-0\",\n \"max-w-2xl\",\n textAlignments[align] ?? textAlignments.left,\n textColors[node.props.color ?? \"muted\"],\n textSizes[node.props.size],\n )}\n >\n {node.props.text}\n </p>\n );\n\n if (!node.props.copyable) {\n return text;\n }\n\n return (\n <CopyableText value={node.props.text} label={node.props.text}>\n {text}\n </CopyableText>\n );\n};\n\nexport default TextComponent;\n"],"mappings":";;;;AAKA,IAAM,iBAAyC;CAC7C,QAAQ;CACR,MAAM;AACR;AAEA,IAAM,aAAoC;CACxC,SAAS;CACT,OAAO;CACP,SAAS;CACT,SAAS;CACT,MAAM;CACN,SAAS;CACT,QAAQ;AACV;AAEA,IAAM,YAAkC;CACtC,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,OAAO;AACT;AAEA,IAAM,iBAA4C,EAAE,WAAW;CAG7D,MAAM,OACJ,oBAAC,KAAD;EACE,WAAW,GACT,OACA,aACA,eAPQ,KAAK,MAAM,SAAS,WAOH,eAAe,MACxC,WAAW,KAAK,MAAM,SAAS,UAC/B,UAAU,KAAK,MAAM,KACvB;YAEC,KAAK,MAAM;CACX,CAAA;CAGL,IAAI,CAAC,KAAK,MAAM,UACd,OAAO;CAGT,OACE,oBAAC,cAAD;EAAc,OAAO,KAAK,MAAM;EAAM,OAAO,KAAK,MAAM;YACrD;CACW,CAAA;AAElB"}
1
+ {"version":3,"file":"text.js","names":[],"sources":["../../resources/js/ui/text.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { coerceColor, colorValue, namedColor } from \"@lattice-php/lattice/lib/color\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { Size } from \"@lattice-php/lattice/types/generated\";\nimport { CopyableText } from \"./copyable-text\";\n\nconst textAlignments: Record<string, string> = {\n center: \"text-center\",\n left: \"text-left\",\n};\n\nconst textSizes: Record<Size, string> = {\n xs: \"text-xs leading-5\",\n sm: \"text-sm leading-6\",\n md: \"text-base leading-7\",\n lg: \"text-lg leading-8\",\n xl: \"text-xl leading-8\",\n \"2xl\": \"text-2xl leading-9\",\n \"3xl\": \"text-3xl leading-10\",\n \"4xl\": \"text-4xl leading-none\",\n};\n\nconst TextComponent: RendererComponent<\"text\"> = ({ node }) => {\n const align = node.props.align ?? \"left\";\n const color = colorValue(coerceColor(node.props.color) ?? namedColor(\"muted\"));\n\n const text = (\n <p\n className={cn(\n \"m-0\",\n \"max-w-2xl\",\n textAlignments[align] ?? textAlignments.left,\n textSizes[node.props.size],\n )}\n style={{ color }}\n >\n {node.props.text}\n </p>\n );\n\n if (!node.props.copyable) {\n return text;\n }\n\n return (\n <CopyableText value={node.props.text} label={node.props.text}>\n {text}\n </CopyableText>\n );\n};\n\nexport default TextComponent;\n"],"mappings":";;;;;AAMA,IAAM,iBAAyC;CAC7C,QAAQ;CACR,MAAM;AACR;AAEA,IAAM,YAAkC;CACtC,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,OAAO;AACT;AAEA,IAAM,iBAA4C,EAAE,WAAW;CAC7D,MAAM,QAAQ,KAAK,MAAM,SAAS;CAClC,MAAM,QAAQ,WAAW,YAAY,KAAK,MAAM,KAAK,KAAK,WAAW,OAAO,CAAC;CAE7E,MAAM,OACJ,oBAAC,KAAD;EACE,WAAW,GACT,OACA,aACA,eAAe,UAAU,eAAe,MACxC,UAAU,KAAK,MAAM,KACvB;EACA,OAAO,EAAE,MAAM;YAEd,KAAK,MAAM;CACX,CAAA;CAGL,IAAI,CAAC,KAAK,MAAM,UACd,OAAO;CAGT,OACE,oBAAC,cAAD;EAAc,OAAO,KAAK,MAAM;EAAM,OAAO,KAAK,MAAM;YACrD;CACW,CAAA;AAElB"}
@@ -0,0 +1,33 @@
1
+ import { RefObject } from 'react';
2
+ export type TreeItemRegistration = {
3
+ id: string;
4
+ label: string;
5
+ orderPath: string;
6
+ parentPath: string | null;
7
+ path: string;
8
+ ref: RefObject<HTMLLIElement | null>;
9
+ };
10
+ export type TreeFocusDirection = "first" | "firstChild" | "last" | "next" | "parent" | "prev";
11
+ export type TreeContextValue = {
12
+ activate: (id: string) => void;
13
+ activeId: string | null;
14
+ expanded: Set<string>;
15
+ focus: (id: string) => void;
16
+ focusedId: string | null;
17
+ moveFocus: (fromId: string, direction: TreeFocusDirection) => void;
18
+ register: (entry: TreeItemRegistration) => void;
19
+ toggle: (id: string) => void;
20
+ typeAhead: (fromId: string, character: string) => void;
21
+ unregister: (path: string) => void;
22
+ };
23
+ export declare const TreeContext: import('react').Context<TreeContextValue>;
24
+ export declare function useTreeContext(): TreeContextValue;
25
+ export declare function useTreeState({ activeId: initialActiveId, defaultExpanded, nodes, rememberState, storageKey, }: {
26
+ activeId: string | null;
27
+ defaultExpanded: string[];
28
+ nodes: Array<{
29
+ id: string;
30
+ }>;
31
+ rememberState: boolean;
32
+ storageKey: string;
33
+ }): TreeContextValue;