@stackcraftmx/calcita 0.28.0 → 0.30.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 (298) hide show
  1. package/README.md +139 -0
  2. package/dist/DataTable/AuditTrailDialog.js +18 -14
  3. package/dist/DataTable/AuditTrailDialog.js.map +1 -1
  4. package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js +12 -6
  5. package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js.map +1 -1
  6. package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js +8 -3
  7. package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js.map +1 -1
  8. package/dist/DataTable/ColumnFilters/SortableFilterHeader.js +26 -18
  9. package/dist/DataTable/ColumnFilters/SortableFilterHeader.js.map +1 -1
  10. package/dist/DataTable/EmptyState.js +8 -3
  11. package/dist/DataTable/EmptyState.js.map +1 -1
  12. package/dist/DataTable/FilterChips.js +11 -5
  13. package/dist/DataTable/FilterChips.js.map +1 -1
  14. package/dist/DataTable/GoToPage.js +9 -4
  15. package/dist/DataTable/GoToPage.js.map +1 -1
  16. package/dist/DataTable/ServerTable.js +74 -61
  17. package/dist/DataTable/ServerTable.js.map +1 -1
  18. package/dist/DataTable/columns.js +1 -8
  19. package/dist/DataTable/columns.js.map +1 -1
  20. package/dist/access/PermissionMatrix.js +18 -9
  21. package/dist/access/PermissionMatrix.js.map +1 -1
  22. package/dist/account/AccountSecuritySection.js +8 -3
  23. package/dist/account/AccountSecuritySection.js.map +1 -1
  24. package/dist/account/DemoTotpCodeButton.js +8 -3
  25. package/dist/account/DemoTotpCodeButton.js.map +1 -1
  26. package/dist/account/ProfileScreen.js +19 -13
  27. package/dist/account/ProfileScreen.js.map +1 -1
  28. package/dist/account/SignInScreen.js +6 -2
  29. package/dist/account/SignInScreen.js.map +1 -1
  30. package/dist/appShell/AccountMenu.js +13 -5
  31. package/dist/appShell/AccountMenu.js.map +1 -1
  32. package/dist/appShell/AppLayout.js +100 -71
  33. package/dist/appShell/AppLayout.js.map +1 -1
  34. package/dist/appShell/AppearanceSettings.js +21 -13
  35. package/dist/appShell/AppearanceSettings.js.map +1 -1
  36. package/dist/appShell/AuthLayout.js +26 -13
  37. package/dist/appShell/AuthLayout.js.map +1 -1
  38. package/dist/appShell/BarActions.js +10 -5
  39. package/dist/appShell/BarActions.js.map +1 -1
  40. package/dist/appShell/BarCapsule.js +9 -4
  41. package/dist/appShell/BarCapsule.js.map +1 -1
  42. package/dist/appShell/BarSearch.js +7 -3
  43. package/dist/appShell/BarSearch.js.map +1 -1
  44. package/dist/appShell/HeaderTools.js +20 -15
  45. package/dist/appShell/HeaderTools.js.map +1 -1
  46. package/dist/appShell/MobileTabBar.js +25 -14
  47. package/dist/appShell/MobileTabBar.js.map +1 -1
  48. package/dist/appShell/SettingsMenu.js +7 -3
  49. package/dist/appShell/SettingsMenu.js.map +1 -1
  50. package/dist/appShell/SideMenu.js +53 -35
  51. package/dist/appShell/SideMenu.js.map +1 -1
  52. package/dist/appShell/SideMenuEntry.js +18 -9
  53. package/dist/appShell/SideMenuEntry.js.map +1 -1
  54. package/dist/appShell/SubmenuActionsMenu.js +6 -2
  55. package/dist/appShell/SubmenuActionsMenu.js.map +1 -1
  56. package/dist/appShell/TabBarEditor.js +16 -7
  57. package/dist/appShell/TabBarEditor.js.map +1 -1
  58. package/dist/appShell/TopMenu.js +12 -7
  59. package/dist/appShell/TopMenu.js.map +1 -1
  60. package/dist/appShell/Wordmark.js +6 -2
  61. package/dist/appShell/Wordmark.js.map +1 -1
  62. package/dist/auth/PasswordChecklist.js +14 -7
  63. package/dist/auth/PasswordChecklist.js.map +1 -1
  64. package/dist/calendar/EventCalendar.js +26 -19
  65. package/dist/calendar/EventCalendar.js.map +1 -1
  66. package/dist/calendar/EventDetails.js +28 -13
  67. package/dist/calendar/EventDetails.js.map +1 -1
  68. package/dist/downloads/DownloadManager.js +34 -18
  69. package/dist/downloads/DownloadManager.js.map +1 -1
  70. package/dist/feedback/ConfirmDialog.js +22 -17
  71. package/dist/feedback/ConfirmDialog.js.map +1 -1
  72. package/dist/feedback/ModalWaiting.js +12 -5
  73. package/dist/feedback/ModalWaiting.js.map +1 -1
  74. package/dist/feedback/NewBuildNotice.js +16 -8
  75. package/dist/feedback/NewBuildNotice.js.map +1 -1
  76. package/dist/filepond/FileDropzone.js +39 -31
  77. package/dist/filepond/FileDropzone.js.map +1 -1
  78. package/dist/forms/FormProblemAlert.js +4 -1
  79. package/dist/forms/FormProblemAlert.js.map +1 -1
  80. package/dist/forms/auth/SignInForm.js +6 -2
  81. package/dist/forms/auth/SignInForm.js.map +1 -1
  82. package/dist/forms/security/SecondStepForm.js +6 -2
  83. package/dist/forms/security/SecondStepForm.js.map +1 -1
  84. package/dist/forms/security/TwoStepVerificationCard.js +19 -9
  85. package/dist/forms/security/TwoStepVerificationCard.js.map +1 -1
  86. package/dist/hookForm/FormProblemAlert.js +4 -1
  87. package/dist/hookForm/FormProblemAlert.js.map +1 -1
  88. package/dist/inbox/InboxLayout.js +47 -29
  89. package/dist/inbox/InboxLayout.js.map +1 -1
  90. package/dist/inbox/MessageList.js +53 -32
  91. package/dist/inbox/MessageList.js.map +1 -1
  92. package/dist/inbox/MessageView.js +31 -15
  93. package/dist/inbox/MessageView.js.map +1 -1
  94. package/dist/index.js +4 -0
  95. package/dist/index.js.map +1 -1
  96. package/dist/inputs/ColorInput.js +22 -17
  97. package/dist/inputs/ColorInput.js.map +1 -1
  98. package/dist/inputs/FormSection.js +64 -64
  99. package/dist/inputs/FormSection.js.map +1 -1
  100. package/dist/inputs/SelectInput.js +21 -16
  101. package/dist/inputs/SelectInput.js.map +1 -1
  102. package/dist/inputs/TextInput.js +25 -20
  103. package/dist/inputs/TextInput.js.map +1 -1
  104. package/dist/inputs/WizardLayout.js +21 -15
  105. package/dist/inputs/WizardLayout.js.map +1 -1
  106. package/dist/kanban/KanbanBoard.js +82 -50
  107. package/dist/kanban/KanbanBoard.js.map +1 -1
  108. package/dist/maps/MapView.js +19 -14
  109. package/dist/maps/MapView.js.map +1 -1
  110. package/dist/pwa/InstallAppSetting.js +4 -1
  111. package/dist/pwa/InstallAppSetting.js.map +1 -1
  112. package/dist/pwa/InstallInstructionsDialog.js +6 -2
  113. package/dist/pwa/InstallInstructionsDialog.js.map +1 -1
  114. package/dist/pwa/InstallPromptBanner.js +10 -5
  115. package/dist/pwa/InstallPromptBanner.js.map +1 -1
  116. package/dist/security/ActivityLog.js +6 -2
  117. package/dist/security/ActivityLog.js.map +1 -1
  118. package/dist/security/RecoveryCodesDialog.js +8 -3
  119. package/dist/security/RecoveryCodesDialog.js.map +1 -1
  120. package/dist/security/SessionsCard.js +12 -5
  121. package/dist/security/SessionsCard.js.map +1 -1
  122. package/dist/theme/components/glassComponents.js +19 -16
  123. package/dist/theme/components/glassComponents.js.map +1 -1
  124. package/dist/theme/components/minimalComponents.js +6 -2
  125. package/dist/theme/components/minimalComponents.js.map +1 -1
  126. package/dist/theme/createToolkitTheme.js +8 -1
  127. package/dist/theme/createToolkitTheme.js.map +1 -1
  128. package/dist/theme/cssTokens.js +23 -0
  129. package/dist/theme/cssTokens.js.map +1 -0
  130. package/dist/theme/glassSurface.js +9 -3
  131. package/dist/theme/glassSurface.js.map +1 -1
  132. package/dist/theme/glassToasterStyles.js +2 -3
  133. package/dist/theme/glassToasterStyles.js.map +1 -1
  134. package/dist/theme/themePieces.js +16 -0
  135. package/dist/theme/themePieces.js.map +1 -0
  136. package/dist/types/DataTable/AuditTrailDialog.d.ts +1 -1
  137. package/dist/types/DataTable/ColumnFilters/HeaderFilterPopover.d.ts +1 -1
  138. package/dist/types/DataTable/ColumnFilters/MultiSelectColumnFilter.d.ts +1 -1
  139. package/dist/types/DataTable/ColumnFilters/SortableFilterHeader.d.ts +1 -1
  140. package/dist/types/DataTable/EmptyState.d.ts +1 -1
  141. package/dist/types/DataTable/FilterChips.d.ts +1 -1
  142. package/dist/types/DataTable/GoToPage.d.ts +1 -1
  143. package/dist/types/DataTable/ServerTable.d.ts +1 -1
  144. package/dist/types/access/PermissionMatrix.d.ts +1 -1
  145. package/dist/types/account/AccountSecuritySection.d.ts +1 -1
  146. package/dist/types/account/DemoTotpCodeButton.d.ts +1 -1
  147. package/dist/types/account/ProfileScreen.d.ts +1 -1
  148. package/dist/types/account/SignInScreen.d.ts +1 -1
  149. package/dist/types/appShell/AccountMenu.d.ts +1 -1
  150. package/dist/types/appShell/AppLayout.d.ts +1 -1
  151. package/dist/types/appShell/AppearanceSettings.d.ts +1 -1
  152. package/dist/types/appShell/AuthLayout.d.ts +1 -1
  153. package/dist/types/appShell/BarActions.d.ts +1 -1
  154. package/dist/types/appShell/BarCapsule.d.ts +1 -1
  155. package/dist/types/appShell/BarSearch.d.ts +1 -1
  156. package/dist/types/appShell/HeaderTools.d.ts +1 -1
  157. package/dist/types/appShell/MobileTabBar.d.ts +1 -1
  158. package/dist/types/appShell/SettingsMenu.d.ts +1 -1
  159. package/dist/types/appShell/SideMenu.d.ts +1 -1
  160. package/dist/types/appShell/SideMenuEntry.d.ts +1 -1
  161. package/dist/types/appShell/SubmenuActionsMenu.d.ts +1 -1
  162. package/dist/types/appShell/TabBarEditor.d.ts +1 -1
  163. package/dist/types/appShell/TopMenu.d.ts +1 -1
  164. package/dist/types/appShell/Wordmark.d.ts +1 -1
  165. package/dist/types/auth/PasswordChecklist.d.ts +1 -1
  166. package/dist/types/calendar/EventCalendar.d.ts +1 -1
  167. package/dist/types/calendar/EventDetails.d.ts +1 -1
  168. package/dist/types/feedback/ConfirmDialog.d.ts +1 -1
  169. package/dist/types/feedback/ModalWaiting.d.ts +1 -1
  170. package/dist/types/feedback/NewBuildNotice.d.ts +1 -1
  171. package/dist/types/filepond/FileDropzone.d.ts +1 -1
  172. package/dist/types/forms/auth/SignInForm.d.ts +1 -1
  173. package/dist/types/forms/security/SecondStepForm.d.ts +1 -1
  174. package/dist/types/forms/security/TwoStepVerificationCard.d.ts +1 -1
  175. package/dist/types/inbox/InboxLayout.d.ts +1 -1
  176. package/dist/types/inbox/MessageList.d.ts +1 -1
  177. package/dist/types/inbox/MessageView.d.ts +1 -1
  178. package/dist/types/index.d.ts +1 -0
  179. package/dist/types/inputs/ColorInput.d.ts +1 -1
  180. package/dist/types/inputs/FormSection.d.ts +2 -2
  181. package/dist/types/inputs/SelectInput.d.ts +1 -1
  182. package/dist/types/inputs/TextInput.d.ts +1 -1
  183. package/dist/types/inputs/WizardLayout.d.ts +1 -1
  184. package/dist/types/kanban/KanbanBoard.d.ts +1 -1
  185. package/dist/types/maps/MapView.d.ts +1 -1
  186. package/dist/types/pwa/InstallInstructionsDialog.d.ts +1 -1
  187. package/dist/types/pwa/InstallPromptBanner.d.ts +1 -1
  188. package/dist/types/security/ActivityLog.d.ts +1 -1
  189. package/dist/types/security/RecoveryCodesDialog.d.ts +1 -1
  190. package/dist/types/security/SessionsCard.d.ts +1 -1
  191. package/dist/types/theme/createToolkitTheme.d.ts +12 -1
  192. package/dist/types/theme/cssTokens.d.ts +46 -0
  193. package/dist/types/theme/glassSurface.d.ts +3 -0
  194. package/dist/types/theme/themePieces.d.ts +20 -0
  195. package/dist/types/ui/actions/ActionsMenu.d.ts +1 -1
  196. package/dist/types/ui/actions/DownloadMenu.d.ts +1 -1
  197. package/dist/types/ui/actions/SelectionActions.d.ts +1 -1
  198. package/dist/types/ui/filters/DateRangeFilter.d.ts +1 -1
  199. package/dist/types/ui/filters/PeriodRangeSelector.d.ts +1 -1
  200. package/dist/types/ui/filters/QuickFilters.d.ts +1 -1
  201. package/dist/types/ui/filters/SegmentedControl.d.ts +7 -2
  202. package/dist/types/ui/labels/StatusChip.d.ts +1 -1
  203. package/dist/types/ui/labels/Tag.d.ts +1 -1
  204. package/dist/types/ui/layout/CollapsibleSection.d.ts +1 -1
  205. package/dist/types/ui/layout/ContentDialog.d.ts +1 -1
  206. package/dist/types/ui/layout/DefinitionList.d.ts +1 -1
  207. package/dist/types/ui/layout/DetailHeader.d.ts +1 -1
  208. package/dist/types/ui/layout/ErrorPage.d.ts +1 -1
  209. package/dist/types/ui/layout/GlassPanel.d.ts +1 -1
  210. package/dist/types/ui/layout/PageHeader.d.ts +1 -1
  211. package/dist/types/ui/layout/PageHeading.d.ts +1 -1
  212. package/dist/types/ui/layout/ProfileHeader.d.ts +1 -1
  213. package/dist/types/ui/layout/ScrollableRow.d.ts +1 -1
  214. package/dist/types/ui/layout/SectionCard.d.ts +1 -1
  215. package/dist/types/ui/metrics/BarList.d.ts +1 -1
  216. package/dist/types/ui/metrics/CalendarHeatmap.d.ts +1 -1
  217. package/dist/types/ui/metrics/ChartTooltip.d.ts +1 -1
  218. package/dist/types/ui/metrics/ColumnChart.d.ts +1 -1
  219. package/dist/types/ui/metrics/LineChart.d.ts +1 -1
  220. package/dist/types/ui/metrics/MetricCard.d.ts +1 -1
  221. package/dist/types/ui/metrics/TableToggle.d.ts +1 -1
  222. package/dist/types/ui/navigation/ColorSchemeToggle.d.ts +1 -1
  223. package/dist/types/ui/navigation/FontSizeToggle.d.ts +1 -1
  224. package/dist/types/ui/navigation/LanguageToggle.d.ts +1 -1
  225. package/dist/types/ui/navigation/PageBreadcrumbs.d.ts +1 -1
  226. package/dist/types/ui/timeline/GroupedTimeline.d.ts +1 -1
  227. package/dist/types/upload/FileDropzone.d.ts +1 -1
  228. package/dist/ui/actions/ActionsMenu.js +9 -4
  229. package/dist/ui/actions/ActionsMenu.js.map +1 -1
  230. package/dist/ui/actions/DownloadMenu.js +21 -17
  231. package/dist/ui/actions/DownloadMenu.js.map +1 -1
  232. package/dist/ui/actions/SelectionActions.js +15 -7
  233. package/dist/ui/actions/SelectionActions.js.map +1 -1
  234. package/dist/ui/filters/DateRangeFilter.js +11 -5
  235. package/dist/ui/filters/DateRangeFilter.js.map +1 -1
  236. package/dist/ui/filters/PeriodRangeSelector.js +11 -5
  237. package/dist/ui/filters/PeriodRangeSelector.js.map +1 -1
  238. package/dist/ui/filters/QuickFilters.js +16 -8
  239. package/dist/ui/filters/QuickFilters.js.map +1 -1
  240. package/dist/ui/filters/SegmentedControl.js +12 -5
  241. package/dist/ui/filters/SegmentedControl.js.map +1 -1
  242. package/dist/ui/labels/StatusChip.js +35 -25
  243. package/dist/ui/labels/StatusChip.js.map +1 -1
  244. package/dist/ui/labels/Tag.js +8 -3
  245. package/dist/ui/labels/Tag.js.map +1 -1
  246. package/dist/ui/layout/CollapsibleSection.js +18 -8
  247. package/dist/ui/layout/CollapsibleSection.js.map +1 -1
  248. package/dist/ui/layout/ContentDialog.js +13 -6
  249. package/dist/ui/layout/ContentDialog.js.map +1 -1
  250. package/dist/ui/layout/DefinitionList.js +13 -6
  251. package/dist/ui/layout/DefinitionList.js.map +1 -1
  252. package/dist/ui/layout/DetailHeader.js +14 -6
  253. package/dist/ui/layout/DetailHeader.js.map +1 -1
  254. package/dist/ui/layout/ErrorPage.js +20 -15
  255. package/dist/ui/layout/ErrorPage.js.map +1 -1
  256. package/dist/ui/layout/FullPageLoader.js +4 -1
  257. package/dist/ui/layout/FullPageLoader.js.map +1 -1
  258. package/dist/ui/layout/GlassPanel.js +8 -4
  259. package/dist/ui/layout/GlassPanel.js.map +1 -1
  260. package/dist/ui/layout/PageHeader.js +10 -4
  261. package/dist/ui/layout/PageHeader.js.map +1 -1
  262. package/dist/ui/layout/PageHeading.js +17 -8
  263. package/dist/ui/layout/PageHeading.js.map +1 -1
  264. package/dist/ui/layout/ProfileHeader.js +21 -10
  265. package/dist/ui/layout/ProfileHeader.js.map +1 -1
  266. package/dist/ui/layout/ScrollableRow.js +19 -15
  267. package/dist/ui/layout/ScrollableRow.js.map +1 -1
  268. package/dist/ui/layout/SectionCard.js +10 -4
  269. package/dist/ui/layout/SectionCard.js.map +1 -1
  270. package/dist/ui/metrics/BarList.js +9 -4
  271. package/dist/ui/metrics/BarList.js.map +1 -1
  272. package/dist/ui/metrics/CalendarHeatmap.js +40 -21
  273. package/dist/ui/metrics/CalendarHeatmap.js.map +1 -1
  274. package/dist/ui/metrics/ChartTooltip.js +6 -2
  275. package/dist/ui/metrics/ChartTooltip.js.map +1 -1
  276. package/dist/ui/metrics/ColumnChart.js +22 -18
  277. package/dist/ui/metrics/ColumnChart.js.map +1 -1
  278. package/dist/ui/metrics/LineChart.js +20 -16
  279. package/dist/ui/metrics/LineChart.js.map +1 -1
  280. package/dist/ui/metrics/MetricCard.js +42 -24
  281. package/dist/ui/metrics/MetricCard.js.map +1 -1
  282. package/dist/ui/metrics/TableToggle.js +7 -2
  283. package/dist/ui/metrics/TableToggle.js.map +1 -1
  284. package/dist/ui/metrics/chartParts.js +14 -5
  285. package/dist/ui/metrics/chartParts.js.map +1 -1
  286. package/dist/ui/navigation/ColorSchemeToggle.js +8 -4
  287. package/dist/ui/navigation/ColorSchemeToggle.js.map +1 -1
  288. package/dist/ui/navigation/FontSizeToggle.js +6 -2
  289. package/dist/ui/navigation/FontSizeToggle.js.map +1 -1
  290. package/dist/ui/navigation/LanguageToggle.js +8 -4
  291. package/dist/ui/navigation/LanguageToggle.js.map +1 -1
  292. package/dist/ui/navigation/PageBreadcrumbs.js +12 -6
  293. package/dist/ui/navigation/PageBreadcrumbs.js.map +1 -1
  294. package/dist/ui/timeline/GroupedTimeline.js +26 -13
  295. package/dist/ui/timeline/GroupedTimeline.js.map +1 -1
  296. package/dist/upload/FileDropzone.js +35 -25
  297. package/dist/upload/FileDropzone.js.map +1 -1
  298. package/package.json +1 -1
@@ -16,13 +16,20 @@ import LightModeIcon from "@mui/icons-material/LightModeOutlined";
16
16
  import { useToolkitSettings } from "../toolkit/toolkitContext.js";
17
17
  import { DEFAULT_LANGUAGES } from "../toolkit/toolkitSettings.js";
18
18
  import { useFontSize } from "../ui/navigation/useFontSize.js";
19
+ import { piecePart, usePieceProps } from "../theme/themePieces.js";
20
+ const THEME_NAME = "CalcitaAppearanceSettings";
21
+ const AppearanceSelectSection = piecePart(THEME_NAME, "SelectSection", Box);
22
+ const AppearanceSection = piecePart(THEME_NAME, "Section", Box);
23
+ const AppearanceSectionLabel = piecePart(THEME_NAME, "SectionLabel", Typography);
24
+ const AppearanceOption = piecePart(THEME_NAME, "Option", ToggleButton);
25
+ const AppearanceDivider = piecePart(THEME_NAME, "Divider", Divider);
19
26
  const SETTING_BUTTONS_LIMIT = 3;
20
27
  function SettingSection({ label, value, options, onChange }) {
21
28
  if (options.length > SETTING_BUTTONS_LIMIT) {
22
- return /* @__PURE__ */ jsx(Box, { sx: { px: 1, py: 0.5 }, children: /* @__PURE__ */ jsx(TextField, { select: true, fullWidth: true, size: "small", label, value, onChange: (event) => onChange(event.target.value), children: options.map((option) => /* @__PURE__ */ jsx(MenuItem, { value: option.value, children: option.label }, option.value)) }) });
29
+ return /* @__PURE__ */ jsx(AppearanceSelectSection, { ownSx: { px: 1, py: 0.5 }, children: /* @__PURE__ */ jsx(TextField, { select: true, fullWidth: true, size: "small", label, value, onChange: (event) => onChange(event.target.value), children: options.map((option) => /* @__PURE__ */ jsx(MenuItem, { value: option.value, children: option.label }, option.value)) }) });
23
30
  }
24
- return /* @__PURE__ */ jsxs(Box, { sx: { px: 1, py: 0.5 }, children: [
25
- /* @__PURE__ */ jsx(Typography, { variant: "overline", color: "text.secondary", component: "p", sx: { px: 1, lineHeight: 1.6 }, children: label }),
31
+ return /* @__PURE__ */ jsxs(AppearanceSection, { ownSx: { px: 1, py: 0.5 }, children: [
32
+ /* @__PURE__ */ jsx(AppearanceSectionLabel, { variant: "overline", color: "text.secondary", component: "p", ownSx: { px: 1, lineHeight: 1.6 }, children: label }),
26
33
  /* @__PURE__ */ jsx(
27
34
  ToggleButtonGroup,
28
35
  {
@@ -36,7 +43,7 @@ function SettingSection({ label, value, options, onChange }) {
36
43
  onChange(nextValue);
37
44
  }
38
45
  },
39
- children: options.map((option) => /* @__PURE__ */ jsxs(ToggleButton, { value: option.value, sx: { gap: 0.75 }, children: [
46
+ children: options.map((option) => /* @__PURE__ */ jsxs(AppearanceOption, { value: option.value, ownSx: { gap: 0.75 }, children: [
40
47
  option.icon,
41
48
  option.label
42
49
  ] }, option.value))
@@ -44,14 +51,15 @@ function SettingSection({ label, value, options, onChange }) {
44
51
  )
45
52
  ] });
46
53
  }
47
- function AppearanceSettings({
48
- showFontSize = true,
49
- showLanguage = true,
50
- showColorScheme = true,
51
- onFontSizeChange,
52
- onColorSchemeChange,
53
- texts
54
- }) {
54
+ function AppearanceSettings(props) {
55
+ const {
56
+ showFontSize = true,
57
+ showLanguage = true,
58
+ showColorScheme = true,
59
+ onFontSizeChange,
60
+ onColorSchemeChange,
61
+ texts
62
+ } = usePieceProps(props, THEME_NAME);
55
63
  const { t, language, changeLanguage } = useToolkitTranslation("layout", texts);
56
64
  const { languages = DEFAULT_LANGUAGES } = useToolkitSettings();
57
65
  const { level, setLevel, levels } = useFontSize();
@@ -105,7 +113,7 @@ function AppearanceSettings({
105
113
  )
106
114
  ].filter(Boolean);
107
115
  return sections.map((section, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
108
- index > 0 && /* @__PURE__ */ jsx(Divider, { sx: { my: 0.5 } }),
116
+ index > 0 && /* @__PURE__ */ jsx(AppearanceDivider, { ownSx: { my: 0.5 } }),
109
117
  section
110
118
  ] }, section.key));
111
119
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AppearanceSettings.js","sources":["../../src/appShell/AppearanceSettings.jsx"],"sourcesContent":["// Los ajustes de cómo se ve la app para esta persona: tamaño de letra, idioma y claro u oscuro, cada uno con sus opciones\n// a la vista (botones de grupo) en lugar de un botón que cambia sin decir a qué. Los usan el engrane del teléfono\n// (SettingsMenu), el menú de la cuenta (AccountMenu) y la pantalla de «Mi perfil» del proyecto: un solo lugar para todos.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {Fragment} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport Divider from '@mui/material/Divider';\nimport MenuItem from '@mui/material/MenuItem';\nimport TextField from '@mui/material/TextField';\nimport ToggleButton from '@mui/material/ToggleButton';\nimport ToggleButtonGroup from '@mui/material/ToggleButtonGroup';\nimport Typography from '@mui/material/Typography';\nimport {useColorScheme} from '@mui/material/styles';\nimport AutomaticModeIcon from '@mui/icons-material/BrightnessAutoOutlined';\nimport DarkModeIcon from '@mui/icons-material/DarkModeOutlined';\nimport LightModeIcon from '@mui/icons-material/LightModeOutlined';\n\nimport {useToolkitSettings} from '@/toolkit/toolkitContext.js';\nimport {DEFAULT_LANGUAGES} from '@/toolkit/toolkitSettings.js';\nimport {useFontSize} from '@/ui/navigation/useFontSize.js';\n\n// cuántas opciones caben como botones lado a lado en el menú de la cuenta; con más, lista desplegable\nconst SETTING_BUTTONS_LIMIT = 3;\n\n/**\n * Un ajuste: su nombre y sus opciones a la vista. Es público: el proyecto agrega los suyos al menú de la cuenta con la\n * misma forma (AppLayout accountSettings), como el vidrio en los ejemplos.\n *\n * @param {object} props\n * @param {string} props.label ya traducido\n * @param {string} props.value la opción elegida\n * @param {Object[]} props.options\n * @param {string} props.options[].value\n * @param {string} props.options[].label ya traducido\n * @param {import('react').ReactNode} [props.options[].icon]\n * @param {(value: string) => void} props.onChange\n */\nexport function SettingSection({label, value, options, onChange}) {\n // con muchas opciones (los idiomas de una app que ofrece cinco) los botones lado a lado no caben: lista desplegable\n if (options.length > SETTING_BUTTONS_LIMIT) {\n return (\n <Box sx={{px: 1, py: 0.5}}>\n <TextField select fullWidth size=\"small\" label={label} value={value} onChange={(event) => onChange(event.target.value)}>\n {options.map((option) => <MenuItem key={option.value} value={option.value}>{option.label}</MenuItem>)}\n </TextField>\n </Box>\n );\n }\n return (\n <Box sx={{px: 1, py: 0.5}}>\n <Typography variant=\"overline\" color=\"text.secondary\" component=\"p\" sx={{px: 1, lineHeight: 1.6}}>{label}</Typography>\n <ToggleButtonGroup value={value} exclusive fullWidth size=\"small\" aria-label={label}\n onChange={(event, nextValue) => {\n // al picar la opción ya elegida MUI manda null: se queda la que estaba\n if (nextValue) {\n onChange(nextValue);\n }\n }}>\n {options.map((option) => (\n <ToggleButton key={option.value} value={option.value} sx={{gap: 0.75}}>{option.icon}{option.label}</ToggleButton>\n ))}\n </ToggleButtonGroup>\n </Box>\n );\n}\n\n/**\n * @param {object} props\n * @param {boolean} [props.showFontSize] por omisión sí\n * @param {boolean} [props.showLanguage] por omisión sí\n * @param {boolean} [props.showColorScheme] por omisión sí\n * @param {(level: string) => void} [props.onFontSizeChange] la persona eligió otro tamaño de letra (para guardarlo en su\n * servidor; el idioma ya sale por onLanguageChange de ToolkitProvider)\n * @param {(mode: 'light'|'dark'|'system') => void} [props.onColorSchemeChange] la persona eligió otro modo\n * @param {object} [props.texts] los textos que cambian, con la forma de `layout` en los textos del paquete\n */\nexport default function AppearanceSettings({\n showFontSize = true, showLanguage = true, showColorScheme = true, onFontSizeChange, onColorSchemeChange, texts,\n}) {\n const {t, language, changeLanguage} = useToolkitTranslation('layout', texts);\n const {languages = DEFAULT_LANGUAGES} = useToolkitSettings();\n const {level, setLevel, levels} = useFontSize();\n const {mode, setMode} = useColorScheme();\n const chooseFontSize = (nextLevel) => {\n setLevel(nextLevel);\n onFontSizeChange?.(nextLevel);\n };\n const chooseColorScheme = (nextMode) => {\n setMode(nextMode);\n onColorSchemeChange?.(nextMode);\n };\n\n const sections = [\n showFontSize && (\n <SettingSection key=\"fontSize\" label={t('fontSize.label')} value={level} onChange={chooseFontSize}\n options={levels.map((option) => ({value: option.key, label: t(option.labelKey)}))} />\n ),\n showLanguage && (\n <SettingSection key=\"language\" label={t('settings.language')} value={language} onChange={changeLanguage}\n // los idiomas de la app; español e inglés con su nombre de siempre, los del proyecto con el suyo\n options={languages.map((entry) => ({value: entry.code, label: t(`languageName.${entry.code}`, {defaultValue: entry.label})}))} />\n ),\n // antes de montar no se sabe el modo (el servidor no lo conoce): la sección sale ya montada.\n // Tres opciones: «Automático» (system de MUI) sigue lo que diga el equipo y es lo de omisión. Es la ÚNICA salida\n // para volver a seguirlo: el botón de la barra (ColorSchemeToggle) fija claro u oscuro para siempre. La guía de\n // Apple pide seguir el ajuste del equipo; el botón de la barra se queda con dos estados para no sumar una decisión.\n showColorScheme && mode && (\n <SettingSection key=\"colorScheme\" label={t('settings.colorScheme')} value={mode} onChange={chooseColorScheme}\n options={[\n {value: 'light', label: t('settings.light'), icon: <LightModeIcon fontSize=\"small\" />},\n {value: 'dark', label: t('settings.dark'), icon: <DarkModeIcon fontSize=\"small\" />},\n {value: 'system', label: t('settings.system'), icon: <AutomaticModeIcon fontSize=\"small\" />},\n ]} />\n ),\n ].filter(Boolean);\n\n return sections.map((section, index) => (\n <Fragment key={section.key}>\n {index > 0 && <Divider sx={{my: 0.5}} />}\n {section}\n </Fragment>\n ));\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AppearanceSettings.js","sources":["../../src/appShell/AppearanceSettings.jsx"],"sourcesContent":["// Los ajustes de cómo se ve la app para esta persona: tamaño de letra, idioma y claro u oscuro, cada uno con sus opciones\n// a la vista (botones de grupo) en lugar de un botón que cambia sin decir a qué. Los usan el engrane del teléfono\n// (SettingsMenu), el menú de la cuenta (AccountMenu) y la pantalla de «Mi perfil» del proyecto: un solo lugar para todos.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaAppearanceSettings con defaultProps y\n// styleOverrides de sus partes: selectSection, section, sectionLabel, option, divider.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {Fragment} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport Divider from '@mui/material/Divider';\nimport MenuItem from '@mui/material/MenuItem';\nimport TextField from '@mui/material/TextField';\nimport ToggleButton from '@mui/material/ToggleButton';\nimport ToggleButtonGroup from '@mui/material/ToggleButtonGroup';\nimport Typography from '@mui/material/Typography';\nimport {useColorScheme} from '@mui/material/styles';\nimport AutomaticModeIcon from '@mui/icons-material/BrightnessAutoOutlined';\nimport DarkModeIcon from '@mui/icons-material/DarkModeOutlined';\nimport LightModeIcon from '@mui/icons-material/LightModeOutlined';\n\nimport {useToolkitSettings} from '@/toolkit/toolkitContext.js';\nimport {DEFAULT_LANGUAGES} from '@/toolkit/toolkitSettings.js';\nimport {useFontSize} from '@/ui/navigation/useFontSize.js';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaAppearanceSettings)\nconst THEME_NAME = 'CalcitaAppearanceSettings';\nconst AppearanceSelectSection = piecePart(THEME_NAME, 'SelectSection', Box);\nconst AppearanceSection = piecePart(THEME_NAME, 'Section', Box);\nconst AppearanceSectionLabel = piecePart(THEME_NAME, 'SectionLabel', Typography);\nconst AppearanceOption = piecePart(THEME_NAME, 'Option', ToggleButton);\nconst AppearanceDivider = piecePart(THEME_NAME, 'Divider', Divider);\n\n// cuántas opciones caben como botones lado a lado en el menú de la cuenta; con más, lista desplegable\nconst SETTING_BUTTONS_LIMIT = 3;\n\n/**\n * Un ajuste: su nombre y sus opciones a la vista. Es público: el proyecto agrega los suyos al menú de la cuenta con la\n * misma forma (AppLayout accountSettings), como el vidrio en los ejemplos.\n *\n * @param {object} props\n * @param {string} props.label ya traducido\n * @param {string} props.value la opción elegida\n * @param {Object[]} props.options\n * @param {string} props.options[].value\n * @param {string} props.options[].label ya traducido\n * @param {import('react').ReactNode} [props.options[].icon]\n * @param {(value: string) => void} props.onChange\n */\nexport function SettingSection({label, value, options, onChange}) {\n // con muchas opciones (los idiomas de una app que ofrece cinco) los botones lado a lado no caben: lista desplegable\n if (options.length > SETTING_BUTTONS_LIMIT) {\n return (\n <AppearanceSelectSection ownSx={{px: 1, py: 0.5}}>\n <TextField select fullWidth size=\"small\" label={label} value={value} onChange={(event) => onChange(event.target.value)}>\n {options.map((option) => <MenuItem key={option.value} value={option.value}>{option.label}</MenuItem>)}\n </TextField>\n </AppearanceSelectSection>\n );\n }\n return (\n <AppearanceSection ownSx={{px: 1, py: 0.5}}>\n <AppearanceSectionLabel variant=\"overline\" color=\"text.secondary\" component=\"p\" ownSx={{px: 1, lineHeight: 1.6}}>{label}</AppearanceSectionLabel>\n <ToggleButtonGroup value={value} exclusive fullWidth size=\"small\" aria-label={label}\n onChange={(event, nextValue) => {\n // al picar la opción ya elegida MUI manda null: se queda la que estaba\n if (nextValue) {\n onChange(nextValue);\n }\n }}>\n {options.map((option) => (\n <AppearanceOption key={option.value} value={option.value} ownSx={{gap: 0.75}}>{option.icon}{option.label}</AppearanceOption>\n ))}\n </ToggleButtonGroup>\n </AppearanceSection>\n );\n}\n\n/**\n * @param {object} props\n * @param {boolean} [props.showFontSize] por omisión sí\n * @param {boolean} [props.showLanguage] por omisión sí\n * @param {boolean} [props.showColorScheme] por omisión sí\n * @param {(level: string) => void} [props.onFontSizeChange] la persona eligió otro tamaño de letra (para guardarlo en su\n * servidor; el idioma ya sale por onLanguageChange de ToolkitProvider)\n * @param {(mode: 'light'|'dark'|'system') => void} [props.onColorSchemeChange] la persona eligió otro modo\n * @param {object} [props.texts] los textos que cambian, con la forma de `layout` en los textos del paquete\n */\nexport default function AppearanceSettings(props) {\n // lo que el proyecto puso en su tema (components.CalcitaAppearanceSettings.defaultProps) y encima lo que llega aquí\n const {\n showFontSize = true, showLanguage = true, showColorScheme = true, onFontSizeChange, onColorSchemeChange, texts,\n} = usePieceProps(props, THEME_NAME);\n const {t, language, changeLanguage} = useToolkitTranslation('layout', texts);\n const {languages = DEFAULT_LANGUAGES} = useToolkitSettings();\n const {level, setLevel, levels} = useFontSize();\n const {mode, setMode} = useColorScheme();\n const chooseFontSize = (nextLevel) => {\n setLevel(nextLevel);\n onFontSizeChange?.(nextLevel);\n };\n const chooseColorScheme = (nextMode) => {\n setMode(nextMode);\n onColorSchemeChange?.(nextMode);\n };\n\n const sections = [\n showFontSize && (\n <SettingSection key=\"fontSize\" label={t('fontSize.label')} value={level} onChange={chooseFontSize}\n options={levels.map((option) => ({value: option.key, label: t(option.labelKey)}))} />\n ),\n showLanguage && (\n <SettingSection key=\"language\" label={t('settings.language')} value={language} onChange={changeLanguage}\n // los idiomas de la app; español e inglés con su nombre de siempre, los del proyecto con el suyo\n options={languages.map((entry) => ({value: entry.code, label: t(`languageName.${entry.code}`, {defaultValue: entry.label})}))} />\n ),\n // antes de montar no se sabe el modo (el servidor no lo conoce): la sección sale ya montada.\n // Tres opciones: «Automático» (system de MUI) sigue lo que diga el equipo y es lo de omisión. Es la ÚNICA salida\n // para volver a seguirlo: el botón de la barra (ColorSchemeToggle) fija claro u oscuro para siempre. La guía de\n // Apple pide seguir el ajuste del equipo; el botón de la barra se queda con dos estados para no sumar una decisión.\n showColorScheme && mode && (\n <SettingSection key=\"colorScheme\" label={t('settings.colorScheme')} value={mode} onChange={chooseColorScheme}\n options={[\n {value: 'light', label: t('settings.light'), icon: <LightModeIcon fontSize=\"small\" />},\n {value: 'dark', label: t('settings.dark'), icon: <DarkModeIcon fontSize=\"small\" />},\n {value: 'system', label: t('settings.system'), icon: <AutomaticModeIcon fontSize=\"small\" />},\n ]} />\n ),\n ].filter(Boolean);\n\n return sections.map((section, index) => (\n <Fragment key={section.key}>\n {index > 0 && <AppearanceDivider ownSx={{my: 0.5}} />}\n {section}\n </Fragment>\n ));\n}\n"],"names":[],"mappings":"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"}
@@ -5,38 +5,51 @@ import Box from "@mui/material/Box";
5
5
  import Paper from "@mui/material/Paper";
6
6
  import Stack from "@mui/material/Stack";
7
7
  import Typography from "@mui/material/Typography";
8
- import { GLASS_PANEL_RADIUS_PIXELS, isGlassTheme, ambientBackgroundOf, glassStylesOf } from "../theme/glassSurface.js";
8
+ import { PANEL_RADIUS, isGlassTheme, ambientBackgroundOf, glassStylesOf } from "../theme/glassSurface.js";
9
9
  import NewBuildNotice, { NEW_BUILD_NOTICE_VARIANT } from "../feedback/NewBuildNotice.js";
10
10
  import GlassLensFilter from "../ui/layout/GlassLensFilter.js";
11
11
  import DocumentTitle from "../ui/navigation/DocumentTitle.js";
12
12
  import ColorSchemeToggle from "../ui/navigation/ColorSchemeToggle.js";
13
13
  import LanguageToggle from "../ui/navigation/LanguageToggle.js";
14
+ import { piecePart, usePieceProps } from "../theme/themePieces.js";
15
+ const THEME_NAME = "CalcitaAuthLayout";
16
+ const AuthRoot = piecePart(THEME_NAME, "Root", Box);
17
+ const AuthTools = piecePart(THEME_NAME, "Tools", Stack);
18
+ const AuthBody = piecePart(THEME_NAME, "Body", Box);
19
+ const AuthBrand = piecePart(THEME_NAME, "Brand", Stack);
20
+ const AuthLogo = piecePart(THEME_NAME, "Logo", Box);
21
+ const AuthBrandName = piecePart(THEME_NAME, "BrandName", Typography);
22
+ const AuthCard = piecePart(THEME_NAME, "Card", Paper);
23
+ const AuthDescription = piecePart(THEME_NAME, "Description", Typography);
24
+ const AuthContent = piecePart(THEME_NAME, "Content", Box);
25
+ const AuthFooter = piecePart(THEME_NAME, "Footer", Box);
14
26
  const CARD_MAX_WIDTH_PIXELS = 440;
15
- const cardSurfaceOf = (theme) => isGlassTheme(theme) ? { ...glassStylesOf(theme), borderColor: "transparent", borderRadius: `${GLASS_PANEL_RADIUS_PIXELS}px` } : {};
16
- const AuthLayout = ({ logo, brandName, title, description, children, footer, showLanguageToggle = true, showColorSchemeToggle = true }) => {
27
+ const cardSurfaceOf = (theme) => isGlassTheme(theme) ? { ...glassStylesOf(theme), borderColor: "transparent", borderRadius: PANEL_RADIUS } : {};
28
+ const AuthLayout = (props) => {
29
+ const { logo, brandName, title, description, children, footer, showLanguageToggle = true, showColorSchemeToggle = true } = usePieceProps(props, THEME_NAME);
17
30
  const { appName } = useToolkitSettings();
18
- return /* @__PURE__ */ jsxs(Box, { sx: [
31
+ return /* @__PURE__ */ jsxs(AuthRoot, { ownSx: [
19
32
  { minHeight: "100vh", display: "flex", flexDirection: "column", bgcolor: "background.default" },
20
33
  (theme) => isGlassTheme(theme) ? ambientBackgroundOf(theme) : {}
21
34
  ], children: [
22
35
  /* @__PURE__ */ jsx(DocumentTitle, { title }),
23
36
  /* @__PURE__ */ jsx(GlassLensFilter, {}),
24
37
  /* @__PURE__ */ jsx(NewBuildNotice, { variant: NEW_BUILD_NOTICE_VARIANT.floating }),
25
- /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, sx: { justifyContent: "flex-end", p: 2, pt: "max(16px, env(safe-area-inset-top))" }, children: [
38
+ /* @__PURE__ */ jsxs(AuthTools, { direction: "row", spacing: 1, ownSx: { justifyContent: "flex-end", p: 2, pt: "max(16px, env(safe-area-inset-top))" }, children: [
26
39
  showLanguageToggle && /* @__PURE__ */ jsx(LanguageToggle, {}),
27
40
  showColorSchemeToggle && /* @__PURE__ */ jsx(ColorSchemeToggle, {})
28
41
  ] }),
29
- /* @__PURE__ */ jsxs(Box, { component: "main", sx: { flexGrow: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", px: 2, pb: 6 }, children: [
30
- /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1.25, sx: { alignItems: "center", mb: 3 }, children: [
31
- logo && /* @__PURE__ */ jsx(Box, { sx: { width: 28, height: 28, display: "flex", alignItems: "center", justifyContent: "center" }, children: logo }),
32
- /* @__PURE__ */ jsx(Typography, { variant: "subtitle1", component: "p", sx: { fontWeight: 600 }, children: brandName ?? appName })
42
+ /* @__PURE__ */ jsxs(AuthBody, { component: "main", ownSx: { flexGrow: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", px: 2, pb: 6 }, children: [
43
+ /* @__PURE__ */ jsxs(AuthBrand, { direction: "row", spacing: 1.25, ownSx: { alignItems: "center", mb: 3 }, children: [
44
+ logo && /* @__PURE__ */ jsx(AuthLogo, { ownSx: { width: 28, height: 28, display: "flex", alignItems: "center", justifyContent: "center" }, children: logo }),
45
+ /* @__PURE__ */ jsx(AuthBrandName, { variant: "subtitle1", component: "p", ownSx: { fontWeight: 600 }, children: brandName ?? appName })
33
46
  ] }),
34
- /* @__PURE__ */ jsxs(Paper, { variant: "outlined", sx: [{ width: "100%", maxWidth: CARD_MAX_WIDTH_PIXELS, p: { xs: 3, sm: 4 } }, cardSurfaceOf], children: [
47
+ /* @__PURE__ */ jsxs(AuthCard, { variant: "outlined", ownSx: [{ width: "100%", maxWidth: CARD_MAX_WIDTH_PIXELS, p: { xs: 3, sm: 4 } }, cardSurfaceOf], children: [
35
48
  /* @__PURE__ */ jsx(Typography, { variant: "h5", component: "h1", children: title }),
36
- description && /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", sx: { mt: 1 }, children: description }),
37
- /* @__PURE__ */ jsx(Box, { sx: { mt: 3 }, children })
49
+ description && /* @__PURE__ */ jsx(AuthDescription, { variant: "body2", color: "text.secondary", ownSx: { mt: 1 }, children: description }),
50
+ /* @__PURE__ */ jsx(AuthContent, { ownSx: { mt: 3 }, children })
38
51
  ] }),
39
- footer && /* @__PURE__ */ jsx(Box, { sx: { width: "100%", maxWidth: CARD_MAX_WIDTH_PIXELS, mt: 2 }, children: footer })
52
+ footer && /* @__PURE__ */ jsx(AuthFooter, { ownSx: { width: "100%", maxWidth: CARD_MAX_WIDTH_PIXELS, mt: 2 }, children: footer })
40
53
  ] })
41
54
  ] });
42
55
  };
@@ -1 +1 @@
1
- {"version":3,"file":"AuthLayout.js","sources":["../../src/appShell/AuthLayout.jsx"],"sourcesContent":["// La pantalla de entrada (iniciar sesión, «¿olvidó su contraseña?», elegir una contraseña nueva): el logo y el nombre de\n// la app, una tarjeta al centro con su título y lo que lleve adentro, y arriba a la derecha el idioma y claro u oscuro\n// (quien no ha entrado también los necesita). Como la plantilla «Sign in» de MUI.\n//\n// <AuthLayout logo={<Logo />} title={t('auth:signIn.title')} description={t('auth:signIn.subtitle')}>\n// <SignInForm onSubmit={signIn} forgotPasswordPath=\"/forgot-password\" />\n// </AuthLayout>\n//\n// Con el vidrio del tema (createToolkitTheme({glass: true})), el lienzo lleva sus manchas de color y la tarjeta es de\n// vidrio; sin vidrio, una tarjeta con borde sobre el lienzo.\n//\n// También pinta el aviso de versión nueva (cápsula flotante), como el marco: quien abre la app sin sesión (o la deja abierta\n// en esta pantalla) también debe enterarse; antes solo salía en las pantallas con sesión.\n//\n// Lo renderiza la app: arrow (regla de la casa).\nimport {useToolkitSettings} from '@/toolkit/toolkitContext.js';\nimport Box from '@mui/material/Box';\nimport Paper from '@mui/material/Paper';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\n\nimport {GLASS_PANEL_RADIUS_PIXELS, ambientBackgroundOf, glassStylesOf, isGlassTheme} from '@/theme/glassSurface.js';\nimport NewBuildNotice, {NEW_BUILD_NOTICE_VARIANT} from '@/feedback/NewBuildNotice.jsx';\nimport GlassLensFilter from '@/ui/layout/GlassLensFilter.jsx';\nimport DocumentTitle from '@/ui/navigation/DocumentTitle.jsx';\nimport ColorSchemeToggle from '@/ui/navigation/ColorSchemeToggle.jsx';\nimport LanguageToggle from '@/ui/navigation/LanguageToggle.jsx';\n\n// lo ancho de la tarjeta: lo que cabe cómodo un correo largo\nconst CARD_MAX_WIDTH_PIXELS = 440;\n\n/**\n * La tarjeta: de vidrio si el tema lo trae; si no, con borde.\n *\n * @param {object} theme\n * @returns {object}\n */\nconst cardSurfaceOf = (theme) => (isGlassTheme(theme)\n ? {...glassStylesOf(theme), borderColor: 'transparent', borderRadius: `${GLASS_PANEL_RADIUS_PIXELS}px`}\n : {});\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode} [props.logo] el logo chico (28 px)\n * @param {string} [props.brandName] por omisión el appName de ToolkitProvider\n * @param {string} props.title el título de la tarjeta y de la pestaña, ya traducido\n * @param {import('react').ReactNode} [props.description] el renglón debajo del título\n * @param {import('react').ReactNode} props.children el formulario\n * @param {import('react').ReactNode} [props.footer] debajo de la tarjeta (los botones de prueba, el aviso de privacidad…)\n * @param {boolean} [props.showLanguageToggle] por omisión sí\n * @param {boolean} [props.showColorSchemeToggle] por omisión sí\n */\nexport const AuthLayout = ({logo, brandName, title, description, children, footer, showLanguageToggle = true, showColorSchemeToggle = true}) => {\n const {appName} = useToolkitSettings();\n return (\n <Box sx={[{minHeight: '100vh', display: 'flex', flexDirection: 'column', bgcolor: 'background.default'},\n (theme) => (isGlassTheme(theme) ? ambientBackgroundOf(theme) : {})]}>\n <DocumentTitle title={title} />\n <GlassLensFilter />\n <NewBuildNotice variant={NEW_BUILD_NOTICE_VARIANT.floating} />\n <Stack direction=\"row\" spacing={1} sx={{justifyContent: 'flex-end', p: 2, pt: 'max(16px, env(safe-area-inset-top))'}}>\n {showLanguageToggle && <LanguageToggle />}\n {showColorSchemeToggle && <ColorSchemeToggle />}\n </Stack>\n <Box component=\"main\" sx={{flexGrow: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', px: 2, pb: 6}}>\n <Stack direction=\"row\" spacing={1.25} sx={{alignItems: 'center', mb: 3}}>\n {logo && <Box sx={{width: 28, height: 28, display: 'flex', alignItems: 'center', justifyContent: 'center'}}>{logo}</Box>}\n <Typography variant=\"subtitle1\" component=\"p\" sx={{fontWeight: 600}}>{brandName ?? appName}</Typography>\n </Stack>\n <Paper variant=\"outlined\" sx={[{width: '100%', maxWidth: CARD_MAX_WIDTH_PIXELS, p: {xs: 3, sm: 4}}, cardSurfaceOf]}>\n <Typography variant=\"h5\" component=\"h1\">{title}</Typography>\n {description && <Typography variant=\"body2\" color=\"text.secondary\" sx={{mt: 1}}>{description}</Typography>}\n <Box sx={{mt: 3}}>{children}</Box>\n </Paper>\n {footer && <Box sx={{width: '100%', maxWidth: CARD_MAX_WIDTH_PIXELS, mt: 2}}>{footer}</Box>}\n </Box>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;AA6BA,MAAM,wBAAwB;AAQ9B,MAAM,gBAAgB,CAAC,UAAW,aAAa,KAAK,IAC9C,EAAC,GAAG,cAAc,KAAK,GAAG,aAAa,eAAe,cAAc,GAAG,yBAAyB,KAAA,IAChG,CAAA;AAaC,MAAM,aAAa,CAAC,EAAC,MAAM,WAAW,OAAO,aAAa,UAAU,QAAQ,qBAAqB,MAAM,wBAAwB,WAAU;AAC5I,QAAM,EAAC,QAAA,IAAW,mBAAA;AAClB,SACI,qBAAC,OAAI,IAAI;AAAA,IAAC,EAAC,WAAW,SAAS,SAAS,QAAQ,eAAe,UAAU,SAAS,qBAAA;AAAA,IAC9E,CAAC,UAAW,aAAa,KAAK,IAAI,oBAAoB,KAAK,IAAI,CAAA;AAAA,EAAC,GAChE,UAAA;AAAA,IAAA,oBAAC,iBAAc,OAAc;AAAA,wBAC5B,iBAAA,EAAgB;AAAA,IACjB,oBAAC,gBAAA,EAAe,SAAS,yBAAyB,SAAA,CAAU;AAAA,IAC5D,qBAAC,OAAA,EAAM,WAAU,OAAM,SAAS,GAAG,IAAI,EAAC,gBAAgB,YAAY,GAAG,GAAG,IAAI,yCACzE,UAAA;AAAA,MAAA,0CAAuB,gBAAA,EAAe;AAAA,MACtC,6CAA0B,mBAAA,CAAA,CAAkB;AAAA,IAAA,GACjD;AAAA,IACA,qBAAC,OAAI,WAAU,QAAO,IAAI,EAAC,UAAU,GAAG,SAAS,QAAQ,eAAe,UAAU,YAAY,UAAU,gBAAgB,UAAU,IAAI,GAAG,IAAI,KACzI,UAAA;AAAA,MAAA,qBAAC,OAAA,EAAM,WAAU,OAAM,SAAS,MAAM,IAAI,EAAC,YAAY,UAAU,IAAI,EAAA,GAChE,UAAA;AAAA,QAAA,QAAQ,oBAAC,KAAA,EAAI,IAAI,EAAC,OAAO,IAAI,QAAQ,IAAI,SAAS,QAAQ,YAAY,UAAU,gBAAgB,YAAY,UAAA,MAAK;AAAA,QAClH,oBAAC,YAAA,EAAW,SAAQ,aAAY,WAAU,KAAI,IAAI,EAAC,YAAY,IAAA,GAAO,UAAA,aAAa,QAAA,CAAQ;AAAA,MAAA,GAC/F;AAAA,MACA,qBAAC,SAAM,SAAQ,YAAW,IAAI,CAAC,EAAC,OAAO,QAAQ,UAAU,uBAAuB,GAAG,EAAC,IAAI,GAAG,IAAI,IAAC,GAAI,aAAa,GAC7G,UAAA;AAAA,QAAA,oBAAC,YAAA,EAAW,SAAQ,MAAK,WAAU,MAAM,UAAA,OAAM;AAAA,QAC9C,eAAe,oBAAC,YAAA,EAAW,SAAQ,SAAQ,OAAM,kBAAiB,IAAI,EAAC,IAAI,EAAA,GAAK,UAAA,YAAA,CAAY;AAAA,4BAC5F,KAAA,EAAI,IAAI,EAAC,IAAI,EAAA,GAAK,SAAA,CAAS;AAAA,MAAA,GAChC;AAAA,MACC,UAAU,oBAAC,KAAA,EAAI,IAAI,EAAC,OAAO,QAAQ,UAAU,uBAAuB,IAAI,EAAA,GAAK,UAAA,OAAA,CAAO;AAAA,IAAA,EAAA,CACzF;AAAA,EAAA,GACJ;AAER;"}
1
+ {"version":3,"file":"AuthLayout.js","sources":["../../src/appShell/AuthLayout.jsx"],"sourcesContent":["// La pantalla de entrada (iniciar sesión, «¿olvidó su contraseña?», elegir una contraseña nueva): el logo y el nombre de\n// la app, una tarjeta al centro con su título y lo que lleve adentro, y arriba a la derecha el idioma y claro u oscuro\n// (quien no ha entrado también los necesita). Como la plantilla «Sign in» de MUI.\n//\n// <AuthLayout logo={<Logo />} title={t('auth:signIn.title')} description={t('auth:signIn.subtitle')}>\n// <SignInForm onSubmit={signIn} forgotPasswordPath=\"/forgot-password\" />\n// </AuthLayout>\n//\n// Con el vidrio del tema (createToolkitTheme({glass: true})), el lienzo lleva sus manchas de color y la tarjeta es de\n// vidrio; sin vidrio, una tarjeta con borde sobre el lienzo.\n//\n// También pinta el aviso de versión nueva (cápsula flotante), como el marco: quien abre la app sin sesión (o la deja abierta\n// en esta pantalla) también debe enterarse; antes solo salía en las pantallas con sesión.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaAuthLayout con defaultProps y\n// styleOverrides de sus partes: root, tools, body, brand, logo, brandName, card, description, content, footer.\n//\n// Lo renderiza la app: arrow (regla de la casa).\nimport {useToolkitSettings} from '@/toolkit/toolkitContext.js';\nimport Box from '@mui/material/Box';\nimport Paper from '@mui/material/Paper';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\n\nimport {PANEL_RADIUS, ambientBackgroundOf, glassStylesOf, isGlassTheme} from '@/theme/glassSurface.js';\nimport NewBuildNotice, {NEW_BUILD_NOTICE_VARIANT} from '@/feedback/NewBuildNotice.jsx';\nimport GlassLensFilter from '@/ui/layout/GlassLensFilter.jsx';\nimport DocumentTitle from '@/ui/navigation/DocumentTitle.jsx';\nimport ColorSchemeToggle from '@/ui/navigation/ColorSchemeToggle.jsx';\nimport LanguageToggle from '@/ui/navigation/LanguageToggle.jsx';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaAuthLayout)\nconst THEME_NAME = 'CalcitaAuthLayout';\nconst AuthRoot = piecePart(THEME_NAME, 'Root', Box);\nconst AuthTools = piecePart(THEME_NAME, 'Tools', Stack);\nconst AuthBody = piecePart(THEME_NAME, 'Body', Box);\nconst AuthBrand = piecePart(THEME_NAME, 'Brand', Stack);\nconst AuthLogo = piecePart(THEME_NAME, 'Logo', Box);\nconst AuthBrandName = piecePart(THEME_NAME, 'BrandName', Typography);\nconst AuthCard = piecePart(THEME_NAME, 'Card', Paper);\nconst AuthDescription = piecePart(THEME_NAME, 'Description', Typography);\nconst AuthContent = piecePart(THEME_NAME, 'Content', Box);\nconst AuthFooter = piecePart(THEME_NAME, 'Footer', Box);\n\n// lo ancho de la tarjeta: lo que cabe cómodo un correo largo\nconst CARD_MAX_WIDTH_PIXELS = 440;\n\n/**\n * La tarjeta: de vidrio si el tema lo trae; si no, con borde.\n *\n * @param {object} theme\n * @returns {object}\n */\nconst cardSurfaceOf = (theme) => (isGlassTheme(theme)\n ? {...glassStylesOf(theme), borderColor: 'transparent', borderRadius: PANEL_RADIUS}\n : {});\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode} [props.logo] el logo chico (28 px)\n * @param {string} [props.brandName] por omisión el appName de ToolkitProvider\n * @param {string} props.title el título de la tarjeta y de la pestaña, ya traducido\n * @param {import('react').ReactNode} [props.description] el renglón debajo del título\n * @param {import('react').ReactNode} props.children el formulario\n * @param {import('react').ReactNode} [props.footer] debajo de la tarjeta (los botones de prueba, el aviso de privacidad…)\n * @param {boolean} [props.showLanguageToggle] por omisión sí\n * @param {boolean} [props.showColorSchemeToggle] por omisión sí\n */\nexport const AuthLayout = (props) => {\n // lo que el proyecto puso en su tema (components.CalcitaAuthLayout.defaultProps) y encima lo que llega aquí\n const {logo, brandName, title, description, children, footer, showLanguageToggle = true, showColorSchemeToggle = true} = usePieceProps(props, THEME_NAME);\n const {appName} = useToolkitSettings();\n return (\n <AuthRoot ownSx={[{minHeight: '100vh', display: 'flex', flexDirection: 'column', bgcolor: 'background.default'},\n (theme) => (isGlassTheme(theme) ? ambientBackgroundOf(theme) : {})]}>\n <DocumentTitle title={title} />\n <GlassLensFilter />\n <NewBuildNotice variant={NEW_BUILD_NOTICE_VARIANT.floating} />\n <AuthTools direction=\"row\" spacing={1} ownSx={{justifyContent: 'flex-end', p: 2, pt: 'max(16px, env(safe-area-inset-top))'}}>\n {showLanguageToggle && <LanguageToggle />}\n {showColorSchemeToggle && <ColorSchemeToggle />}\n </AuthTools>\n <AuthBody component=\"main\" ownSx={{flexGrow: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', px: 2, pb: 6}}>\n <AuthBrand direction=\"row\" spacing={1.25} ownSx={{alignItems: 'center', mb: 3}}>\n {logo && <AuthLogo ownSx={{width: 28, height: 28, display: 'flex', alignItems: 'center', justifyContent: 'center'}}>{logo}</AuthLogo>}\n <AuthBrandName variant=\"subtitle1\" component=\"p\" ownSx={{fontWeight: 600}}>{brandName ?? appName}</AuthBrandName>\n </AuthBrand>\n <AuthCard variant=\"outlined\" ownSx={[{width: '100%', maxWidth: CARD_MAX_WIDTH_PIXELS, p: {xs: 3, sm: 4}}, cardSurfaceOf]}>\n <Typography variant=\"h5\" component=\"h1\">{title}</Typography>\n {description && <AuthDescription variant=\"body2\" color=\"text.secondary\" ownSx={{mt: 1}}>{description}</AuthDescription>}\n <AuthContent ownSx={{mt: 3}}>{children}</AuthContent>\n </AuthCard>\n {footer && <AuthFooter ownSx={{width: '100%', maxWidth: CARD_MAX_WIDTH_PIXELS, mt: 2}}>{footer}</AuthFooter>}\n </AuthBody>\n </AuthRoot>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;AAiCA,MAAM,aAAa;AACnB,MAAM,WAAW,UAAU,YAAY,QAAQ,GAAG;AAClD,MAAM,YAAY,UAAU,YAAY,SAAS,KAAK;AACtD,MAAM,WAAW,UAAU,YAAY,QAAQ,GAAG;AAClD,MAAM,YAAY,UAAU,YAAY,SAAS,KAAK;AACtD,MAAM,WAAW,UAAU,YAAY,QAAQ,GAAG;AAClD,MAAM,gBAAgB,UAAU,YAAY,aAAa,UAAU;AACnE,MAAM,WAAW,UAAU,YAAY,QAAQ,KAAK;AACpD,MAAM,kBAAkB,UAAU,YAAY,eAAe,UAAU;AACvE,MAAM,cAAc,UAAU,YAAY,WAAW,GAAG;AACxD,MAAM,aAAa,UAAU,YAAY,UAAU,GAAG;AAGtD,MAAM,wBAAwB;AAQ9B,MAAM,gBAAgB,CAAC,UAAW,aAAa,KAAK,IAC9C,EAAC,GAAG,cAAc,KAAK,GAAG,aAAa,eAAe,cAAc,aAAA,IACpE,CAAA;AAaC,MAAM,aAAa,CAAC,UAAU;AAEjC,QAAM,EAAC,MAAM,WAAW,OAAO,aAAa,UAAU,QAAQ,qBAAqB,MAAM,wBAAwB,KAAA,IAAQ,cAAc,OAAO,UAAU;AACxJ,QAAM,EAAC,QAAA,IAAW,mBAAA;AAClB,SACI,qBAAC,YAAS,OAAO;AAAA,IAAC,EAAC,WAAW,SAAS,SAAS,QAAQ,eAAe,UAAU,SAAS,qBAAA;AAAA,IACtF,CAAC,UAAW,aAAa,KAAK,IAAI,oBAAoB,KAAK,IAAI,CAAA;AAAA,EAAC,GAChE,UAAA;AAAA,IAAA,oBAAC,iBAAc,OAAc;AAAA,wBAC5B,iBAAA,EAAgB;AAAA,IACjB,oBAAC,gBAAA,EAAe,SAAS,yBAAyB,SAAA,CAAU;AAAA,IAC5D,qBAAC,WAAA,EAAU,WAAU,OAAM,SAAS,GAAG,OAAO,EAAC,gBAAgB,YAAY,GAAG,GAAG,IAAI,yCAChF,UAAA;AAAA,MAAA,0CAAuB,gBAAA,EAAe;AAAA,MACtC,6CAA0B,mBAAA,CAAA,CAAkB;AAAA,IAAA,GACjD;AAAA,IACA,qBAAC,YAAS,WAAU,QAAO,OAAO,EAAC,UAAU,GAAG,SAAS,QAAQ,eAAe,UAAU,YAAY,UAAU,gBAAgB,UAAU,IAAI,GAAG,IAAI,KACjJ,UAAA;AAAA,MAAA,qBAAC,WAAA,EAAU,WAAU,OAAM,SAAS,MAAM,OAAO,EAAC,YAAY,UAAU,IAAI,EAAA,GACvE,UAAA;AAAA,QAAA,QAAQ,oBAAC,UAAA,EAAS,OAAO,EAAC,OAAO,IAAI,QAAQ,IAAI,SAAS,QAAQ,YAAY,UAAU,gBAAgB,YAAY,UAAA,MAAK;AAAA,QAC1H,oBAAC,eAAA,EAAc,SAAQ,aAAY,WAAU,KAAI,OAAO,EAAC,YAAY,IAAA,GAAO,UAAA,aAAa,QAAA,CAAQ;AAAA,MAAA,GACrG;AAAA,MACA,qBAAC,YAAS,SAAQ,YAAW,OAAO,CAAC,EAAC,OAAO,QAAQ,UAAU,uBAAuB,GAAG,EAAC,IAAI,GAAG,IAAI,IAAC,GAAI,aAAa,GACnH,UAAA;AAAA,QAAA,oBAAC,YAAA,EAAW,SAAQ,MAAK,WAAU,MAAM,UAAA,OAAM;AAAA,QAC9C,eAAe,oBAAC,iBAAA,EAAgB,SAAQ,SAAQ,OAAM,kBAAiB,OAAO,EAAC,IAAI,EAAA,GAAK,UAAA,YAAA,CAAY;AAAA,4BACpG,aAAA,EAAY,OAAO,EAAC,IAAI,EAAA,GAAK,SAAA,CAAS;AAAA,MAAA,GAC3C;AAAA,MACC,UAAU,oBAAC,YAAA,EAAW,OAAO,EAAC,OAAO,QAAQ,UAAU,uBAAuB,IAAI,EAAA,GAAK,UAAA,OAAA,CAAO;AAAA,IAAA,EAAA,CACnG;AAAA,EAAA,GACJ;AAER;"}
@@ -14,6 +14,9 @@ import { useBarActionsSlot, BarActionsPlacementContext, BAR_ACTIONS_PLACEMENT, B
14
14
  import { DESKTOP_MEDIA_QUERY } from "./shellSizes.js";
15
15
  import useFittingActionCount from "./useFittingActionCount.js";
16
16
  import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
17
+ import { piecePart, usePieceProps } from "../theme/themePieces.js";
18
+ const THEME_NAME = "CalcitaBarActions";
19
+ const ActionsGroup = piecePart(THEME_NAME, "Group", Box);
17
20
  const EXCLUSIVE_ATTRIBUTE = "data-bar-exclusive";
18
21
  const HIDE_NOT_EXCLUSIVE_STYLES = { [`[data-phone-bar-actions] > :not([${EXCLUSIVE_ATTRIBUTE}])`]: { display: "none !important" } };
19
22
  const InCapsule = ({ children }) => /* @__PURE__ */ jsx(BarActionsPlacementContext.Provider, { value: BAR_ACTIONS_PLACEMENT.capsule, children });
@@ -56,7 +59,8 @@ const PhoneFloatingCapsule = ({ phoneSlot, label, sx, texts, children, ...rest }
56
59
  hiddenActions.length > 0 && /* @__PURE__ */ jsx(MoreActionsMenu, { label: t("barActions.more"), children: hiddenActions })
57
60
  ] });
58
61
  };
59
- function BarActions({ children, label, order, sx, inlineSx, bare = false, exclusive = false, texts }) {
62
+ function BarActions(props) {
63
+ const { children, label, order, sx, inlineSx, bare = false, exclusive = false, texts } = usePieceProps(props, THEME_NAME);
60
64
  const { slot, phoneSlot, usesCapsules } = useBarActionsSlot();
61
65
  const isDesktop = useMediaQuery(DESKTOP_MEDIA_QUERY);
62
66
  const target = isDesktop ? slot : phoneSlot;
@@ -65,7 +69,7 @@ function BarActions({ children, label, order, sx, inlineSx, bare = false, exclus
65
69
  const extraInlineSx = Array.isArray(inlineSx) ? inlineSx : [inlineSx];
66
70
  if (!target) {
67
71
  if (bare) {
68
- return /* @__PURE__ */ jsx(Box, { role: "group", "aria-label": label, sx: [{ display: "flex", alignItems: "center" }, ...extraInlineSx], children });
72
+ return /* @__PURE__ */ jsx(ActionsGroup, { role: "group", "aria-label": label, ownSx: { display: "flex", alignItems: "center" }, sx: extraInlineSx, children });
69
73
  }
70
74
  return /* @__PURE__ */ jsx(BarCapsule, { "aria-label": label, sx: [{ alignSelf: "flex-start" }, ...extraInlineSx], children: /* @__PURE__ */ jsx(InCapsule, { children }) });
71
75
  }
@@ -83,16 +87,17 @@ function BarActions({ children, label, order, sx, inlineSx, bare = false, exclus
83
87
  if (usesCapsules) {
84
88
  return /* @__PURE__ */ jsxs(Fragment, { children: [
85
89
  hideOthers,
86
- createPortal(/* @__PURE__ */ jsx(Box, { role: "group", "aria-label": label, sx: [{ display: "flex", alignItems: "center" }, orderSx, ...extraSx], ...exclusiveProps, children }), target)
90
+ createPortal(/* @__PURE__ */ jsx(ActionsGroup, { role: "group", "aria-label": label, ownSx: [{ display: "flex", alignItems: "center" }, orderSx], sx: extraSx, ...exclusiveProps, children }), target)
87
91
  ] });
88
92
  }
89
93
  return createPortal(
90
94
  /* @__PURE__ */ jsx(
91
- Box,
95
+ ActionsGroup,
92
96
  {
93
97
  role: "group",
94
98
  "aria-label": label,
95
- sx: [{ display: "flex", alignItems: "center", gap: 0.5, ...monochromeButtonsSxOf("inherit") }, orderSx, ...extraSx],
99
+ ownSx: [{ display: "flex", alignItems: "center", gap: 0.5, ...monochromeButtonsSxOf("inherit") }, orderSx],
100
+ sx: extraSx,
96
101
  children: /* @__PURE__ */ jsx(InCapsule, { children })
97
102
  }
98
103
  ),
@@ -1 +1 @@
1
- {"version":3,"file":"BarActions.js","sources":["../../src/appShell/BarActions.jsx"],"sourcesContent":["// Las acciones de UNA pantalla en una cápsula, como las barras de herramientas de Apple: la pantalla las pone en su código\n// donde quiera y el marco decide dónde se ven.\n//\n// - Escritorio con la barra en cápsulas (TOP_BAR.capsules): suben a la barra, cada <BarActions> en su cápsula. Dos grupos\n// que no van juntos (buscar; exportar y agregar) son dos <BarActions>, como Apple separa los grupos.\n// - Teléfono con cápsulas: las mismas cápsulas flotan arriba a la derecha y se quedan al bajar, como los botones de iOS 26\n// (en el teléfono no hay barra de arriba: la de pestañas va abajo). Se ven todas las que caben, solo con ícono; las que\n// ya no caben a lo ancho van a un menú «⋯» con su nombre (useFittingActionCount mide el renglón de verdad). Así una\n// pantalla con muchas acciones arriba no rompe el teléfono.\n// - Escritorio con la franja: entran a la franja como botones (con el color de la franja).\n// - Sin lugar (sin AppLayout, la barra fundida al menú, o el teléfono sin cápsulas): se quedan donde la pantalla las puso,\n// también en una cápsula de solo íconos. PageHeading ya las usa para sus `actions`.\n//\n// Se extiende sin tocar el framework: cualquier contenido adentro (lo normal es BarActionButton, que se acomoda solo), varias\n// por pantalla con su `order`, estilos propios con `sx` (la cápsula de arriba o la flotante) e `inlineSx` (la que se queda en\n// la pantalla), y `bare` cuando lo de adentro ya es una cápsula (el buscador de la tabla). Para una cápsula fuera de todo\n// esto: BarCapsule.\n//\n// OJO: escritorio o teléfono se decide con useMediaQuery (el único lugar del marco): hay que mover los botones a otro lugar\n// del árbol y eso no se puede solo con CSS sin pintarlos dos veces (con sus estados por duplicado). Con Next, el primer\n// pintado los deja en el contenido y se mueven a su lugar al hidratar; con Vite no se nota.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {Children, useState} from 'react';\nimport {createPortal} from 'react-dom';\nimport Box from '@mui/material/Box';\nimport GlobalStyles from '@mui/material/GlobalStyles';\nimport IconButton from '@mui/material/IconButton';\nimport Menu from '@mui/material/Menu';\nimport Tooltip from '@mui/material/Tooltip';\nimport useMediaQuery from '@mui/material/useMediaQuery';\nimport MoreHorizRoundedIcon from '@mui/icons-material/MoreHorizRounded';\n\nimport BarCapsule, {monochromeButtonsSxOf} from '@/appShell/BarCapsule.jsx';\nimport {\n BAR_ACTIONS_PLACEMENT, BarActionsMenuCloseContext, BarActionsPlacementContext, useBarActionsSlot,\n} from '@/appShell/barActionsSlot.js';\nimport {DESKTOP_MEDIA_QUERY} from '@/appShell/shellSizes.js';\nimport useFittingActionCount from '@/appShell/useFittingActionCount.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\n\n// la marca de un grupo exclusivo (BarActions exclusive) y la regla que, mientras exista, esconde a los demás grupos del\n// renglón flotante del teléfono (data-phone-bar-actions lo pone AppLayout)\nconst EXCLUSIVE_ATTRIBUTE = 'data-bar-exclusive';\nconst HIDE_NOT_EXCLUSIVE_STYLES = {[`[data-phone-bar-actions] > :not([${EXCLUSIVE_ATTRIBUTE}])`]: {display: 'none !important'}};\n\n/** Lo de adentro sabe que quedó en una cápsula (BarActionButton se vuelve solo ícono). */\nconst InCapsule = ({children}) => (\n <BarActionsPlacementContext.Provider value={BAR_ACTIONS_PLACEMENT.capsule}>{children}</BarActionsPlacementContext.Provider>\n);\n\n/** El «⋯» del teléfono con las acciones que no caben, como renglones de menú con su nombre. */\nconst MoreActionsMenu = ({label, children}) => {\n const [anchorElement, setAnchorElement] = useState(null);\n const close = () => setAnchorElement(null);\n return (\n <>\n <Tooltip title={label}>\n <IconButton aria-label={label} aria-haspopup=\"menu\" aria-expanded={Boolean(anchorElement)}\n onClick={(event) => setAnchorElement(event.currentTarget)}>\n <MoreHorizRoundedIcon />\n </IconButton>\n </Tooltip>\n {/* OJO keepMounted: una acción del «⋯» puede abrir algo suyo al picarla (DownloadMenu abre sus formatos y su\n confirmación); sin él, al cerrarse este menú se desmontaba con todo y lo que abrió */}\n <Menu anchorEl={anchorElement} open={Boolean(anchorElement)} onClose={close} keepMounted\n anchorOrigin={{vertical: 'bottom', horizontal: 'right'}} transformOrigin={{vertical: 'top', horizontal: 'right'}}>\n <BarActionsMenuCloseContext.Provider value={close}>\n <BarActionsPlacementContext.Provider value={BAR_ACTIONS_PLACEMENT.menu}>{children}</BarActionsPlacementContext.Provider>\n </BarActionsMenuCloseContext.Provider>\n </Menu>\n </>\n );\n};\n\n/** La cápsula que flota en el teléfono: las que caben como ícono y, si sobran, el «⋯» con las demás. */\nconst PhoneFloatingCapsule = ({phoneSlot, label, sx, texts, children, ...rest}) => {\n const {t} = useToolkitTranslation('layout', texts);\n const [capsuleElement, setCapsuleElement] = useState(null);\n const actions = Children.toArray(children);\n const visibleCount = useFittingActionCount(phoneSlot, capsuleElement, actions.length);\n const hiddenActions = actions.slice(visibleCount);\n return (\n <BarCapsule ref={setCapsuleElement} aria-label={label} sx={sx} {...rest}>\n <InCapsule>{actions.slice(0, visibleCount)}</InCapsule>\n {hiddenActions.length > 0 && <MoreActionsMenu label={t('barActions.more')}>{hiddenActions}</MoreActionsMenu>}\n </BarCapsule>\n );\n};\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode} props.children los botones de este grupo (normalmente BarActionButton)\n * @param {string} [props.label] el nombre del grupo (lector de pantalla): «Acciones de pedidos»\n * @param {number} [props.order] en qué lugar va entre los grupos de la pantalla (CSS order; por omisión el de aparición)\n * @param {object|Function|Array} [props.sx] estilos propios de la cápsula de arriba o de la flotante del teléfono (o del\n * grupo, en la franja)\n * @param {object|Function|Array} [props.inlineSx] estilos de la cápsula cuando se queda en la pantalla\n * @param {boolean} [props.bare] sin cápsula alrededor: lo de adentro ya es una (un buscador)\n * @param {boolean} [props.exclusive] en el teléfono, mientras se ve, es lo único del renglón flotante (con los demás grupos\n * exclusivos): los otros se esconden, como el modo de edición del iPhone deja solo lo de lo elegido. Lo usa SelectionActions\n * @param {object} [props.texts] los textos que cambian, con la forma de `layout` en los textos del paquete\n */\nexport default function BarActions({children, label, order, sx, inlineSx, bare = false, exclusive = false, texts}) {\n const {slot, phoneSlot, usesCapsules} = useBarActionsSlot();\n const isDesktop = useMediaQuery(DESKTOP_MEDIA_QUERY);\n // en escritorio, la barra; en el teléfono, el renglón flotante (solo existe con cápsulas)\n const target = isDesktop ? slot : phoneSlot;\n const orderSx = order === undefined ? {} : {order};\n const extraSx = Array.isArray(sx) ? sx : [sx];\n const extraInlineSx = Array.isArray(inlineSx) ? inlineSx : [inlineSx];\n\n // sin lugar: donde la pantalla las puso, en su cápsula de íconos\n if (!target) {\n if (bare) {\n return <Box role=\"group\" aria-label={label} sx={[{display: 'flex', alignItems: 'center'}, ...extraInlineSx]}>{children}</Box>;\n }\n return (\n <BarCapsule aria-label={label} sx={[{alignSelf: 'flex-start'}, ...extraInlineSx]}>\n <InCapsule>{children}</InCapsule>\n </BarCapsule>\n );\n }\n // exclusivo en el teléfono: se marca y esconde a los demás grupos del renglón mientras se ve. OJO: sin esto, con algo\n // elegido no cabían el conteo, sus acciones, la lupa y las de la pantalla, y el renglón se salía por los dos lados\n const exclusiveProps = !isDesktop && exclusive ? {[EXCLUSIVE_ATTRIBUTE]: ''} : {};\n const hideOthers = !isDesktop && exclusive && <GlobalStyles styles={HIDE_NOT_EXCLUSIVE_STYLES} />;\n // flotando en el teléfono: las que caben y el «⋯»\n if (!isDesktop && !bare) {\n return (\n <>\n {hideOthers}\n {createPortal(<PhoneFloatingCapsule phoneSlot={phoneSlot} label={label} sx={[orderSx, ...extraSx]} texts={texts} {...exclusiveProps}>{children}</PhoneFloatingCapsule>, target)}\n </>\n );\n }\n // arriba en la barra (o el buscador flotando en el teléfono)\n if (usesCapsules && !bare) {\n return createPortal(<BarCapsule aria-label={label} sx={[orderSx, ...extraSx]}><InCapsule>{children}</InCapsule></BarCapsule>, target);\n }\n if (usesCapsules) {\n return (\n <>\n {hideOthers}\n {createPortal(<Box role=\"group\" aria-label={label} sx={[{display: 'flex', alignItems: 'center'}, orderSx, ...extraSx]} {...exclusiveProps}>{children}</Box>, target)}\n </>\n );\n }\n // en la franja: botones sueltos (solo ícono) con el color de la franja (sobre el naranja de Stackcraft, el color\n // principal no se vería)\n return createPortal(\n <Box role=\"group\" aria-label={label}\n sx={[{display: 'flex', alignItems: 'center', gap: 0.5, ...monochromeButtonsSxOf('inherit')}, orderSx, ...extraSx]}>\n <InCapsule>{children}</InCapsule>\n </Box>,\n target,\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BarActions.js","sources":["../../src/appShell/BarActions.jsx"],"sourcesContent":["// Las acciones de UNA pantalla en una cápsula, como las barras de herramientas de Apple: la pantalla las pone en su código\n// donde quiera y el marco decide dónde se ven.\n//\n// - Escritorio con la barra en cápsulas (TOP_BAR.capsules): suben a la barra, cada <BarActions> en su cápsula. Dos grupos\n// que no van juntos (buscar; exportar y agregar) son dos <BarActions>, como Apple separa los grupos.\n// - Teléfono con cápsulas: las mismas cápsulas flotan arriba a la derecha y se quedan al bajar, como los botones de iOS 26\n// (en el teléfono no hay barra de arriba: la de pestañas va abajo). Se ven todas las que caben, solo con ícono; las que\n// ya no caben a lo ancho van a un menú «⋯» con su nombre (useFittingActionCount mide el renglón de verdad). Así una\n// pantalla con muchas acciones arriba no rompe el teléfono.\n// - Escritorio con la franja: entran a la franja como botones (con el color de la franja).\n// - Sin lugar (sin AppLayout, la barra fundida al menú, o el teléfono sin cápsulas): se quedan donde la pantalla las puso,\n// también en una cápsula de solo íconos. PageHeading ya las usa para sus `actions`.\n//\n// Se extiende sin tocar el framework: cualquier contenido adentro (lo normal es BarActionButton, que se acomoda solo), varias\n// por pantalla con su `order`, estilos propios con `sx` (la cápsula de arriba o la flotante) e `inlineSx` (la que se queda en\n// la pantalla), y `bare` cuando lo de adentro ya es una cápsula (el buscador de la tabla). Para una cápsula fuera de todo\n// esto: BarCapsule.\n//\n// OJO: escritorio o teléfono se decide con useMediaQuery (el único lugar del marco): hay que mover los botones a otro lugar\n// del árbol y eso no se puede solo con CSS sin pintarlos dos veces (con sus estados por duplicado). Con Next, el primer\n// pintado los deja en el contenido y se mueven a su lugar al hidratar; con Vite no se nota.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaBarActions con defaultProps y\n// styleOverrides.group (el grupo sin cápsula); la cápsula, con CalcitaBarCapsule. El sx y el inlineSx de la pantalla siguen\n// ganando a todo.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {Children, useState} from 'react';\nimport {createPortal} from 'react-dom';\nimport Box from '@mui/material/Box';\nimport GlobalStyles from '@mui/material/GlobalStyles';\nimport IconButton from '@mui/material/IconButton';\nimport Menu from '@mui/material/Menu';\nimport Tooltip from '@mui/material/Tooltip';\nimport useMediaQuery from '@mui/material/useMediaQuery';\nimport MoreHorizRoundedIcon from '@mui/icons-material/MoreHorizRounded';\n\nimport BarCapsule, {monochromeButtonsSxOf} from '@/appShell/BarCapsule.jsx';\nimport {\n BAR_ACTIONS_PLACEMENT, BarActionsMenuCloseContext, BarActionsPlacementContext, useBarActionsSlot,\n} from '@/appShell/barActionsSlot.js';\nimport {DESKTOP_MEDIA_QUERY} from '@/appShell/shellSizes.js';\nimport useFittingActionCount from '@/appShell/useFittingActionCount.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaBarActions): el grupo sin cápsula (bare, o en la\n// franja); con cápsula, la cápsula es CalcitaBarCapsule\nconst THEME_NAME = 'CalcitaBarActions';\nconst ActionsGroup = piecePart(THEME_NAME, 'Group', Box);\n\n// la marca de un grupo exclusivo (BarActions exclusive) y la regla que, mientras exista, esconde a los demás grupos del\n// renglón flotante del teléfono (data-phone-bar-actions lo pone AppLayout)\nconst EXCLUSIVE_ATTRIBUTE = 'data-bar-exclusive';\nconst HIDE_NOT_EXCLUSIVE_STYLES = {[`[data-phone-bar-actions] > :not([${EXCLUSIVE_ATTRIBUTE}])`]: {display: 'none !important'}};\n\n/** Lo de adentro sabe que quedó en una cápsula (BarActionButton se vuelve solo ícono). */\nconst InCapsule = ({children}) => (\n <BarActionsPlacementContext.Provider value={BAR_ACTIONS_PLACEMENT.capsule}>{children}</BarActionsPlacementContext.Provider>\n);\n\n/** El «⋯» del teléfono con las acciones que no caben, como renglones de menú con su nombre. */\nconst MoreActionsMenu = ({label, children}) => {\n const [anchorElement, setAnchorElement] = useState(null);\n const close = () => setAnchorElement(null);\n return (\n <>\n <Tooltip title={label}>\n <IconButton aria-label={label} aria-haspopup=\"menu\" aria-expanded={Boolean(anchorElement)}\n onClick={(event) => setAnchorElement(event.currentTarget)}>\n <MoreHorizRoundedIcon />\n </IconButton>\n </Tooltip>\n {/* OJO keepMounted: una acción del «⋯» puede abrir algo suyo al picarla (DownloadMenu abre sus formatos y su\n confirmación); sin él, al cerrarse este menú se desmontaba con todo y lo que abrió */}\n <Menu anchorEl={anchorElement} open={Boolean(anchorElement)} onClose={close} keepMounted\n anchorOrigin={{vertical: 'bottom', horizontal: 'right'}} transformOrigin={{vertical: 'top', horizontal: 'right'}}>\n <BarActionsMenuCloseContext.Provider value={close}>\n <BarActionsPlacementContext.Provider value={BAR_ACTIONS_PLACEMENT.menu}>{children}</BarActionsPlacementContext.Provider>\n </BarActionsMenuCloseContext.Provider>\n </Menu>\n </>\n );\n};\n\n/** La cápsula que flota en el teléfono: las que caben como ícono y, si sobran, el «⋯» con las demás. */\nconst PhoneFloatingCapsule = ({phoneSlot, label, sx, texts, children, ...rest}) => {\n const {t} = useToolkitTranslation('layout', texts);\n const [capsuleElement, setCapsuleElement] = useState(null);\n const actions = Children.toArray(children);\n const visibleCount = useFittingActionCount(phoneSlot, capsuleElement, actions.length);\n const hiddenActions = actions.slice(visibleCount);\n return (\n <BarCapsule ref={setCapsuleElement} aria-label={label} sx={sx} {...rest}>\n <InCapsule>{actions.slice(0, visibleCount)}</InCapsule>\n {hiddenActions.length > 0 && <MoreActionsMenu label={t('barActions.more')}>{hiddenActions}</MoreActionsMenu>}\n </BarCapsule>\n );\n};\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode} props.children los botones de este grupo (normalmente BarActionButton)\n * @param {string} [props.label] el nombre del grupo (lector de pantalla): «Acciones de pedidos»\n * @param {number} [props.order] en qué lugar va entre los grupos de la pantalla (CSS order; por omisión el de aparición)\n * @param {object|Function|Array} [props.sx] estilos propios de la cápsula de arriba o de la flotante del teléfono (o del\n * grupo, en la franja)\n * @param {object|Function|Array} [props.inlineSx] estilos de la cápsula cuando se queda en la pantalla\n * @param {boolean} [props.bare] sin cápsula alrededor: lo de adentro ya es una (un buscador)\n * @param {boolean} [props.exclusive] en el teléfono, mientras se ve, es lo único del renglón flotante (con los demás grupos\n * exclusivos): los otros se esconden, como el modo de edición del iPhone deja solo lo de lo elegido. Lo usa SelectionActions\n * @param {object} [props.texts] los textos que cambian, con la forma de `layout` en los textos del paquete\n */\nexport default function BarActions(props) {\n // lo que el proyecto puso en su tema (components.CalcitaBarActions.defaultProps) y encima lo que llega aquí\n const {children, label, order, sx, inlineSx, bare = false, exclusive = false, texts} = usePieceProps(props, THEME_NAME);\n const {slot, phoneSlot, usesCapsules} = useBarActionsSlot();\n const isDesktop = useMediaQuery(DESKTOP_MEDIA_QUERY);\n // en escritorio, la barra; en el teléfono, el renglón flotante (solo existe con cápsulas)\n const target = isDesktop ? slot : phoneSlot;\n const orderSx = order === undefined ? {} : {order};\n const extraSx = Array.isArray(sx) ? sx : [sx];\n const extraInlineSx = Array.isArray(inlineSx) ? inlineSx : [inlineSx];\n\n // sin lugar: donde la pantalla las puso, en su cápsula de íconos\n if (!target) {\n if (bare) {\n return <ActionsGroup role=\"group\" aria-label={label} ownSx={{display: 'flex', alignItems: 'center'}} sx={extraInlineSx}>{children}</ActionsGroup>;\n }\n return (\n <BarCapsule aria-label={label} sx={[{alignSelf: 'flex-start'}, ...extraInlineSx]}>\n <InCapsule>{children}</InCapsule>\n </BarCapsule>\n );\n }\n // exclusivo en el teléfono: se marca y esconde a los demás grupos del renglón mientras se ve. OJO: sin esto, con algo\n // elegido no cabían el conteo, sus acciones, la lupa y las de la pantalla, y el renglón se salía por los dos lados\n const exclusiveProps = !isDesktop && exclusive ? {[EXCLUSIVE_ATTRIBUTE]: ''} : {};\n const hideOthers = !isDesktop && exclusive && <GlobalStyles styles={HIDE_NOT_EXCLUSIVE_STYLES} />;\n // flotando en el teléfono: las que caben y el «⋯»\n if (!isDesktop && !bare) {\n return (\n <>\n {hideOthers}\n {createPortal(<PhoneFloatingCapsule phoneSlot={phoneSlot} label={label} sx={[orderSx, ...extraSx]} texts={texts} {...exclusiveProps}>{children}</PhoneFloatingCapsule>, target)}\n </>\n );\n }\n // arriba en la barra (o el buscador flotando en el teléfono)\n if (usesCapsules && !bare) {\n return createPortal(<BarCapsule aria-label={label} sx={[orderSx, ...extraSx]}><InCapsule>{children}</InCapsule></BarCapsule>, target);\n }\n if (usesCapsules) {\n return (\n <>\n {hideOthers}\n {createPortal(<ActionsGroup role=\"group\" aria-label={label} ownSx={[{display: 'flex', alignItems: 'center'}, orderSx]} sx={extraSx} {...exclusiveProps}>{children}</ActionsGroup>, target)}\n </>\n );\n }\n // en la franja: botones sueltos (solo ícono) con el color de la franja (sobre el naranja de Stackcraft, el color\n // principal no se vería)\n return createPortal(\n <ActionsGroup role=\"group\" aria-label={label}\n ownSx={[{display: 'flex', alignItems: 'center', gap: 0.5, ...monochromeButtonsSxOf('inherit')}, orderSx]} sx={extraSx}>\n <InCapsule>{children}</InCapsule>\n </ActionsGroup>,\n target,\n );\n}\n"],"names":[],"mappings":"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"}
@@ -3,6 +3,9 @@ import { jsx } from "react/jsx-runtime";
3
3
  import Box from "@mui/material/Box";
4
4
  import { paletteOf } from "../theme/components/paletteOf.js";
5
5
  import { isGlassTheme, glassStylesOf } from "../theme/glassSurface.js";
6
+ import { piecePart, usePieceProps } from "../theme/themePieces.js";
7
+ const THEME_NAME = "CalcitaBarCapsule";
8
+ const CapsuleRoot = piecePart(THEME_NAME, "Root", Box);
6
9
  const BAR_CAPSULE_HEIGHT_PIXELS = 48;
7
10
  function monochromeButtonsSxOf(color) {
8
11
  return {
@@ -20,13 +23,14 @@ function monochromeButtonsSxOf(color) {
20
23
  }
21
24
  };
22
25
  }
23
- function BarCapsule({ children, sx, role = "group", ...rest }) {
26
+ function BarCapsule(props) {
27
+ const { children, sx, role = "group", ...rest } = usePieceProps(props, THEME_NAME);
24
28
  return /* @__PURE__ */ jsx(
25
- Box,
29
+ CapsuleRoot,
26
30
  {
27
31
  role,
28
32
  ...rest,
29
- sx: [(theme) => ({
33
+ ownSx: (theme) => ({
30
34
  ...isGlassTheme(theme) ? glassStylesOf(theme, { isControl: true }) : { backgroundColor: paletteOf(theme).background.paper },
31
35
  ...isGlassTheme(theme) && monochromeButtonsSxOf(paletteOf(theme).text.primary),
32
36
  display: "flex",
@@ -37,7 +41,8 @@ function BarCapsule({ children, sx, role = "group", ...rest }) {
37
41
  height: BAR_CAPSULE_HEIGHT_PIXELS,
38
42
  px: 0.75,
39
43
  borderRadius: "999px"
40
- }), ...Array.isArray(sx) ? sx : [sx]],
44
+ }),
45
+ sx,
41
46
  children
42
47
  }
43
48
  );
@@ -1 +1 @@
1
- {"version":3,"file":"BarCapsule.js","sources":["../../src/appShell/BarCapsule.jsx"],"sourcesContent":["// Una cápsula de la barra de arriba (como las de las ventanas de macOS Tahoe): un grupo de botones juntos, con vidrio si el\n// tema lo trae y, con el minimalista, un bloque del tono de las tarjetas sin borde ni sombra. La usan el marco (la ☰ con el\n// nombre, la cuenta), las acciones de cada pantalla (BarActions) y el proyecto para algo suyo que deba verse igual (unos\n// botones encima de un mapa, una barra de herramientas propia).\n//\n// Con vidrio, los botones de adentro van SIEMPRE del color del texto y sin relleno, borde ni sombra, aunque quien los usa\n// les ponga color o variante (color=\"primary\", variant=\"contained\" u \"outlined\", un sx propio): en las barras de Apple los\n// símbolos son de un solo color y el color queda para el contenido (HIG Toolbars y Color). Lo pidió el autor. OJO: al\n// principio solo se quitó el color del texto y un «Redactar» con relleno seguía naranja en la barra (lo cachó el autor). Se\n// logra con selectores de más clases que las del botón; los deshabilitados se quedan con su gris. Con el minimalista\n// conservan su color.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Box from '@mui/material/Box';\n\nimport {paletteOf} from '@/theme/components/paletteOf.js';\nimport {glassStylesOf, isGlassTheme} from '@/theme/glassSurface.js';\n\n// lo alto de una cápsula (px): cabe en el alto de siempre de la barra con aire arriba y abajo\nexport const BAR_CAPSULE_HEIGHT_PIXELS = 48;\n\n/**\n * Los botones de adentro de un solo color y sin relleno, borde ni sombra (la regla de la barra con vidrio). La usan también\n * la franja (BarActions) y lo que se ponga junto a la barra.\n *\n * @param {string} color el del texto de la barra ('inherit' en la franja)\n * @returns {object} estilos para el sx del contenedor\n */\nexport function monochromeButtonsSxOf(color) {\n return {\n '& .MuiIconButton-root:not(.Mui-disabled), & .MuiButton-root:not(.Mui-disabled)': {color},\n // un botón con relleno o con borde se queda como uno de texto: sin fondo, sin borde y sin sombra, también al pasar el\n // cursor (ahí lleva el velo de cualquier botón de texto). OJO: la barra es un Paper y el tema tiñe los botones con\n // borde «dentro de una tarjeta» con body[data-glass-lens] .MuiPaper-root … (cuatro clases y un elemento): por eso\n // .MuiButton-root va repetido, para pesar cinco clases (con menos, «Restablecer» seguía teñido; medido en Chrome)\n '& .MuiButton-root.MuiButton-root.MuiButton-root.MuiButton-contained, & .MuiButton-root.MuiButton-root.MuiButton-root.MuiButton-outlined': {\n backgroundColor: 'transparent', backgroundImage: 'none', boxShadow: 'none', border: 0,\n '&:hover': {backgroundColor: 'action.hover', boxShadow: 'none'},\n },\n };\n}\n\n/**\n * Lo demás va al div de la cápsula: aria-label (el nombre del grupo para quien usa lector de pantalla), id, onClick…\n * role va por omisión en 'group' (lo que se agrupa se anuncia junto).\n *\n * @param {Omit<import('react').HTMLAttributes<HTMLDivElement>, 'children'> & {children: import('react').ReactNode, sx?: object|Function|Array<any>}} props\n * children: los botones del grupo; sx: estilos propios, encima de los de la cápsula\n */\nexport default function BarCapsule({children, sx, role = 'group', ...rest}) {\n return (\n <Box role={role} {...rest}\n sx={[(theme) => ({\n ...(isGlassTheme(theme) ? glassStylesOf(theme, {isControl: true}) : {backgroundColor: paletteOf(theme).background.paper}),\n ...(isGlassTheme(theme) && monochromeButtonsSxOf(paletteOf(theme).text.primary)),\n display: 'flex', alignItems: 'center', gap: 0.5, flexShrink: 0, minWidth: 0,\n height: BAR_CAPSULE_HEIGHT_PIXELS, px: 0.75, borderRadius: '999px',\n }), ...(Array.isArray(sx) ? sx : [sx])]}>\n {children}\n </Box>\n );\n}\n"],"names":[],"mappings":";;;;;AAmBO,MAAM,4BAA4B;AASlC,SAAS,sBAAsB,OAAO;AACzC,SAAO;AAAA,IACH,kFAAkF,EAAC,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAKnF,2IAA2I;AAAA,MACvI,iBAAiB;AAAA,MAAe,iBAAiB;AAAA,MAAQ,WAAW;AAAA,MAAQ,QAAQ;AAAA,MACpF,WAAW,EAAC,iBAAiB,gBAAgB,WAAW,OAAA;AAAA,IAAM;AAAA,EAClE;AAER;AASA,SAAwB,WAAW,EAAC,UAAU,IAAI,OAAO,SAAS,GAAG,QAAO;AACxE,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MAAI;AAAA,MAAa,GAAG;AAAA,MAChB,IAAI,CAAC,CAAC,WAAW;AAAA,QACb,GAAI,aAAa,KAAK,IAAI,cAAc,OAAO,EAAC,WAAW,KAAA,CAAK,IAAI,EAAC,iBAAiB,UAAU,KAAK,EAAE,WAAW,MAAA;AAAA,QAClH,GAAI,aAAa,KAAK,KAAK,sBAAsB,UAAU,KAAK,EAAE,KAAK,OAAO;AAAA,QAC9E,SAAS;AAAA,QAAQ,YAAY;AAAA,QAAU,KAAK;AAAA,QAAK,YAAY;AAAA,QAAG,UAAU;AAAA,QAC1E,QAAQ;AAAA,QAA2B,IAAI;AAAA,QAAM,cAAc;AAAA,MAAA,IAC3D,GAAI,MAAM,QAAQ,EAAE,IAAI,KAAK,CAAC,EAAE,CAAE;AAAA,MACtC;AAAA,IAAA;AAAA,EAAA;AAGb;"}
1
+ {"version":3,"file":"BarCapsule.js","sources":["../../src/appShell/BarCapsule.jsx"],"sourcesContent":["// Una cápsula de la barra de arriba (como las de las ventanas de macOS Tahoe): un grupo de botones juntos, con vidrio si el\n// tema lo trae y, con el minimalista, un bloque del tono de las tarjetas sin borde ni sombra. La usan el marco (la ☰ con el\n// nombre, la cuenta), las acciones de cada pantalla (BarActions) y el proyecto para algo suyo que deba verse igual (unos\n// botones encima de un mapa, una barra de herramientas propia).\n//\n// Con vidrio, los botones de adentro van SIEMPRE del color del texto y sin relleno, borde ni sombra, aunque quien los usa\n// les ponga color o variante (color=\"primary\", variant=\"contained\" u \"outlined\", un sx propio): en las barras de Apple los\n// símbolos son de un solo color y el color queda para el contenido (HIG Toolbars y Color). Lo pidió el autor. OJO: al\n// principio solo se quitó el color del texto y un «Redactar» con relleno seguía naranja en la barra (lo cachó el autor). Se\n// logra con selectores de más clases que las del botón; los deshabilitados se quedan con su gris. Con el minimalista\n// conservan su color.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaBarCapsule con defaultProps y\n// styleOverrides.root (el sx de la pantalla sigue ganando a todo).\n//\n// Genérico del paquete: function (regla de la casa).\nimport Box from '@mui/material/Box';\n\nimport {paletteOf} from '@/theme/components/paletteOf.js';\nimport {glassStylesOf, isGlassTheme} from '@/theme/glassSurface.js';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y su parte (theme.components.CalcitaBarCapsule)\nconst THEME_NAME = 'CalcitaBarCapsule';\nconst CapsuleRoot = piecePart(THEME_NAME, 'Root', Box);\n\n// lo alto de una cápsula (px): cabe en el alto de siempre de la barra con aire arriba y abajo\nexport const BAR_CAPSULE_HEIGHT_PIXELS = 48;\n\n/**\n * Los botones de adentro de un solo color y sin relleno, borde ni sombra (la regla de la barra con vidrio). La usan también\n * la franja (BarActions) y lo que se ponga junto a la barra.\n *\n * @param {string} color el del texto de la barra ('inherit' en la franja)\n * @returns {object} estilos para el sx del contenedor\n */\nexport function monochromeButtonsSxOf(color) {\n return {\n '& .MuiIconButton-root:not(.Mui-disabled), & .MuiButton-root:not(.Mui-disabled)': {color},\n // un botón con relleno o con borde se queda como uno de texto: sin fondo, sin borde y sin sombra, también al pasar el\n // cursor (ahí lleva el velo de cualquier botón de texto). OJO: la barra es un Paper y el tema tiñe los botones con\n // borde «dentro de una tarjeta» con body[data-glass-lens] .MuiPaper-root … (cuatro clases y un elemento): por eso\n // .MuiButton-root va repetido, para pesar cinco clases (con menos, «Restablecer» seguía teñido; medido en Chrome)\n '& .MuiButton-root.MuiButton-root.MuiButton-root.MuiButton-contained, & .MuiButton-root.MuiButton-root.MuiButton-root.MuiButton-outlined': {\n backgroundColor: 'transparent', backgroundImage: 'none', boxShadow: 'none', border: 0,\n '&:hover': {backgroundColor: 'action.hover', boxShadow: 'none'},\n },\n };\n}\n\n/**\n * Lo demás va al div de la cápsula: aria-label (el nombre del grupo para quien usa lector de pantalla), id, onClick…\n * role va por omisión en 'group' (lo que se agrupa se anuncia junto).\n *\n * @param {Omit<import('react').HTMLAttributes<HTMLDivElement>, 'children'> & {children: import('react').ReactNode, sx?: object|Function|Array<any>}} props\n * children: los botones del grupo; sx: estilos propios, encima de los de la cápsula\n */\nexport default function BarCapsule(props) {\n // lo que el proyecto puso en su tema (components.CalcitaBarCapsule.defaultProps) y encima lo que llega aquí\n const {children, sx, role = 'group', ...rest} = usePieceProps(props, THEME_NAME);\n // el estilo de la cápsula va abajo (ownSx): encima el del tema del proyecto y, al final, el sx de la pantalla\n return (\n <CapsuleRoot role={role} {...rest}\n ownSx={(theme) => ({\n ...(isGlassTheme(theme) ? glassStylesOf(theme, {isControl: true}) : {backgroundColor: paletteOf(theme).background.paper}),\n ...(isGlassTheme(theme) && monochromeButtonsSxOf(paletteOf(theme).text.primary)),\n display: 'flex', alignItems: 'center', gap: 0.5, flexShrink: 0, minWidth: 0,\n height: BAR_CAPSULE_HEIGHT_PIXELS, px: 0.75, borderRadius: '999px',\n })}\n sx={sx}>\n {children}\n </CapsuleRoot>\n );\n}\n"],"names":[],"mappings":";;;;;;AAuBA,MAAM,aAAa;AACnB,MAAM,cAAc,UAAU,YAAY,QAAQ,GAAG;AAG9C,MAAM,4BAA4B;AASlC,SAAS,sBAAsB,OAAO;AACzC,SAAO;AAAA,IACH,kFAAkF,EAAC,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAKnF,2IAA2I;AAAA,MACvI,iBAAiB;AAAA,MAAe,iBAAiB;AAAA,MAAQ,WAAW;AAAA,MAAQ,QAAQ;AAAA,MACpF,WAAW,EAAC,iBAAiB,gBAAgB,WAAW,OAAA;AAAA,IAAM;AAAA,EAClE;AAER;AASA,SAAwB,WAAW,OAAO;AAEtC,QAAM,EAAC,UAAU,IAAI,OAAO,SAAS,GAAG,SAAQ,cAAc,OAAO,UAAU;AAE/E,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MAAY;AAAA,MAAa,GAAG;AAAA,MACxB,OAAO,CAAC,WAAW;AAAA,QACf,GAAI,aAAa,KAAK,IAAI,cAAc,OAAO,EAAC,WAAW,KAAA,CAAK,IAAI,EAAC,iBAAiB,UAAU,KAAK,EAAE,WAAW,MAAA;AAAA,QAClH,GAAI,aAAa,KAAK,KAAK,sBAAsB,UAAU,KAAK,EAAE,KAAK,OAAO;AAAA,QAC9E,SAAS;AAAA,QAAQ,YAAY;AAAA,QAAU,KAAK;AAAA,QAAK,YAAY;AAAA,QAAG,UAAU;AAAA,QAC1E,QAAQ;AAAA,QAA2B,IAAI;AAAA,QAAM,cAAc;AAAA,MAAA;AAAA,MAE/D;AAAA,MACA;AAAA,IAAA;AAAA,EAAA;AAGb;"}
@@ -7,13 +7,17 @@ import SearchIcon from "@mui/icons-material/Search";
7
7
  import BarActions from "./BarActions.js";
8
8
  import { BAR_CAPSULE_HEIGHT_PIXELS } from "./BarCapsule.js";
9
9
  import { PHONE_MEDIA_QUERY } from "./shellSizes.js";
10
+ import { piecePart, usePieceProps } from "../theme/themePieces.js";
11
+ const THEME_NAME = "CalcitaBarSearch";
12
+ const SearchField = piecePart(THEME_NAME, "Field", TextField);
10
13
  const SEARCH_BOX_MIN_WIDTH_PIXELS = 400;
11
14
  const SEARCH_IN_BAR_WIDTH_PIXELS = 380;
12
- function BarSearch({ value, onChange, placeholder, inBar = true, collapsible = true, order = 0, onFocus, onBlur, inputRef }) {
15
+ function BarSearch(props) {
16
+ const { value, onChange, placeholder, inBar = true, collapsible = true, order = 0, onFocus, onBlur, inputRef } = usePieceProps(props, THEME_NAME);
13
17
  const [isFocused, setIsFocused] = useState(false);
14
18
  const isCompact = inBar && collapsible && !isFocused && !value;
15
19
  const searchBox = /* @__PURE__ */ jsx(
16
- TextField,
20
+ SearchField,
17
21
  {
18
22
  type: "search",
19
23
  size: "small",
@@ -35,7 +39,7 @@ function BarSearch({ value, onChange, placeholder, inBar = true, collapsible = t
35
39
  }
36
40
  },
37
41
  placeholder,
38
- sx: {
42
+ ownSx: {
39
43
  minWidth: { xs: 0, md: inBar ? 0 : SEARCH_BOX_MIN_WIDTH_PIXELS },
40
44
  // la × del navegador para type="search" no va: la caja se borra con Escape
41
45
  '& input[type="search"]::-webkit-search-cancel-button': { WebkitAppearance: "none", display: "none" }
@@ -1 +1 @@
1
- {"version":3,"file":"BarSearch.js","sources":["../../src/appShell/BarSearch.jsx"],"sourcesContent":["// Una caja de búsqueda que sube a la barra de la app, como el buscador de las ventanas de macOS: sin usar se encoge a la\n// lupa, al picarla (o llegar con Tab) se estira, y con texto se queda abierta. En el teléfono con cápsulas flota arriba con\n// las demás; sin barra en cápsulas se queda donde la pantalla la puso. Escape borra lo escrito y la suelta.\n//\n// <BarSearch value={query} onChange={setQuery} placeholder=\"Buscar por título o etiqueta\" />\n//\n// La usan la tabla de servidor (searchInBar) y cualquier pantalla que busque en lo suyo (Tareas). Con inBar={false} es la\n// misma caja dentro de la pantalla.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport InputAdornment from '@mui/material/InputAdornment';\nimport TextField from '@mui/material/TextField';\nimport SearchIcon from '@mui/icons-material/Search';\n\nimport BarActions from '@/appShell/BarActions.jsx';\nimport {BAR_CAPSULE_HEIGHT_PIXELS} from '@/appShell/BarCapsule.jsx';\nimport {PHONE_MEDIA_QUERY} from '@/appShell/shellSizes.js';\n\n// ancho de la caja dentro de la pantalla en escritorio: cabe un texto de ayuda como «Buscar por pedido, cliente o producto…».\n// OJO: con 280 se cortaba («…cliente o pro»); en el teléfono la caja toma todo el ancho\nconst SEARCH_BOX_MIN_WIDTH_PIXELS = 400;\n// en la barra un poco más angosta: comparte el renglón con el título y las cápsulas\nconst SEARCH_IN_BAR_WIDTH_PIXELS = 380;\n\n/**\n * @param {object} props\n * @param {string} props.value lo escrito\n * @param {(value: string) => void} props.onChange recibe el texto, no el evento\n * @param {string} props.placeholder ya traducido: qué se busca («Buscar por título o etiqueta»); también es su nombre para el\n * lector de pantalla\n * @param {boolean} [props.inBar] en la barra de la app (por omisión) o dentro de la pantalla\n * @param {boolean} [props.collapsible] en la barra, sin usar se encoge a la lupa; por omisión sí (false: siempre abierta)\n * @param {number} [props.order] en qué lugar va entre las cápsulas de la barra (por omisión la primera)\n * @param {() => void} [props.onFocus]\n * @param {() => void} [props.onBlur]\n * @param {import('react').Ref<HTMLInputElement>} [props.inputRef] la caja, para enfocarla desde afuera (un atajo «/»)\n */\nexport default function BarSearch({value, onChange, placeholder, inBar = true, collapsible = true, order = 0, onFocus, onBlur, inputRef}) {\n const [isFocused, setIsFocused] = useState(false);\n // en la barra, chica cuando no se usa: ni tiene el foco ni tiene texto\n const isCompact = inBar && collapsible && !isFocused && !value;\n const searchBox = (\n <TextField\n type=\"search\"\n size=\"small\"\n inputRef={inputRef}\n value={value}\n onChange={(event) => onChange(event.target.value)}\n onFocus={() => {\n setIsFocused(true);\n onFocus?.();\n }}\n onBlur={() => {\n setIsFocused(false);\n onBlur?.();\n }}\n // Escape borra lo escrito y suelta la caja (en la barra, regresa a la lupa)\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n onChange('');\n event.currentTarget.querySelector('input')?.blur();\n }\n }}\n placeholder={placeholder}\n sx={{\n minWidth: {xs: 0, md: inBar ? 0 : SEARCH_BOX_MIN_WIDTH_PIXELS},\n // la × del navegador para type=\"search\" no va: la caja se borra con Escape\n '& input[type=\"search\"]::-webkit-search-cancel-button': {WebkitAppearance: 'none', display: 'none'},\n }}\n slotProps={{\n input: {startAdornment: <InputAdornment position=\"start\"><SearchIcon fontSize=\"small\" /></InputAdornment>},\n htmlInput: {'aria-label': placeholder},\n }}\n />\n );\n\n if (!inBar) {\n return searchBox;\n }\n\n // en la barra: la caja ya es su propia cápsula (bare), del alto y la forma de las demás y más angosta.\n // OJO: la barra es un Paper y el tema le pone al campo el radio de «campo dentro de tarjeta», con el lente\n // (body[data-glass-lens] .MuiPaper-root …) aún más específica: por eso las tres clases (con menos salía con esquinas de\n // 12 px y no en cápsula; medido en Chrome). La lupa no atrapa el clic: lo deja pasar a la caja, que es la que se enfoca\n return (\n <BarActions label={placeholder} bare order={order}\n sx={(theme) => ({\n // en el teléfono flota arriba junto a las demás cápsulas. Su lugar SIEMPRE ocupa lo libre del renglón y\n // la caja va pegada a la derecha: así se abre de derecha a izquierda y regresa igual (el ancho pasa de 48 px\n // a 100 % con transición). OJO: antes el lugar brincaba de golpe (flex-grow no se anima) y la caja crecía\n // de izquierda a derecha. El hueco de la izquierda deja pasar el dedo a lo de abajo; solo la caja lo recibe\n [PHONE_MEDIA_QUERY]: {\n flexGrow: 1, minWidth: 0, justifyContent: 'flex-end', pointerEvents: 'none',\n '& .MuiTextField-root': {pointerEvents: 'auto'},\n },\n '& .MuiTextField-root': {\n width: isCompact ? BAR_CAPSULE_HEIGHT_PIXELS : SEARCH_IN_BAR_WIDTH_PIXELS,\n minWidth: 0,\n transition: theme.transitions.create('width', {duration: theme.transitions.duration.short}),\n '@media (prefers-reduced-motion: reduce)': {transition: 'none'},\n [PHONE_MEDIA_QUERY]: {width: isCompact ? BAR_CAPSULE_HEIGHT_PIXELS : '100%'},\n },\n '& .MuiFormControl-root .MuiInputBase-root.MuiOutlinedInput-root': {\n height: BAR_CAPSULE_HEIGHT_PIXELS, borderRadius: '999px', cursor: isCompact ? 'pointer' : 'text',\n },\n '& .MuiInputAdornment-root': {pointerEvents: 'none'},\n '& input::placeholder': {opacity: isCompact ? 0 : undefined},\n })}>\n {searchBox}\n </BarActions>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;AAqBA,MAAM,8BAA8B;AAEpC,MAAM,6BAA6B;AAenC,SAAwB,UAAU,EAAC,OAAO,UAAU,aAAa,QAAQ,MAAM,cAAc,MAAM,QAAQ,GAAG,SAAS,QAAQ,YAAW;AACtI,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAEhD,QAAM,YAAY,SAAS,eAAe,CAAC,aAAa,CAAC;AACzD,QAAM,YACF;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,MAAK;AAAA,MACL,MAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAU,CAAC,UAAU,SAAS,MAAM,OAAO,KAAK;AAAA,MAChD,SAAS,MAAM;AACX,qBAAa,IAAI;AACjB,kBAAA;AAAA,MACJ;AAAA,MACA,QAAQ,MAAM;AACV,qBAAa,KAAK;AAClB,iBAAA;AAAA,MACJ;AAAA,MAEA,WAAW,CAAC,UAAU;AAClB,YAAI,MAAM,QAAQ,UAAU;AACxB,mBAAS,EAAE;AACX,gBAAM,cAAc,cAAc,OAAO,GAAG,KAAA;AAAA,QAChD;AAAA,MACJ;AAAA,MACA;AAAA,MACA,IAAI;AAAA,QACA,UAAU,EAAC,IAAI,GAAG,IAAI,QAAQ,IAAI,4BAAA;AAAA;AAAA,QAElC,wDAAwD,EAAC,kBAAkB,QAAQ,SAAS,OAAA;AAAA,MAAM;AAAA,MAEtG,WAAW;AAAA,QACP,OAAO,EAAC,gBAAgB,oBAAC,gBAAA,EAAe,UAAS,SAAQ,UAAA,oBAAC,YAAA,EAAW,UAAS,QAAA,CAAQ,EAAA,CAAE,EAAA;AAAA,QACxF,WAAW,EAAC,cAAc,YAAA;AAAA,MAAW;AAAA,IACzC;AAAA,EAAA;AAIR,MAAI,CAAC,OAAO;AACR,WAAO;AAAA,EACX;AAMA,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MAAW,OAAO;AAAA,MAAa,MAAI;AAAA,MAAC;AAAA,MACzB,IAAI,CAAC,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,QAKZ,CAAC,iBAAiB,GAAG;AAAA,UACjB,UAAU;AAAA,UAAG,UAAU;AAAA,UAAG,gBAAgB;AAAA,UAAY,eAAe;AAAA,UACrE,wBAAwB,EAAC,eAAe,OAAA;AAAA,QAAM;AAAA,QAElD,wBAAwB;AAAA,UACpB,OAAO,YAAY,4BAA4B;AAAA,UAC/C,UAAU;AAAA,UACV,YAAY,MAAM,YAAY,OAAO,SAAS,EAAC,UAAU,MAAM,YAAY,SAAS,MAAA,CAAM;AAAA,UAC1F,2CAA2C,EAAC,YAAY,OAAA;AAAA,UACxD,CAAC,iBAAiB,GAAG,EAAC,OAAO,YAAY,4BAA4B,OAAA;AAAA,QAAM;AAAA,QAE/E,mEAAmE;AAAA,UAC/D,QAAQ;AAAA,UAA2B,cAAc;AAAA,UAAS,QAAQ,YAAY,YAAY;AAAA,QAAA;AAAA,QAE9F,6BAA6B,EAAC,eAAe,OAAA;AAAA,QAC7C,wBAAwB,EAAC,SAAS,YAAY,IAAI,OAAA;AAAA,MAAS;AAAA,MAEtE,UAAA;AAAA,IAAA;AAAA,EAAA;AAGb;"}
1
+ {"version":3,"file":"BarSearch.js","sources":["../../src/appShell/BarSearch.jsx"],"sourcesContent":["// Una caja de búsqueda que sube a la barra de la app, como el buscador de las ventanas de macOS: sin usar se encoge a la\n// lupa, al picarla (o llegar con Tab) se estira, y con texto se queda abierta. En el teléfono con cápsulas flota arriba con\n// las demás; sin barra en cápsulas se queda donde la pantalla la puso. Escape borra lo escrito y la suelta.\n//\n// <BarSearch value={query} onChange={setQuery} placeholder=\"Buscar por título o etiqueta\" />\n//\n// La usan la tabla de servidor (searchInBar) y cualquier pantalla que busque en lo suyo (Tareas). Con inBar={false} es la\n// misma caja dentro de la pantalla.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaBarSearch con defaultProps y\n// styleOverrides de sus partes: field.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport InputAdornment from '@mui/material/InputAdornment';\nimport TextField from '@mui/material/TextField';\nimport SearchIcon from '@mui/icons-material/Search';\n\nimport BarActions from '@/appShell/BarActions.jsx';\nimport {BAR_CAPSULE_HEIGHT_PIXELS} from '@/appShell/BarCapsule.jsx';\nimport {PHONE_MEDIA_QUERY} from '@/appShell/shellSizes.js';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaBarSearch)\nconst THEME_NAME = 'CalcitaBarSearch';\nconst SearchField = piecePart(THEME_NAME, 'Field', TextField);\n\n// ancho de la caja dentro de la pantalla en escritorio: cabe un texto de ayuda como «Buscar por pedido, cliente o producto…».\n// OJO: con 280 se cortaba («…cliente o pro»); en el teléfono la caja toma todo el ancho\nconst SEARCH_BOX_MIN_WIDTH_PIXELS = 400;\n// en la barra un poco más angosta: comparte el renglón con el título y las cápsulas\nconst SEARCH_IN_BAR_WIDTH_PIXELS = 380;\n\n/**\n * @param {object} props\n * @param {string} props.value lo escrito\n * @param {(value: string) => void} props.onChange recibe el texto, no el evento\n * @param {string} props.placeholder ya traducido: qué se busca («Buscar por título o etiqueta»); también es su nombre para el\n * lector de pantalla\n * @param {boolean} [props.inBar] en la barra de la app (por omisión) o dentro de la pantalla\n * @param {boolean} [props.collapsible] en la barra, sin usar se encoge a la lupa; por omisión sí (false: siempre abierta)\n * @param {number} [props.order] en qué lugar va entre las cápsulas de la barra (por omisión la primera)\n * @param {() => void} [props.onFocus]\n * @param {() => void} [props.onBlur]\n * @param {import('react').Ref<HTMLInputElement>} [props.inputRef] la caja, para enfocarla desde afuera (un atajo «/»)\n */\nexport default function BarSearch(props) {\n // lo que el proyecto puso en su tema (components.CalcitaBarSearch.defaultProps) y encima lo que llega aquí\n const {value, onChange, placeholder, inBar = true, collapsible = true, order = 0, onFocus, onBlur, inputRef} = usePieceProps(props, THEME_NAME);\n const [isFocused, setIsFocused] = useState(false);\n // en la barra, chica cuando no se usa: ni tiene el foco ni tiene texto\n const isCompact = inBar && collapsible && !isFocused && !value;\n const searchBox = (\n <SearchField\n type=\"search\"\n size=\"small\"\n inputRef={inputRef}\n value={value}\n onChange={(event) => onChange(event.target.value)}\n onFocus={() => {\n setIsFocused(true);\n onFocus?.();\n }}\n onBlur={() => {\n setIsFocused(false);\n onBlur?.();\n }}\n // Escape borra lo escrito y suelta la caja (en la barra, regresa a la lupa)\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n onChange('');\n event.currentTarget.querySelector('input')?.blur();\n }\n }}\n placeholder={placeholder}\n ownSx={{\n minWidth: {xs: 0, md: inBar ? 0 : SEARCH_BOX_MIN_WIDTH_PIXELS},\n // la × del navegador para type=\"search\" no va: la caja se borra con Escape\n '& input[type=\"search\"]::-webkit-search-cancel-button': {WebkitAppearance: 'none', display: 'none'},\n }}\n slotProps={{\n input: {startAdornment: <InputAdornment position=\"start\"><SearchIcon fontSize=\"small\" /></InputAdornment>},\n htmlInput: {'aria-label': placeholder},\n }}\n />\n );\n\n if (!inBar) {\n return searchBox;\n }\n\n // en la barra: la caja ya es su propia cápsula (bare), del alto y la forma de las demás y más angosta.\n // OJO: la barra es un Paper y el tema le pone al campo el radio de «campo dentro de tarjeta», con el lente\n // (body[data-glass-lens] .MuiPaper-root …) aún más específica: por eso las tres clases (con menos salía con esquinas de\n // 12 px y no en cápsula; medido en Chrome). La lupa no atrapa el clic: lo deja pasar a la caja, que es la que se enfoca\n return (\n <BarActions label={placeholder} bare order={order}\n sx={(theme) => ({\n // en el teléfono flota arriba junto a las demás cápsulas. Su lugar SIEMPRE ocupa lo libre del renglón y\n // la caja va pegada a la derecha: así se abre de derecha a izquierda y regresa igual (el ancho pasa de 48 px\n // a 100 % con transición). OJO: antes el lugar brincaba de golpe (flex-grow no se anima) y la caja crecía\n // de izquierda a derecha. El hueco de la izquierda deja pasar el dedo a lo de abajo; solo la caja lo recibe\n [PHONE_MEDIA_QUERY]: {\n flexGrow: 1, minWidth: 0, justifyContent: 'flex-end', pointerEvents: 'none',\n '& .MuiTextField-root': {pointerEvents: 'auto'},\n },\n '& .MuiTextField-root': {\n width: isCompact ? BAR_CAPSULE_HEIGHT_PIXELS : SEARCH_IN_BAR_WIDTH_PIXELS,\n minWidth: 0,\n transition: theme.transitions.create('width', {duration: theme.transitions.duration.short}),\n '@media (prefers-reduced-motion: reduce)': {transition: 'none'},\n [PHONE_MEDIA_QUERY]: {width: isCompact ? BAR_CAPSULE_HEIGHT_PIXELS : '100%'},\n },\n '& .MuiFormControl-root .MuiInputBase-root.MuiOutlinedInput-root': {\n height: BAR_CAPSULE_HEIGHT_PIXELS, borderRadius: '999px', cursor: isCompact ? 'pointer' : 'text',\n },\n '& .MuiInputAdornment-root': {pointerEvents: 'none'},\n '& input::placeholder': {opacity: isCompact ? 0 : undefined},\n })}>\n {searchBox}\n </BarActions>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;AAwBA,MAAM,aAAa;AACnB,MAAM,cAAc,UAAU,YAAY,SAAS,SAAS;AAI5D,MAAM,8BAA8B;AAEpC,MAAM,6BAA6B;AAenC,SAAwB,UAAU,OAAO;AAErC,QAAM,EAAC,OAAO,UAAU,aAAa,QAAQ,MAAM,cAAc,MAAM,QAAQ,GAAG,SAAS,QAAQ,SAAA,IAAY,cAAc,OAAO,UAAU;AAC9I,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAEhD,QAAM,YAAY,SAAS,eAAe,CAAC,aAAa,CAAC;AACzD,QAAM,YACF;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,MAAK;AAAA,MACL,MAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAU,CAAC,UAAU,SAAS,MAAM,OAAO,KAAK;AAAA,MAChD,SAAS,MAAM;AACX,qBAAa,IAAI;AACjB,kBAAA;AAAA,MACJ;AAAA,MACA,QAAQ,MAAM;AACV,qBAAa,KAAK;AAClB,iBAAA;AAAA,MACJ;AAAA,MAEA,WAAW,CAAC,UAAU;AAClB,YAAI,MAAM,QAAQ,UAAU;AACxB,mBAAS,EAAE;AACX,gBAAM,cAAc,cAAc,OAAO,GAAG,KAAA;AAAA,QAChD;AAAA,MACJ;AAAA,MACA;AAAA,MACA,OAAO;AAAA,QACH,UAAU,EAAC,IAAI,GAAG,IAAI,QAAQ,IAAI,4BAAA;AAAA;AAAA,QAElC,wDAAwD,EAAC,kBAAkB,QAAQ,SAAS,OAAA;AAAA,MAAM;AAAA,MAEtG,WAAW;AAAA,QACP,OAAO,EAAC,gBAAgB,oBAAC,gBAAA,EAAe,UAAS,SAAQ,UAAA,oBAAC,YAAA,EAAW,UAAS,QAAA,CAAQ,EAAA,CAAE,EAAA;AAAA,QACxF,WAAW,EAAC,cAAc,YAAA;AAAA,MAAW;AAAA,IACzC;AAAA,EAAA;AAIR,MAAI,CAAC,OAAO;AACR,WAAO;AAAA,EACX;AAMA,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MAAW,OAAO;AAAA,MAAa,MAAI;AAAA,MAAC;AAAA,MACzB,IAAI,CAAC,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,QAKZ,CAAC,iBAAiB,GAAG;AAAA,UACjB,UAAU;AAAA,UAAG,UAAU;AAAA,UAAG,gBAAgB;AAAA,UAAY,eAAe;AAAA,UACrE,wBAAwB,EAAC,eAAe,OAAA;AAAA,QAAM;AAAA,QAElD,wBAAwB;AAAA,UACpB,OAAO,YAAY,4BAA4B;AAAA,UAC/C,UAAU;AAAA,UACV,YAAY,MAAM,YAAY,OAAO,SAAS,EAAC,UAAU,MAAM,YAAY,SAAS,MAAA,CAAM;AAAA,UAC1F,2CAA2C,EAAC,YAAY,OAAA;AAAA,UACxD,CAAC,iBAAiB,GAAG,EAAC,OAAO,YAAY,4BAA4B,OAAA;AAAA,QAAM;AAAA,QAE/E,mEAAmE;AAAA,UAC/D,QAAQ;AAAA,UAA2B,cAAc;AAAA,UAAS,QAAQ,YAAY,YAAY;AAAA,QAAA;AAAA,QAE9F,6BAA6B,EAAC,eAAe,OAAA;AAAA,QAC7C,wBAAwB,EAAC,SAAS,YAAY,IAAI,OAAA;AAAA,MAAS;AAAA,MAEtE,UAAA;AAAA,IAAA;AAAA,EAAA;AAGb;"}
@@ -5,26 +5,31 @@ import Divider from "@mui/material/Divider";
5
5
  import AccountMenu from "./AccountMenu.js";
6
6
  import SettingsMenu from "./SettingsMenu.js";
7
7
  import AppearanceSettings from "./AppearanceSettings.js";
8
- function HeaderTools({
9
- headerActions,
10
- showFontSizeToggle,
11
- showLanguageToggle,
12
- showColorSchemeToggle,
13
- user,
14
- profilePath,
15
- accountMenuItems,
16
- onSignOut,
17
- isSigningOut,
18
- accountSettings,
19
- vertical = false
20
- }) {
8
+ import { piecePart, usePieceProps } from "../theme/themePieces.js";
9
+ const THEME_NAME = "CalcitaHeaderTools";
10
+ const ToolsDivider = piecePart(THEME_NAME, "Divider", Divider);
11
+ const ToolsRoot = piecePart(THEME_NAME, "Root", Box);
12
+ function HeaderTools(props) {
13
+ const {
14
+ headerActions,
15
+ showFontSizeToggle,
16
+ showLanguageToggle,
17
+ showColorSchemeToggle,
18
+ user,
19
+ profilePath,
20
+ accountMenuItems,
21
+ onSignOut,
22
+ isSigningOut,
23
+ accountSettings,
24
+ vertical = false
25
+ } = usePieceProps(props, THEME_NAME);
21
26
  const hasAppearance = showFontSizeToggle || showLanguageToggle || showColorSchemeToggle;
22
27
  const settings = hasAppearance || accountSettings ? /* @__PURE__ */ jsxs(Fragment, { children: [
23
28
  /* @__PURE__ */ jsx(AppearanceSettings, { showFontSize: showFontSizeToggle, showLanguage: showLanguageToggle, showColorScheme: showColorSchemeToggle }),
24
- hasAppearance && accountSettings && /* @__PURE__ */ jsx(Divider, { sx: { my: 0.5 } }),
29
+ hasAppearance && accountSettings && /* @__PURE__ */ jsx(ToolsDivider, { ownSx: { my: 0.5 } }),
25
30
  accountSettings
26
31
  ] }) : null;
27
- return /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", flexDirection: vertical ? "column" : "row", alignItems: "center", gap: 0.5, flexShrink: 0, "& .MuiButtonBase-root": { color: "inherit" } }, children: [
32
+ return /* @__PURE__ */ jsxs(ToolsRoot, { ownSx: { display: "flex", flexDirection: vertical ? "column" : "row", alignItems: "center", gap: 0.5, flexShrink: 0, "& .MuiButtonBase-root": { color: "inherit" } }, children: [
28
33
  headerActions,
29
34
  user ? /* @__PURE__ */ jsx(
30
35
  AccountMenu,
@@ -1 +1 @@
1
- {"version":3,"file":"HeaderTools.js","sources":["../../src/appShell/HeaderTools.jsx"],"sourcesContent":["// Lo de la derecha de la barra, igual en los dos estilos de barra (menú lateral o arriba):\n// - lo que el proyecto agregue (headerActions: un botón de «reporte urgente», un buscador…);\n// - la cuenta (AccountMenu), y DENTRO de su menú los ajustes de la app: tamaño de letra, idioma, claro u oscuro y los del\n// proyecto (accountSettings). Antes iban sueltos en la barra, cada uno con su botón: ocupaban lugar y en el menú lateral\n// encogido (que hace de barra) tapaban el menú (lo reportaron; el autor pidió «un solo menú como el de perfil»);\n// - sin sesión no hay cuenta: los ajustes van detrás del engrane (SettingsMenu).\n// En columna (vertical) van abajo del menú lateral encogido con vidrio, que hace también de barra (AppLayout).\n//\n// Los botones toman el color de la barra (color: inherit): sobre la barra naranja de Stackcraft van claros, sobre una\n// barra blanca van oscuros, sin que cada botón sepa de qué color es la barra.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Box from '@mui/material/Box';\nimport Divider from '@mui/material/Divider';\n\nimport AccountMenu from '@/appShell/AccountMenu.jsx';\nimport SettingsMenu from '@/appShell/SettingsMenu.jsx';\nimport AppearanceSettings from '@/appShell/AppearanceSettings.jsx';\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode} [props.headerActions]\n * @param {boolean} props.showFontSizeToggle\n * @param {boolean} props.showLanguageToggle\n * @param {boolean} props.showColorSchemeToggle\n * @param {object|null} props.user\n * @param {string} [props.profilePath]\n * @param {object[]} [props.accountMenuItems]\n * @param {import('react').ReactNode} [props.accountSettings] los ajustes del proyecto, en el menú de la cuenta (SettingSection)\n * @param {boolean} [props.vertical] en columna, para el menú lateral encogido\n * @param {() => void} [props.onSignOut]\n * @param {boolean} [props.isSigningOut]\n */\nexport default function HeaderTools({\n headerActions, showFontSizeToggle, showLanguageToggle, showColorSchemeToggle, user, profilePath, accountMenuItems, onSignOut, isSigningOut,\n accountSettings, vertical = false,\n}) {\n const hasAppearance = showFontSizeToggle || showLanguageToggle || showColorSchemeToggle;\n const settings = hasAppearance || accountSettings ? (\n <>\n <AppearanceSettings showFontSize={showFontSizeToggle} showLanguage={showLanguageToggle} showColorScheme={showColorSchemeToggle} />\n {hasAppearance && accountSettings && <Divider sx={{my: 0.5}} />}\n {accountSettings}\n </>\n ) : null;\n\n return (\n <Box sx={{display: 'flex', flexDirection: vertical ? 'column' : 'row', alignItems: 'center', gap: 0.5, flexShrink: 0, '& .MuiButtonBase-root': {color: 'inherit'}}}>\n {headerActions}\n {user ? (\n <AccountMenu user={user} profilePath={profilePath} accountMenuItems={accountMenuItems} onSignOut={onSignOut} isSigningOut={isSigningOut}\n settings={settings} />\n ) : (settings || accountMenuItems?.length > 0) && (\n // sin sesión: el engrane con los ajustes y las ligas propias (en un sistema que ya existía, «Regresar» se perdía)\n <SettingsMenu showFontSize={showFontSizeToggle} showLanguage={showLanguageToggle} showColorScheme={showColorSchemeToggle}\n extraSettings={accountSettings} menuLinks={accountMenuItems} />\n )}\n </Box>\n );\n}\n"],"names":[],"mappings":";;;;;;;AAiCA,SAAwB,YAAY;AAAA,EAChC;AAAA,EAAe;AAAA,EAAoB;AAAA,EAAoB;AAAA,EAAuB;AAAA,EAAM;AAAA,EAAa;AAAA,EAAkB;AAAA,EAAW;AAAA,EAC9H;AAAA,EAAiB,WAAW;AAChC,GAAG;AACC,QAAM,gBAAgB,sBAAsB,sBAAsB;AAClE,QAAM,WAAW,iBAAiB,kBAC9B,qBAAA,UAAA,EACI,UAAA;AAAA,IAAA,oBAAC,sBAAmB,cAAc,oBAAoB,cAAc,oBAAoB,iBAAiB,uBAAuB;AAAA,IAC/H,iBAAiB,mBAAmB,oBAAC,SAAA,EAAQ,IAAI,EAAC,IAAI,OAAM;AAAA,IAC5D;AAAA,EAAA,EAAA,CACL,IACA;AAEJ,SACI,qBAAC,OAAI,IAAI,EAAC,SAAS,QAAQ,eAAe,WAAW,WAAW,OAAO,YAAY,UAAU,KAAK,KAAK,YAAY,GAAG,yBAAyB,EAAC,OAAO,YAAS,GAC3J,UAAA;AAAA,IAAA;AAAA,IACA,OACG;AAAA,MAAC;AAAA,MAAA;AAAA,QAAY;AAAA,QAAY;AAAA,QAA0B;AAAA,QAAoC;AAAA,QAAsB;AAAA,QAChG;AAAA,MAAA;AAAA,IAAA,KACZ,YAAY,kBAAkB,SAAS;AAAA,IAExC;AAAA,MAAC;AAAA,MAAA;AAAA,QAAa,cAAc;AAAA,QAAoB,cAAc;AAAA,QAAoB,iBAAiB;AAAA,QACrF,eAAe;AAAA,QAAiB,WAAW;AAAA,MAAA;AAAA,IAAA;AAAA,EAAkB,GAEnF;AAER;"}
1
+ {"version":3,"file":"HeaderTools.js","sources":["../../src/appShell/HeaderTools.jsx"],"sourcesContent":["// Lo de la derecha de la barra, igual en los dos estilos de barra (menú lateral o arriba):\n// - lo que el proyecto agregue (headerActions: un botón de «reporte urgente», un buscador…);\n// - la cuenta (AccountMenu), y DENTRO de su menú los ajustes de la app: tamaño de letra, idioma, claro u oscuro y los del\n// proyecto (accountSettings). Antes iban sueltos en la barra, cada uno con su botón: ocupaban lugar y en el menú lateral\n// encogido (que hace de barra) tapaban el menú (lo reportaron; el autor pidió «un solo menú como el de perfil»);\n// - sin sesión no hay cuenta: los ajustes van detrás del engrane (SettingsMenu).\n// En columna (vertical) van abajo del menú lateral encogido con vidrio, que hace también de barra (AppLayout).\n//\n// Los botones toman el color de la barra (color: inherit): sobre la barra naranja de Stackcraft van claros, sobre una\n// barra blanca van oscuros, sin que cada botón sepa de qué color es la barra.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaHeaderTools con defaultProps y\n// styleOverrides de sus partes: divider, root.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Box from '@mui/material/Box';\nimport Divider from '@mui/material/Divider';\n\nimport AccountMenu from '@/appShell/AccountMenu.jsx';\nimport SettingsMenu from '@/appShell/SettingsMenu.jsx';\nimport AppearanceSettings from '@/appShell/AppearanceSettings.jsx';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaHeaderTools)\nconst THEME_NAME = 'CalcitaHeaderTools';\nconst ToolsDivider = piecePart(THEME_NAME, 'Divider', Divider);\nconst ToolsRoot = piecePart(THEME_NAME, 'Root', Box);\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode} [props.headerActions]\n * @param {boolean} props.showFontSizeToggle\n * @param {boolean} props.showLanguageToggle\n * @param {boolean} props.showColorSchemeToggle\n * @param {object|null} props.user\n * @param {string} [props.profilePath]\n * @param {object[]} [props.accountMenuItems]\n * @param {import('react').ReactNode} [props.accountSettings] los ajustes del proyecto, en el menú de la cuenta (SettingSection)\n * @param {boolean} [props.vertical] en columna, para el menú lateral encogido\n * @param {() => void} [props.onSignOut]\n * @param {boolean} [props.isSigningOut]\n */\nexport default function HeaderTools(props) {\n // lo que el proyecto puso en su tema (components.CalcitaHeaderTools.defaultProps) y encima lo que llega aquí\n const {\n headerActions, showFontSizeToggle, showLanguageToggle, showColorSchemeToggle, user, profilePath, accountMenuItems, onSignOut, isSigningOut,\n accountSettings, vertical = false,\n} = usePieceProps(props, THEME_NAME);\n const hasAppearance = showFontSizeToggle || showLanguageToggle || showColorSchemeToggle;\n const settings = hasAppearance || accountSettings ? (\n <>\n <AppearanceSettings showFontSize={showFontSizeToggle} showLanguage={showLanguageToggle} showColorScheme={showColorSchemeToggle} />\n {hasAppearance && accountSettings && <ToolsDivider ownSx={{my: 0.5}} />}\n {accountSettings}\n </>\n ) : null;\n\n return (\n <ToolsRoot ownSx={{display: 'flex', flexDirection: vertical ? 'column' : 'row', alignItems: 'center', gap: 0.5, flexShrink: 0, '& .MuiButtonBase-root': {color: 'inherit'}}}>\n {headerActions}\n {user ? (\n <AccountMenu user={user} profilePath={profilePath} accountMenuItems={accountMenuItems} onSignOut={onSignOut} isSigningOut={isSigningOut}\n settings={settings} />\n ) : (settings || accountMenuItems?.length > 0) && (\n // sin sesión: el engrane con los ajustes y las ligas propias (en un sistema que ya existía, «Regresar» se perdía)\n <SettingsMenu showFontSize={showFontSizeToggle} showLanguage={showLanguageToggle} showColorScheme={showColorSchemeToggle}\n extraSettings={accountSettings} menuLinks={accountMenuItems} />\n )}\n </ToolsRoot>\n );\n}\n"],"names":[],"mappings":";;;;;;;;AAwBA,MAAM,aAAa;AACnB,MAAM,eAAe,UAAU,YAAY,WAAW,OAAO;AAC7D,MAAM,YAAY,UAAU,YAAY,QAAQ,GAAG;AAgBnD,SAAwB,YAAY,OAAO;AAEvC,QAAM;AAAA,IACN;AAAA,IAAe;AAAA,IAAoB;AAAA,IAAoB;AAAA,IAAuB;AAAA,IAAM;AAAA,IAAa;AAAA,IAAkB;AAAA,IAAW;AAAA,IAC9H;AAAA,IAAiB,WAAW;AAAA,EAAA,IAC5B,cAAc,OAAO,UAAU;AAC/B,QAAM,gBAAgB,sBAAsB,sBAAsB;AAClE,QAAM,WAAW,iBAAiB,kBAC9B,qBAAA,UAAA,EACI,UAAA;AAAA,IAAA,oBAAC,sBAAmB,cAAc,oBAAoB,cAAc,oBAAoB,iBAAiB,uBAAuB;AAAA,IAC/H,iBAAiB,mBAAmB,oBAAC,cAAA,EAAa,OAAO,EAAC,IAAI,OAAM;AAAA,IACpE;AAAA,EAAA,EAAA,CACL,IACA;AAEJ,SACI,qBAAC,aAAU,OAAO,EAAC,SAAS,QAAQ,eAAe,WAAW,WAAW,OAAO,YAAY,UAAU,KAAK,KAAK,YAAY,GAAG,yBAAyB,EAAC,OAAO,YAAS,GACpK,UAAA;AAAA,IAAA;AAAA,IACA,OACG;AAAA,MAAC;AAAA,MAAA;AAAA,QAAY;AAAA,QAAY;AAAA,QAA0B;AAAA,QAAoC;AAAA,QAAsB;AAAA,QAChG;AAAA,MAAA;AAAA,IAAA,KACZ,YAAY,kBAAkB,SAAS;AAAA,IAExC;AAAA,MAAC;AAAA,MAAA;AAAA,QAAa,cAAc;AAAA,QAAoB,cAAc;AAAA,QAAoB,iBAAiB;AAAA,QACrF,eAAe;AAAA,QAAiB,WAAW;AAAA,MAAA;AAAA,IAAA;AAAA,EAAkB,GAEnF;AAER;"}