@12-apps/ui 6.75.0 → 6.76.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 (56) hide show
  1. package/dist/_internal/components/form/Textarea/Textarea.js +1 -1
  2. package/dist/_internal/components/form/index.js +1 -1
  3. package/dist/_internal/components/index.js +1 -1
  4. package/dist/_internal/components/layout/SettingsLayout/SettingsLayout.items.js +3 -3
  5. package/dist/_internal/components/layout/SettingsLayout/SettingsLayout.js +8 -8
  6. package/dist/_internal/components/layout/SettingsLayout/SettingsLayout.rail.js +4 -4
  7. package/dist/_internal/components/layout/SettingsLayout/SettingsLayout.styles.js +3 -1
  8. package/dist/_internal/components/layout/SettingsLayout/SettingsPanel.js +5 -5
  9. package/dist/_internal/components/layout/SettingsLayout/SettingsSectionChips.js +3 -3
  10. package/dist/_internal/components/layout/SettingsLayout/SettingsSectionHeader.js +2 -2
  11. package/dist/_internal/components/layout/SettingsLayout/SettingsStatusMarker.js +2 -2
  12. package/dist/{chunk-V5EWCJBT.js → chunk-4BLVVMY7.js} +3 -3
  13. package/dist/{chunk-OKYYHBGS.js → chunk-6KM3TL4Q.js} +11 -4
  14. package/dist/chunk-6KM3TL4Q.js.map +1 -0
  15. package/dist/{chunk-DBFRCTI5.js → chunk-7Y2VWMGS.js} +2 -2
  16. package/dist/{chunk-F3Q4CMRB.js → chunk-GBVNY2LG.js} +3 -3
  17. package/dist/{chunk-KKVM723A.js → chunk-LY5I3ZSV.js} +4 -4
  18. package/dist/{chunk-NYFNF7I5.js → chunk-NK4T624E.js} +3 -1
  19. package/dist/chunk-NK4T624E.js.map +1 -0
  20. package/dist/{chunk-X47MWURD.js → chunk-Q6MZHT2F.js} +10 -8
  21. package/dist/chunk-Q6MZHT2F.js.map +1 -0
  22. package/dist/{chunk-TNYKM4UU.js → chunk-SWQXAUUG.js} +55 -21
  23. package/dist/chunk-SWQXAUUG.js.map +1 -0
  24. package/dist/{chunk-6KEXHOIF.js → chunk-WOXNVM52.js} +2 -2
  25. package/dist/form/Textarea.js +1 -1
  26. package/dist/layout/SettingsLayout.js +8 -8
  27. package/dist/types/components/form/Textarea/Textarea.d.ts.map +1 -1
  28. package/dist/types/components/form/Textarea/Textarea.types.d.ts +4 -2
  29. package/dist/types/components/form/Textarea/Textarea.types.d.ts.map +1 -1
  30. package/dist/types/components/layout/SettingsLayout/SettingsLayout.d.ts.map +1 -1
  31. package/dist/types/components/layout/SettingsLayout/SettingsLayout.rail.d.ts +6 -2
  32. package/dist/types/components/layout/SettingsLayout/SettingsLayout.rail.d.ts.map +1 -1
  33. package/dist/types/components/layout/SettingsLayout/SettingsLayout.styles.d.ts +2 -0
  34. package/dist/types/components/layout/SettingsLayout/SettingsLayout.styles.d.ts.map +1 -1
  35. package/dist/types/components/layout/SettingsLayout/SettingsLayout.types.d.ts +19 -0
  36. package/dist/types/components/layout/SettingsLayout/SettingsLayout.types.d.ts.map +1 -1
  37. package/dist/types/components/layout/SettingsLayout/index.d.ts +1 -1
  38. package/dist/types/components/layout/SettingsLayout/index.d.ts.map +1 -1
  39. package/package.json +1 -1
  40. package/src/components/form/Textarea/Textarea.tsx +14 -7
  41. package/src/components/form/Textarea/Textarea.types.ts +4 -2
  42. package/src/components/layout/SettingsLayout/SettingsLayout.md +19 -0
  43. package/src/components/layout/SettingsLayout/SettingsLayout.rail.tsx +67 -23
  44. package/src/components/layout/SettingsLayout/SettingsLayout.styles.ts +3 -0
  45. package/src/components/layout/SettingsLayout/SettingsLayout.tsx +12 -0
  46. package/src/components/layout/SettingsLayout/SettingsLayout.types.ts +20 -0
  47. package/src/components/layout/SettingsLayout/index.ts +1 -0
  48. package/dist/chunk-NYFNF7I5.js.map +0 -1
  49. package/dist/chunk-OKYYHBGS.js.map +0 -1
  50. package/dist/chunk-TNYKM4UU.js.map +0 -1
  51. package/dist/chunk-X47MWURD.js.map +0 -1
  52. /package/dist/{chunk-V5EWCJBT.js.map → chunk-4BLVVMY7.js.map} +0 -0
  53. /package/dist/{chunk-DBFRCTI5.js.map → chunk-7Y2VWMGS.js.map} +0 -0
  54. /package/dist/{chunk-F3Q4CMRB.js.map → chunk-GBVNY2LG.js.map} +0 -0
  55. /package/dist/{chunk-KKVM723A.js.map → chunk-LY5I3ZSV.js.map} +0 -0
  56. /package/dist/{chunk-6KEXHOIF.js.map → chunk-WOXNVM52.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Textarea
3
- } from "../../../../chunk-X47MWURD.js";
3
+ } from "../../../../chunk-Q6MZHT2F.js";
4
4
  import "../../../../chunk-IPC426NS.js";
5
5
  import "../../../../chunk-RGVNXES5.js";
6
6
  import "../../../../chunk-GDN2LUTZ.js";
@@ -2,7 +2,7 @@ import "../../../chunk-BOWS4U6W.js";
2
2
  import "../../../chunk-BH5GSBR3.js";
3
3
  import {
4
4
  Textarea
5
- } from "../../../chunk-X47MWURD.js";
5
+ } from "../../../chunk-Q6MZHT2F.js";
6
6
  import "../../../chunk-IPC426NS.js";
7
7
  import "../../../chunk-6I3TYKE2.js";
8
8
  import {
@@ -219,7 +219,7 @@ import "../../chunk-QUWK7SYN.js";
219
219
  import "../../chunk-BH5GSBR3.js";
220
220
  import {
221
221
  Textarea
222
- } from "../../chunk-X47MWURD.js";
222
+ } from "../../chunk-Q6MZHT2F.js";
223
223
  import "../../chunk-IPC426NS.js";
224
224
  import "../../chunk-6I3TYKE2.js";
225
225
  import {
@@ -2,9 +2,9 @@
2
2
  import {
3
3
  SettingsRailGroup,
4
4
  SettingsRailItem
5
- } from "../../../../chunk-V5EWCJBT.js";
6
- import "../../../../chunk-DBFRCTI5.js";
7
- import "../../../../chunk-NYFNF7I5.js";
5
+ } from "../../../../chunk-4BLVVMY7.js";
6
+ import "../../../../chunk-7Y2VWMGS.js";
7
+ import "../../../../chunk-NK4T624E.js";
8
8
  import "../../../../chunk-YKCAJ2TN.js";
9
9
  import "../../../../chunk-PZ5AY32C.js";
10
10
  export {
@@ -1,16 +1,16 @@
1
1
  "use client";
2
2
  import {
3
3
  SettingsLayout
4
- } from "../../../../chunk-OKYYHBGS.js";
4
+ } from "../../../../chunk-6KM3TL4Q.js";
5
5
  import "../../../../chunk-BXC6GRLE.js";
6
- import "../../../../chunk-KKVM723A.js";
7
- import "../../../../chunk-F3Q4CMRB.js";
6
+ import "../../../../chunk-LY5I3ZSV.js";
7
+ import "../../../../chunk-GBVNY2LG.js";
8
8
  import "../../../../chunk-AJUSBPWG.js";
9
- import "../../../../chunk-TNYKM4UU.js";
10
- import "../../../../chunk-V5EWCJBT.js";
11
- import "../../../../chunk-DBFRCTI5.js";
12
- import "../../../../chunk-6KEXHOIF.js";
13
- import "../../../../chunk-NYFNF7I5.js";
9
+ import "../../../../chunk-SWQXAUUG.js";
10
+ import "../../../../chunk-4BLVVMY7.js";
11
+ import "../../../../chunk-7Y2VWMGS.js";
12
+ import "../../../../chunk-WOXNVM52.js";
13
+ import "../../../../chunk-NK4T624E.js";
14
14
  import "../../../../chunk-HPK33ACY.js";
15
15
  import "../../../../chunk-YKCAJ2TN.js";
16
16
  import "../../../../chunk-PZ5AY32C.js";
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import {
3
3
  SettingsRail
4
- } from "../../../../chunk-TNYKM4UU.js";
5
- import "../../../../chunk-V5EWCJBT.js";
6
- import "../../../../chunk-DBFRCTI5.js";
7
- import "../../../../chunk-NYFNF7I5.js";
4
+ } from "../../../../chunk-SWQXAUUG.js";
5
+ import "../../../../chunk-4BLVVMY7.js";
6
+ import "../../../../chunk-7Y2VWMGS.js";
7
+ import "../../../../chunk-NK4T624E.js";
8
8
  import "../../../../chunk-YKCAJ2TN.js";
9
9
  import "../../../../chunk-PZ5AY32C.js";
10
10
  export {
@@ -4,8 +4,9 @@ import {
4
4
  TOUCH_TARGET,
5
5
  atLeastRail,
6
6
  displayAcrossRail,
7
+ railCardWidth,
7
8
  railWidth
8
- } from "../../../../chunk-NYFNF7I5.js";
9
+ } from "../../../../chunk-NK4T624E.js";
9
10
  import "../../../../chunk-YKCAJ2TN.js";
10
11
  import "../../../../chunk-PZ5AY32C.js";
11
12
  export {
@@ -14,6 +15,7 @@ export {
14
15
  TOUCH_TARGET,
15
16
  atLeastRail,
16
17
  displayAcrossRail,
18
+ railCardWidth,
17
19
  railWidth
18
20
  };
19
21
  //# sourceMappingURL=SettingsLayout.styles.js.map
@@ -1,12 +1,12 @@
1
1
  "use client";
2
2
  import {
3
3
  SettingsPanel
4
- } from "../../../../chunk-KKVM723A.js";
5
- import "../../../../chunk-F3Q4CMRB.js";
4
+ } from "../../../../chunk-LY5I3ZSV.js";
5
+ import "../../../../chunk-GBVNY2LG.js";
6
6
  import "../../../../chunk-AJUSBPWG.js";
7
- import "../../../../chunk-DBFRCTI5.js";
8
- import "../../../../chunk-6KEXHOIF.js";
9
- import "../../../../chunk-NYFNF7I5.js";
7
+ import "../../../../chunk-7Y2VWMGS.js";
8
+ import "../../../../chunk-WOXNVM52.js";
9
+ import "../../../../chunk-NK4T624E.js";
10
10
  import "../../../../chunk-YKCAJ2TN.js";
11
11
  import "../../../../chunk-PZ5AY32C.js";
12
12
  export {
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import {
3
3
  SettingsSectionChips
4
- } from "../../../../chunk-F3Q4CMRB.js";
4
+ } from "../../../../chunk-GBVNY2LG.js";
5
5
  import "../../../../chunk-AJUSBPWG.js";
6
- import "../../../../chunk-DBFRCTI5.js";
7
- import "../../../../chunk-NYFNF7I5.js";
6
+ import "../../../../chunk-7Y2VWMGS.js";
7
+ import "../../../../chunk-NK4T624E.js";
8
8
  import "../../../../chunk-YKCAJ2TN.js";
9
9
  import "../../../../chunk-PZ5AY32C.js";
10
10
  export {
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import {
3
3
  SettingsSectionHeader
4
- } from "../../../../chunk-6KEXHOIF.js";
5
- import "../../../../chunk-NYFNF7I5.js";
4
+ } from "../../../../chunk-WOXNVM52.js";
5
+ import "../../../../chunk-NK4T624E.js";
6
6
  import "../../../../chunk-YKCAJ2TN.js";
7
7
  import "../../../../chunk-PZ5AY32C.js";
8
8
  export {
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import {
3
3
  SettingsStatusMarker
4
- } from "../../../../chunk-DBFRCTI5.js";
5
- import "../../../../chunk-NYFNF7I5.js";
4
+ } from "../../../../chunk-7Y2VWMGS.js";
5
+ import "../../../../chunk-NK4T624E.js";
6
6
  import "../../../../chunk-YKCAJ2TN.js";
7
7
  import "../../../../chunk-PZ5AY32C.js";
8
8
  export {
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  SettingsStatusMarker
3
- } from "./chunk-DBFRCTI5.js";
3
+ } from "./chunk-7Y2VWMGS.js";
4
4
  import {
5
5
  TOUCH_TARGET,
6
6
  atLeastRail
7
- } from "./chunk-NYFNF7I5.js";
7
+ } from "./chunk-NK4T624E.js";
8
8
  import {
9
9
  rem
10
10
  } from "./chunk-YKCAJ2TN.js";
@@ -169,4 +169,4 @@ export {
169
169
  SettingsRailItem,
170
170
  SettingsRailGroup
171
171
  };
172
- //# sourceMappingURL=chunk-V5EWCJBT.js.map
172
+ //# sourceMappingURL=chunk-4BLVVMY7.js.map
@@ -4,13 +4,13 @@ import {
4
4
  } from "./chunk-BXC6GRLE.js";
5
5
  import {
6
6
  SettingsPanel
7
- } from "./chunk-KKVM723A.js";
7
+ } from "./chunk-LY5I3ZSV.js";
8
8
  import {
9
9
  SettingsRail
10
- } from "./chunk-TNYKM4UU.js";
10
+ } from "./chunk-SWQXAUUG.js";
11
11
  import {
12
12
  atLeastRail
13
- } from "./chunk-NYFNF7I5.js";
13
+ } from "./chunk-NK4T624E.js";
14
14
  import {
15
15
  withDefaults
16
16
  } from "./chunk-HPK33ACY.js";
@@ -29,6 +29,12 @@ var DEFAULTS = {
29
29
  atIndex: false,
30
30
  backLabel: "Back"
31
31
  };
32
+ function railLookOf({
33
+ searchable = true,
34
+ railVariant = "divided"
35
+ }) {
36
+ return { searchable, railVariant };
37
+ }
32
38
  function shellSx(breakpoint, fillHeight) {
33
39
  return (theme) => ({
34
40
  display: "flex",
@@ -101,6 +107,7 @@ var SettingsLayout = (props) => {
101
107
  onNavigate: () => setNavOpen(false),
102
108
  testIdPrefix,
103
109
  variant: navVariant,
110
+ ...railLookOf(props),
104
111
  breakpoint: railBreakpoint,
105
112
  atIndex,
106
113
  fillHeight
@@ -135,4 +142,4 @@ SettingsLayout.displayName = "SettingsLayout";
135
142
  export {
136
143
  SettingsLayout
137
144
  };
138
- //# sourceMappingURL=chunk-OKYYHBGS.js.map
145
+ //# sourceMappingURL=chunk-6KM3TL4Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/layout/SettingsLayout/SettingsLayout.tsx"],"sourcesContent":["'use client';\n\nimport Box from '@mui/material/Box/index.js';\nimport type { SxProps, Theme } from '@mui/material/styles/index.js';\nimport React, { useMemo, useState } from 'react';\n\nimport { withDefaults } from '../../../utils/withDefaults';\nimport { activeItemLabel, filterGroups } from './SettingsLayout.filters';\nimport { SettingsRail } from './SettingsLayout.rail';\nimport { atLeastRail } from './SettingsLayout.styles';\nimport { SettingsPanel } from './SettingsPanel';\nimport type { SettingsLayoutProps } from './SettingsLayout.types';\n\n/**\n * The props with every default already applied.\n *\n * A table through `withDefaults` rather than a `= default` per destructured\n * prop: each of those is a branch, and seven of them put the component over the\n * complexity bar before it renders anything. The single cast is what buys the\n * body non-optional values — without it every use site would restate the\n * default as a `??`, which is the same default written twice and free to drift.\n */\ntype ResolvedProps = SettingsLayoutProps &\n Required<\n Pick<\n SettingsLayoutProps,\n | 'searchPlaceholder'\n | 'defaultQuery'\n | 'emptySearchLabel'\n | 'testIdPrefix'\n | 'railBreakpoint'\n | 'navVariant'\n | 'atIndex'\n | 'backLabel'\n >\n >;\n\nconst DEFAULTS = {\n searchPlaceholder: 'Search settings',\n defaultQuery: '',\n emptySearchLabel: 'No settings match your search.',\n testIdPrefix: 'settings',\n railBreakpoint: 'md',\n navVariant: 'switcher',\n atIndex: false,\n backLabel: 'Back',\n} satisfies Partial<SettingsLayoutProps>;\n\n/**\n * How the rail looks: its search field, and its frame from the breakpoint up.\n * Both default to the shape every consumer had before they existed.\n */\nfunction railLookOf({\n searchable = true,\n railVariant = 'divided',\n}: SettingsLayoutProps): Required<Pick<SettingsLayoutProps, 'searchable' | 'railVariant'>> {\n return { searchable, railVariant };\n}\n\n/** Stacked below the rail's breakpoint, two columns at and above it. */\nfunction shellSx(breakpoint: SettingsLayoutProps['railBreakpoint'], fillHeight: boolean): SxProps<Theme> {\n return (theme: Theme) => ({\n display: 'flex',\n flexDirection: 'column' as const,\n alignItems: 'stretch',\n gap: 1.5,\n width: '100%',\n minWidth: 0,\n // Only ever at the wide shape. Narrow, the rail is a disclosure or the page\n // itself, and two independent scrollbars on a phone is a trap rather than a\n // convenience.\n [atLeastRail(theme, breakpoint ?? 'md')]: {\n flexDirection: 'row',\n gap: 3,\n ...(fillHeight ? { height: '100%', minHeight: 0 } : {}),\n },\n });\n}\n\n/**\n * A reusable, agnostic Facebook-style settings shell: a searchable left rail of\n * grouped categories/subcategories and a central panel that renders the selected\n * configuration screen (`children`). Navigation is data-driven via `groups`; the\n * host owns routing (pass `linkComponent` + item `href`, or handle `onSelectItem`).\n *\n * ## Two narrow-width shapes\n *\n * `navVariant=\"switcher\"` (the default) folds the rail into a disclosure above\n * the panel. `navVariant=\"drilldown\"` gives the phone shape instead: at the\n * area's index the LIST is the page, and inside a section the panel is the page\n * with a back link and a scrollable strip of sibling sections above it.\n *\n * ## Why the width decision is CSS and not JavaScript\n *\n * Every part that changes between the two shapes does it through a `display`\n * pair keyed on `railBreakpoint`. Nothing here asks a media query in JS and\n * renders one branch.\n *\n * That is not a performance preference. A layout that RENDERS one navigation and\n * not the other can offer the narrow width less than the wide one, and no test\n * or review catches it — the missing control simply is not in the tree to be\n * asserted about. With both forms always mounted, \"the narrow width reaches\n * everything the wide one does\" holds by construction, and an audit that counts\n * controls per width gets the same answer at both.\n */\nexport const SettingsLayout: React.FC<SettingsLayoutProps> = (props) => {\n const {\n title,\n groups,\n activeItemId,\n onSelectItem,\n searchPlaceholder,\n defaultQuery,\n emptySearchLabel,\n emptySearchAction,\n linkComponent,\n children,\n testIdPrefix,\n railBreakpoint,\n fillHeight = false,\n navVariant,\n atIndex,\n indexHref,\n backLabel,\n sectionChips,\n } = withDefaults(props, DEFAULTS) as ResolvedProps;\n const [query, setQuery] = useState(defaultQuery);\n const [navOpen, setNavOpen] = useState(false);\n const filteredGroups = useMemo(() => filterGroups(groups, query), [groups, query]);\n const activeLabel = useMemo(() => activeItemLabel(groups, activeItemId), [groups, activeItemId]);\n\n const drilldown = navVariant === 'drilldown';\n const ariaLabel = typeof title === 'string' ? title : 'Settings';\n\n return (\n <Box\n data-testid={testIdPrefix}\n data-nav-variant={navVariant}\n data-at-index={atIndex ? 'true' : 'false'}\n sx={shellSx(railBreakpoint, fillHeight)}\n >\n <SettingsRail\n title={title}\n activeLabel={activeLabel}\n navOpen={navOpen}\n onToggleNav={() => setNavOpen((open) => !open)}\n query={query}\n onQueryChange={setQuery}\n searchPlaceholder={searchPlaceholder}\n emptySearchLabel={emptySearchLabel}\n emptySearchAction={emptySearchAction}\n filteredGroups={filteredGroups}\n activeItemId={activeItemId}\n linkComponent={linkComponent}\n onSelectItem={onSelectItem}\n onNavigate={() => setNavOpen(false)}\n testIdPrefix={testIdPrefix}\n variant={navVariant}\n {...railLookOf(props)}\n breakpoint={railBreakpoint}\n atIndex={atIndex}\n fillHeight={fillHeight}\n />\n\n <SettingsPanel\n inSection={drilldown && !atIndex}\n hideOnNarrow={drilldown && atIndex}\n breakpoint={railBreakpoint}\n indexHref={indexHref}\n sectionTitle={props.sectionTitle}\n sectionDescription={props.sectionDescription}\n backLabel={backLabel}\n ariaLabel={ariaLabel}\n sectionChips={sectionChips}\n activeItemId={activeItemId}\n linkComponent={linkComponent}\n onSelectItem={onSelectItem}\n testIdPrefix={testIdPrefix}\n fillHeight={fillHeight}\n >\n {children}\n </SettingsPanel>\n </Box>\n );\n};\n\nSettingsLayout.displayName = 'SettingsLayout';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAEA,OAAO,SAAS;AAEhB,SAAgB,SAAS,gBAAgB;AAmIrC,SAME,KANF;AAlGJ,IAAM,WAAW;AAAA,EACf,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,WAAW;AACb;AAMA,SAAS,WAAW;AAAA,EAClB,aAAa;AAAA,EACb,cAAc;AAChB,GAA2F;AACzF,SAAO,EAAE,YAAY,YAAY;AACnC;AAGA,SAAS,QAAQ,YAAmD,YAAqC;AACvG,SAAO,CAAC,WAAkB;AAAA,IACxB,SAAS;AAAA,IACT,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,OAAO;AAAA,IACP,UAAU;AAAA;AAAA;AAAA;AAAA,IAIV,CAAC,YAAY,OAAO,cAAc,IAAI,CAAC,GAAG;AAAA,MACxC,eAAe;AAAA,MACf,KAAK;AAAA,MACL,GAAI,aAAa,EAAE,QAAQ,QAAQ,WAAW,EAAE,IAAI,CAAC;AAAA,IACvD;AAAA,EACF;AACF;AA4BO,IAAM,iBAAgD,CAAC,UAAU;AACtE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,aAAa,OAAO,QAAQ;AAChC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,YAAY;AAC/C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,iBAAiB,QAAQ,MAAM,aAAa,QAAQ,KAAK,GAAG,CAAC,QAAQ,KAAK,CAAC;AACjF,QAAM,cAAc,QAAQ,MAAM,gBAAgB,QAAQ,YAAY,GAAG,CAAC,QAAQ,YAAY,CAAC;AAE/F,QAAM,YAAY,eAAe;AACjC,QAAM,YAAY,OAAO,UAAU,WAAW,QAAQ;AAEtD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAa;AAAA,MACb,oBAAkB;AAAA,MAClB,iBAAe,UAAU,SAAS;AAAA,MAClC,IAAI,QAAQ,gBAAgB,UAAU;AAAA,MAEtC;AAAA;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA,aAAa,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI;AAAA,YAC7C;AAAA,YACA,eAAe;AAAA,YACf;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,YAAY,MAAM,WAAW,KAAK;AAAA,YAClC;AAAA,YACA,SAAS;AAAA,YACR,GAAG,WAAW,KAAK;AAAA,YACpB,YAAY;AAAA,YACZ;AAAA,YACA;AAAA;AAAA,QACF;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,aAAa,CAAC;AAAA,YACzB,cAAc,aAAa;AAAA,YAC3B,YAAY;AAAA,YACZ;AAAA,YACA,cAAc,MAAM;AAAA,YACpB,oBAAoB,MAAM;AAAA,YAC1B;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YAEC;AAAA;AAAA,QACH;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,eAAe,cAAc;","names":[]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  SR_ONLY_SX,
3
3
  STATUS_COLOR
4
- } from "./chunk-NYFNF7I5.js";
4
+ } from "./chunk-NK4T624E.js";
5
5
  import {
6
6
  sxRem
7
7
  } from "./chunk-YKCAJ2TN.js";
@@ -62,4 +62,4 @@ SettingsStatusMarker.displayName = "SettingsStatusMarker";
62
62
  export {
63
63
  SettingsStatusMarker
64
64
  };
65
- //# sourceMappingURL=chunk-DBFRCTI5.js.map
65
+ //# sourceMappingURL=chunk-7Y2VWMGS.js.map
@@ -5,10 +5,10 @@ import {
5
5
  } from "./chunk-AJUSBPWG.js";
6
6
  import {
7
7
  SettingsStatusMarker
8
- } from "./chunk-DBFRCTI5.js";
8
+ } from "./chunk-7Y2VWMGS.js";
9
9
  import {
10
10
  TOUCH_TARGET
11
- } from "./chunk-NYFNF7I5.js";
11
+ } from "./chunk-NK4T624E.js";
12
12
  import {
13
13
  rem,
14
14
  sxRem
@@ -186,4 +186,4 @@ SettingsSectionChips.displayName = "SettingsSectionChips";
186
186
  export {
187
187
  SettingsSectionChips
188
188
  };
189
- //# sourceMappingURL=chunk-F3Q4CMRB.js.map
189
+ //# sourceMappingURL=chunk-GBVNY2LG.js.map
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  SettingsSectionChips
3
- } from "./chunk-F3Q4CMRB.js";
3
+ } from "./chunk-GBVNY2LG.js";
4
4
  import {
5
5
  SettingsSectionHeader
6
- } from "./chunk-6KEXHOIF.js";
6
+ } from "./chunk-WOXNVM52.js";
7
7
  import {
8
8
  TOUCH_TARGET,
9
9
  atLeastRail,
10
10
  displayAcrossRail
11
- } from "./chunk-NYFNF7I5.js";
11
+ } from "./chunk-NK4T624E.js";
12
12
  import {
13
13
  rem
14
14
  } from "./chunk-YKCAJ2TN.js";
@@ -167,4 +167,4 @@ function SettingsPanel({
167
167
  export {
168
168
  SettingsPanel
169
169
  };
170
- //# sourceMappingURL=chunk-KKVM723A.js.map
170
+ //# sourceMappingURL=chunk-LY5I3ZSV.js.map
@@ -5,6 +5,7 @@ import {
5
5
 
6
6
  // src/components/layout/SettingsLayout/SettingsLayout.styles.ts
7
7
  var railWidth = (theme) => rem(theme, 300);
8
+ var railCardWidth = (theme) => rem(theme, 200);
8
9
  var SR_ONLY_SX = {
9
10
  position: "absolute",
10
11
  width: sxRem(1),
@@ -31,10 +32,11 @@ var STATUS_COLOR = {
31
32
 
32
33
  export {
33
34
  railWidth,
35
+ railCardWidth,
34
36
  SR_ONLY_SX,
35
37
  atLeastRail,
36
38
  displayAcrossRail,
37
39
  TOUCH_TARGET,
38
40
  STATUS_COLOR
39
41
  };
40
- //# sourceMappingURL=chunk-NYFNF7I5.js.map
42
+ //# sourceMappingURL=chunk-NK4T624E.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/layout/SettingsLayout/SettingsLayout.styles.ts"],"sourcesContent":["import type { CSSObject, SxProps, Theme } from '@mui/material/styles/index.js';\n\nimport { rem, sxRem } from '../../../tokens/relative';\n\nimport type { SettingsNavStatus, SettingsRailBreakpoint } from './SettingsLayout.types';\n\n/** Fixed width of the left navigation rail once it has its own column (300 design px). */\nexport const railWidth = (theme: Theme): string => rem(theme, 300);\n\n/** Width of the rail drawn as a card (`railVariant=\"card\"`, 200 design px). */\nexport const railCardWidth = (theme: Theme): string => rem(theme, 200);\n\n/** Visually hidden, still read aloud — for text a marker's colour cannot carry. */\nexport const SR_ONLY_SX: SxProps<Theme> = {\n position: 'absolute',\n width: sxRem(1),\n height: sxRem(1),\n padding: 0,\n margin: sxRem(-1),\n overflow: 'hidden',\n clip: 'rect(0, 0, 0, 0)',\n whiteSpace: 'nowrap',\n border: 0,\n};\n\n/**\n * The media query for \"the rail has its own column\".\n *\n * `theme.breakpoints.up` takes a NUMBER as happily as a name, which is why\n * `railBreakpoint` accepts one: a settings area whose structural switch is at\n * 1024px has no MUI breakpoint to name (the default `lg` is 1200), and rounding\n * the design to the nearest named breakpoint moves 176px of behaviour to keep a\n * string tidy.\n */\nexport function atLeastRail(theme: Theme, breakpoint: SettingsRailBreakpoint): string {\n return theme.breakpoints.up(breakpoint);\n}\n\n/**\n * A `display` pair across that query: `narrow` below it, `wide` at and above.\n *\n * Everything that changes shape between the two navigation modes goes through\n * this, so \"which width am I?\" is answered once, in CSS, for every part at\n * once — rather than by each part asking a media query in JavaScript and\n * answering slightly differently.\n */\nexport function displayAcrossRail(\n theme: Theme,\n breakpoint: SettingsRailBreakpoint,\n narrow: string,\n wide: string,\n): CSSObject {\n return { display: narrow, [atLeastRail(theme, breakpoint)]: { display: wide } };\n}\n\n/** Minimum touch target, in px. Held down to 320px-wide phones, deliberately. */\nexport const TOUCH_TARGET = 44;\n\n/**\n * Palette role per situation.\n *\n * Returned as theme keys rather than hex so a marker follows the host's theme —\n * and so light and dark do not need two copies of this table.\n */\nexport const STATUS_COLOR: Record<Exclude<SettingsNavStatus, 'locked'>, string> = {\n ok: 'success.main',\n off: 'text.disabled',\n new: 'error.main',\n};\n"],"mappings":";;;;;;AAOO,IAAM,YAAY,CAAC,UAAyB,IAAI,OAAO,GAAG;AAG1D,IAAM,gBAAgB,CAAC,UAAyB,IAAI,OAAO,GAAG;AAG9D,IAAM,aAA6B;AAAA,EACxC,UAAU;AAAA,EACV,OAAO,MAAM,CAAC;AAAA,EACd,QAAQ,MAAM,CAAC;AAAA,EACf,SAAS;AAAA,EACT,QAAQ,MAAM,EAAE;AAAA,EAChB,UAAU;AAAA,EACV,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,QAAQ;AACV;AAWO,SAAS,YAAY,OAAc,YAA4C;AACpF,SAAO,MAAM,YAAY,GAAG,UAAU;AACxC;AAUO,SAAS,kBACd,OACA,YACA,QACA,MACW;AACX,SAAO,EAAE,SAAS,QAAQ,CAAC,YAAY,OAAO,UAAU,CAAC,GAAG,EAAE,SAAS,KAAK,EAAE;AAChF;AAGO,IAAM,eAAe;AAQrB,IAAM,eAAqE;AAAA,EAChF,IAAI;AAAA,EACJ,KAAK;AAAA,EACL,KAAK;AACP;","names":[]}
@@ -49,11 +49,11 @@ var StyledTextarea = styled(TextareaAutosize, {
49
49
  const colorPalette = getColorFromTheme(theme, customColor);
50
50
  const errorColor = theme.palette.error;
51
51
  const sizeMap = {
52
- xs: { padding: rems(theme, 6, 8), fontSize: rem(theme, 12), minHeight: rem(theme, 60) },
53
- sm: { padding: rems(theme, 8, 10), fontSize: rem(theme, 14), minHeight: rem(theme, 80) },
54
- md: { padding: rems(theme, 10, 12), fontSize: rem(theme, 16), minHeight: rem(theme, 100) },
55
- lg: { padding: rems(theme, 12, 14), fontSize: rem(theme, 18), minHeight: rem(theme, 120) },
56
- xl: { padding: rems(theme, 14, 16), fontSize: rem(theme, 20), minHeight: rem(theme, 140) }
52
+ xs: { padding: rems(theme, 6, 8), fontSize: rem(theme, 12) },
53
+ sm: { padding: rems(theme, 8, 10), fontSize: rem(theme, 14) },
54
+ md: { padding: rems(theme, 10, 12), fontSize: rem(theme, 16) },
55
+ lg: { padding: rems(theme, 12, 14), fontSize: rem(theme, 18) },
56
+ xl: { padding: rems(theme, 14, 16), fontSize: rem(theme, 20) }
57
57
  };
58
58
  const baseStyles = {
59
59
  width: "100%",
@@ -112,7 +112,9 @@ var TEXTAREA_DEFAULTS = {
112
112
  glass: false,
113
113
  gradient: false,
114
114
  iconPosition: "start",
115
- minRows: 3
115
+ // Four lines of its own text, whatever the variant or size (FUT-3534); a
116
+ // screen that wants another height passes `minRows`.
117
+ minRows: 4
116
118
  };
117
119
  var definedProps = (props) => Object.fromEntries(
118
120
  Object.entries(props).filter(([, value]) => value !== void 0)
@@ -210,7 +212,7 @@ var Textarea = (textareaProps) => {
210
212
  glass,
211
213
  gradient,
212
214
  error,
213
- minRows: variant === "autosize" ? minRows : void 0,
215
+ minRows,
214
216
  maxRows: variant === "autosize" ? maxRows : void 0,
215
217
  style: textareaStyle,
216
218
  "aria-label": label || props["aria-label"],
@@ -225,4 +227,4 @@ Textarea.displayName = "Textarea";
225
227
  export {
226
228
  Textarea
227
229
  };
228
- //# sourceMappingURL=chunk-X47MWURD.js.map
230
+ //# sourceMappingURL=chunk-Q6MZHT2F.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/form/Textarea/Textarea.tsx"],"sourcesContent":["import Box from '@mui/material/Box/index.js';\nimport FormHelperText from '@mui/material/FormHelperText/index.js';\nimport InputLabel from '@mui/material/InputLabel/index.js';\nimport TextareaAutosize from '@mui/material/TextareaAutosize/index.js';\nimport { alpha, styled, useTheme } from '@mui/material/styles/index.js';\nimport type { Theme } from '@mui/material/styles/index.js';\nimport React, { lazy, Suspense, useState } from 'react';\n\nimport {\n getColorFromTheme,\n textareaEmphasisStyles } from './Textarea.styles';\n\n/**\n * The rich editor is LOADED ON DEMAND, not imported (12-51 follow-up).\n *\n * It renders only for `variant === 'rich'`, but a static import made every\n * consumer of a plain `<Textarea>` pay for it — 387 lines of toolbar plus the\n * MUI `Tooltip`, `IconButton` and `Divider` its formatting buttons need. That\n * is not theoretical: an adopting storefront imports this entry for a one-line\n * order note, and `Tooltip` (8.7 KiB) reached its EAGER chunk through here\n * while nothing on that critical path renders a tooltip at all.\n *\n * `variant` is a prop, so the branch cannot be decided at build time and no\n * amount of tree-shaking removes it. A lazy boundary is what expresses \"only\n * the rich variant pays\", and it costs the rich variant one microtask it can\n * afford — it is a text editor a user has already chosen to open, never a\n * first-paint element.\n */\nconst TextareaRichEditor = lazy(async () => ({\n default: (await import('./TextareaRichEditor')).TextareaRichEditor }));\nimport type { TextareaProps } from './Textarea.types';\n\nimport { fieldEdge } from '../../../tokens/field-edge';\nimport { fieldRadius } from '../../../tokens/field-radius';\nimport { FIELD_BORDER_WIDTH, fieldBorder } from '../../../tokens/field-height';\nimport { rem, rems, sxRem } from '../../../tokens/relative';\n\n// Interface for styled component props\ninterface StyledTextareaProps {\n customVariant?: string;\n customColor?: string;\n customSize?: string;\n glow?: boolean;\n glass?: boolean;\n gradient?: boolean;\n error?: boolean;\n theme?: Theme;\n}\n\n// Glow animation for enhanced visual effects\nconst StyledTextarea = styled(TextareaAutosize, {\n shouldForwardProp: (prop) =>\n !['customVariant', 'customColor', 'customSize', 'glow', 'glass', 'gradient', 'error'].includes(\n prop as string,\n ) })<StyledTextareaProps>(({\n theme,\n customVariant,\n customColor = 'primary',\n customSize = 'md',\n glow,\n glass,\n gradient,\n error }) => {\n if (!theme) return {};\n const colorPalette = getColorFromTheme(theme, customColor);\n const errorColor = theme.palette.error;\n\n // No min-height here: the box's height is counted in LINES of its own text\n // (`minRows`). A pixel floor broke that twice over — it ignored the font, and\n // `TextareaAutosize` measures one row on a hidden copy carrying this same\n // class, so a \"row\" came out as the whole floor and `minRows={2}` drew about\n // 200px (FUT-3504, FUT-3534).\n const sizeMap = {\n xs: { padding: rems(theme, 6, 8), fontSize: rem(theme, 12) },\n sm: { padding: rems(theme, 8, 10), fontSize: rem(theme, 14) },\n md: { padding: rems(theme, 10, 12), fontSize: rem(theme, 16) },\n lg: { padding: rems(theme, 12, 14), fontSize: rem(theme, 18) },\n xl: { padding: rems(theme, 14, 16), fontSize: rem(theme, 20) } };\n\n const baseStyles = {\n width: '100%',\n fontFamily: theme.typography.fontFamily,\n borderRadius: fieldRadius(theme),\n border: error ? `${FIELD_BORDER_WIDTH}px solid ${errorColor.main}` : fieldBorder(theme),\n backgroundColor: theme.palette.background.paper,\n color: theme.palette.text.primary,\n transition: 'all 0.3s ease',\n resize: customVariant === 'resizable' ? 'vertical' : 'none',\n outline: 'none',\n ...sizeMap[customSize as keyof typeof sizeMap],\n\n '&::placeholder': {\n color: theme.palette.text.secondary,\n opacity: 0.7 },\n\n '&:hover': {\n borderColor: error ? errorColor.dark : colorPalette.main,\n backgroundColor: alpha(theme.palette.background.paper, 0.8) },\n\n // Focus is two pixels, like every other field's: the second is an inset\n // shadow, so the 1px resting border can thicken without the box moving.\n '&:focus': {\n borderColor: error ? errorColor.main : colorPalette.main,\n backgroundColor: theme.palette.background.paper,\n boxShadow: `inset 0 0 0 ${FIELD_BORDER_WIDTH}px ${error ? errorColor.main : colorPalette.main}, 0 0 0 ${rem(theme, 3)} ${alpha(error ? errorColor.main : colorPalette.main, 0.1)}` } };\n\n // Glass morphism effect\n return {\n ...baseStyles,\n ...textareaEmphasisStyles({ theme, colorPalette, glass, gradient, glow }) };\n});\n\nconst StyledLabel = styled(InputLabel, {\n shouldForwardProp: (prop) => !['glass', 'error'].includes(prop as string) })<{ glass?: boolean; error?: boolean }>(({ theme, glass, error }) => ({\n marginBottom: theme.spacing(1),\n fontWeight: 500,\n color: error ? theme.palette.error.main : theme.palette.text.primary,\n ...(glass && {\n backgroundColor: alpha(theme.palette.background.paper, 0.1),\n backdropFilter: `blur(${rem(theme, 10)})`,\n padding: rems(theme, 4, 8),\n borderRadius: rem(theme, 4),\n border: `1px solid ${fieldEdge(theme)}`,\n display: 'inline-block' }) }));\n\n// IconWrapper - replaced with inline Box component for better TypeScript compatibility\n// const IconWrapper = styled(Box)<{ position: 'start' | 'end' }>(({ theme, position }) => {\n// const positionStyles = position === 'start' ? { left: '12px' } : { right: '12px' };\n// return {\n// position: 'absolute' as const,\n// top: '12px',\n// ...positionStyles,\n// color: theme.palette.text.secondary,\n// pointerEvents: 'none' as const,\n// zIndex: 1,\n// };\n// });\n\n// Rich text toolbar styling\n\nconst TEXTAREA_DEFAULTS = {\n variant: 'default',\n color: 'primary',\n size: 'md',\n error: false,\n glassLabel: false,\n glow: false,\n glass: false,\n gradient: false,\n iconPosition: 'start',\n // Four lines of its own text, whatever the variant or size (FUT-3534); a\n // screen that wants another height passes `minRows`.\n minRows: 4 } satisfies Partial<TextareaProps>;\n\n// Strips explicitly-undefined props before the merge, so `prop={undefined}`\n// still falls back to the default as a destructuring default would.\nconst definedProps = (props: TextareaProps): Partial<TextareaProps> =>\n Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined),\n ) as Partial<TextareaProps>;\n\n// Label above, helper text below — identical for the plain and rich variants,\n// which previously duplicated both.\nconst TextareaShell: React.FC<{\n testId?: string;\n label?: React.ReactNode;\n glassLabel: boolean;\n error: boolean;\n helperText?: React.ReactNode;\n children: React.ReactNode;\n}> = ({ testId, label, glassLabel, error, helperText, children }) => (\n <Box\n sx={{ position: 'relative', width: '100%' }}\n data-testid={testId ? `${testId}-wrapper` : undefined}\n >\n {label && (\n <StyledLabel glass={glassLabel} error={error}>\n {label}\n </StyledLabel>\n )}\n\n {children}\n\n {helperText && (\n <FormHelperText error={error} sx={{ mt: 1 }}>\n {helperText}\n </FormHelperText>\n )}\n </Box>\n);\n\nconst TextareaIcon: React.FC<{\n icon?: React.ReactNode;\n iconPosition: 'start' | 'end';\n}> = ({ icon, iconPosition }) => (\n <Box\n sx={{\n position: 'absolute',\n top: sxRem(12),\n ...(iconPosition === 'start' ? { left: sxRem(12) } : { right: sxRem(12) }),\n color: 'text.secondary',\n pointerEvents: 'none',\n zIndex: 1 }}\n >\n {icon}\n </Box>\n);\n\n/**\n * The rich variant, kept out of the main component's body.\n *\n * Two reasons rather than one: the `Suspense` boundary and its props belong\n * together with the lazy import above, and the component that renders every\n * OTHER variant stays inside the size the complexity gate allows without\n * anything being suppressed.\n */\nfunction RichVariant({\n shell,\n editor }: {\n shell: Omit<React.ComponentProps<typeof TextareaShell>, 'children'>;\n editor: React.ComponentProps<typeof TextareaRichEditor>;\n}): React.JSX.Element {\n return (\n <TextareaShell {...shell}>\n {/*\n `null` rather than a spinner: the editor resolves from the same document\n the caller is already rendering, so a fallback would flash for a frame\n and read as a glitch rather than as loading.\n */}\n <Suspense fallback={null}>\n <TextareaRichEditor {...editor} />\n </Suspense>\n </TextareaShell>\n );\n}\n\n// Same gap either side; only which side it applies to changes. The previous\n// version had `iconPosition === 'start' ? '40px' : '40px'`, a ternary whose\n// two branches were identical. The icon's gutter is 40px at the design scale.\nfunction withIconGutter(\n theme: Theme,\n style: React.CSSProperties | undefined,\n hasIcon: boolean,\n iconPosition: TextareaProps['iconPosition'],\n): React.CSSProperties {\n if (!hasIcon) return { ...style };\n return { ...style, [iconPosition === 'start' ? 'paddingLeft' : 'paddingRight']: rem(theme, 40) };\n}\n\nexport const Textarea: React.FC<TextareaProps> = (textareaProps) => {\n const {\n variant,\n color,\n size,\n error,\n helperText,\n label,\n glassLabel,\n glow,\n glass,\n gradient,\n icon,\n iconPosition,\n minRows,\n maxRows,\n style,\n 'data-testid': dataTestId,\n dataTestId: dataTestIdCamelCase,\n ...props\n } = { ...TEXTAREA_DEFAULTS, ...definedProps(textareaProps) };\n\n // Read off the props rather than the merged object: the spread widens every\n // key to optional, which would lose what the variant union already proved.\n const { richEditorCopy } = textareaProps;\n\n const theme = useTheme();\n const [richTextValue, setRichTextValue] = useState('');\n const hasIcon = Boolean(icon);\n const testId = dataTestId || dataTestIdCamelCase;\n\n const textareaStyle = withIconGutter(theme, style, hasIcon, iconPosition);\n\n // If rich text variant, use the rich text editor\n if (variant === 'rich' && richEditorCopy) {\n return (\n <RichVariant\n shell={{ testId, label, glassLabel, error, helperText }}\n editor={{\n copy: richEditorCopy,\n value: richTextValue,\n onChange: setRichTextValue,\n placeholder: props.placeholder,\n error,\n glass,\n color,\n characterLimit: props.maxLength }}\n />\n );\n }\n\n return (\n <TextareaShell testId={testId} label={label} glassLabel={glassLabel} error={error} helperText={helperText}>\n <Box sx={{ position: 'relative' }}>\n {hasIcon && <TextareaIcon icon={icon} iconPosition={iconPosition} />}\n\n <StyledTextarea\n customVariant={variant}\n customColor={color}\n customSize={size}\n glow={glow}\n glass={glass}\n gradient={gradient}\n error={error}\n minRows={minRows}\n maxRows={variant === 'autosize' ? maxRows : undefined}\n style={textareaStyle}\n aria-label={label || props['aria-label']}\n data-testid={testId}\n {...props}\n />\n </Box>\n </TextareaShell>\n );\n};\n\nTextarea.displayName = 'Textarea';\n"],"mappings":"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","names":[]}
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  SettingsRailGroup
3
- } from "./chunk-V5EWCJBT.js";
3
+ } from "./chunk-4BLVVMY7.js";
4
4
  import {
5
5
  TOUCH_TARGET,
6
6
  atLeastRail,
7
7
  displayAcrossRail,
8
+ railCardWidth,
8
9
  railWidth
9
- } from "./chunk-NYFNF7I5.js";
10
+ } from "./chunk-NK4T624E.js";
10
11
  import {
11
12
  rem,
12
13
  sxRem
@@ -101,6 +102,29 @@ function SettingsSearchEmpty({
101
102
  ) : null
102
103
  ] });
103
104
  }
105
+ function RailSearch({
106
+ query,
107
+ onQueryChange,
108
+ searchPlaceholder,
109
+ testIdPrefix
110
+ }) {
111
+ return /* @__PURE__ */ jsx(
112
+ TextField,
113
+ {
114
+ value: query,
115
+ onChange: (event) => onQueryChange(event.target.value),
116
+ placeholder: searchPlaceholder,
117
+ size: "small",
118
+ fullWidth: true,
119
+ "aria-label": searchPlaceholder,
120
+ "data-testid": `${testIdPrefix}-search`,
121
+ InputProps: {
122
+ startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx(SearchIcon, { fontSize: "small", sx: { color: "text.secondary" } }) })
123
+ },
124
+ sx: { mb: 2 }
125
+ }
126
+ );
127
+ }
104
128
  function SettingsRailBody({
105
129
  navOpen,
106
130
  query,
@@ -114,6 +138,7 @@ function SettingsRailBody({
114
138
  onSelectItem,
115
139
  onNavigate,
116
140
  testIdPrefix,
141
+ searchable,
117
142
  ...shape
118
143
  }) {
119
144
  const hidden = navOpen ? "block" : "none";
@@ -123,22 +148,15 @@ function SettingsRailBody({
123
148
  "data-testid": `${testIdPrefix}-rail-body`,
124
149
  sx: (theme) => shape.variant === "drilldown" ? { display: "block" } : displayAcrossRail(theme, shape.breakpoint, hidden, "block"),
125
150
  children: [
126
- /* @__PURE__ */ jsx(
127
- TextField,
151
+ searchable ? /* @__PURE__ */ jsx(
152
+ RailSearch,
128
153
  {
129
- value: query,
130
- onChange: (event) => onQueryChange(event.target.value),
131
- placeholder: searchPlaceholder,
132
- size: "small",
133
- fullWidth: true,
134
- "aria-label": searchPlaceholder,
135
- "data-testid": `${testIdPrefix}-search`,
136
- InputProps: {
137
- startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx(SearchIcon, { fontSize: "small", sx: { color: "text.secondary" } }) })
138
- },
139
- sx: { mb: 2 }
154
+ query,
155
+ onQueryChange,
156
+ searchPlaceholder,
157
+ testIdPrefix
140
158
  }
141
- ),
159
+ ) : null,
142
160
  filteredGroups.length === 0 ? /* @__PURE__ */ jsx(
143
161
  SettingsSearchEmpty,
144
162
  {
@@ -164,6 +182,23 @@ function SettingsRailBody({
164
182
  }
165
183
  );
166
184
  }
185
+ function railColumnSx(theme, railVariant) {
186
+ if (railVariant === "card") {
187
+ const width2 = railCardWidth(theme);
188
+ return {
189
+ flex: `0 0 ${width2}`,
190
+ width: width2,
191
+ alignSelf: "flex-start",
192
+ border: `1px solid ${theme.palette.divider}`,
193
+ borderRadius: sxRem(14),
194
+ bgcolor: "background.paper",
195
+ px: sxRem(12),
196
+ py: sxRem(16)
197
+ };
198
+ }
199
+ const width = railWidth(theme);
200
+ return { flex: `0 0 ${width}`, width, borderRight: `1px solid ${theme.palette.divider}`, pr: sxRem(16) };
201
+ }
167
202
  function SettingsRail({
168
203
  title,
169
204
  activeLabel,
@@ -171,6 +206,7 @@ function SettingsRail({
171
206
  onToggleNav,
172
207
  testIdPrefix,
173
208
  fillHeight = false,
209
+ railVariant = "divided",
174
210
  ...bodyProps
175
211
  }) {
176
212
  const { variant, breakpoint, atIndex } = bodyProps;
@@ -181,16 +217,14 @@ function SettingsRail({
181
217
  component: "nav",
182
218
  "aria-label": typeof title === "string" ? title : "Settings",
183
219
  "data-testid": `${testIdPrefix}-rail`,
220
+ "data-rail-variant": railVariant,
184
221
  sx: (theme) => ({
185
222
  display: hiddenWhileInSection ? "none" : "block",
186
223
  flex: "0 0 auto",
187
224
  width: "100%",
188
225
  [atLeastRail(theme, breakpoint)]: {
189
226
  display: "block",
190
- flex: `0 0 ${railWidth(theme)}`,
191
- width: railWidth(theme),
192
- borderRight: `1px solid ${theme.palette.divider}`,
193
- pr: 2,
227
+ ...railColumnSx(theme, railVariant),
194
228
  // Its own scrollbar, so a settings area with twenty categories does
195
229
  // not make the thing you NAVIGATE with scroll away while you read the
196
230
  // panel. `minHeight: 0` is the load-bearing half: without it a flex
@@ -233,4 +267,4 @@ function SettingsRail({
233
267
  export {
234
268
  SettingsRail
235
269
  };
236
- //# sourceMappingURL=chunk-TNYKM4UU.js.map
270
+ //# sourceMappingURL=chunk-SWQXAUUG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/layout/SettingsLayout/SettingsLayout.rail.tsx"],"sourcesContent":["'use client';\n\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\nimport SearchIcon from '@mui/icons-material/Search';\nimport Box from '@mui/material/Box/index.js';\nimport Button from '@mui/material/Button/index.js';\nimport InputAdornment from '@mui/material/InputAdornment/index.js';\nimport TextField from '@mui/material/TextField/index.js';\nimport type { Theme } from '@mui/material/styles/index.js';\nimport Typography from '@mui/material/Typography/index.js';\nimport React from 'react';\n\nimport { SettingsRailGroup, type RailShape } from './SettingsLayout.items';\nimport { atLeastRail, displayAcrossRail, railCardWidth, railWidth, TOUCH_TARGET } from './SettingsLayout.styles';\nimport { rem, sxRem } from '../../../tokens/relative';\nimport type {\n SettingsEmptySearchAction,\n SettingsLayoutProps,\n SettingsNavGroup,\n SettingsRailBreakpoint,\n SettingsRailVariant,\n} from './SettingsLayout.types';\n\ninterface RailToggleProps {\n title?: React.ReactNode;\n activeLabel?: string;\n open: boolean;\n onToggle: () => void;\n breakpoint: SettingsRailBreakpoint;\n testIdPrefix: string;\n}\n\n/**\n * `switcher`-only collapse control: shows the current section (a compact\n * switcher) so the panel content stays at the top of the screen. Hidden once the\n * rail has its own column.\n */\nfunction SettingsRailToggle({\n title,\n activeLabel,\n open,\n onToggle,\n breakpoint,\n testIdPrefix,\n}: RailToggleProps): React.JSX.Element {\n return (\n <Box\n component=\"button\"\n type=\"button\"\n onClick={onToggle}\n aria-expanded={open}\n aria-label={typeof title === 'string' ? title : 'Settings'}\n data-testid={`${testIdPrefix}-toggle`}\n sx={(theme) => ({\n ...displayAcrossRail(theme, breakpoint, 'flex', 'none'),\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 1,\n width: '100%',\n minHeight: rem(theme, TOUCH_TARGET),\n px: 1.5,\n py: 1,\n mb: 1,\n textAlign: 'left',\n cursor: 'pointer',\n color: 'text.primary',\n background: 'transparent',\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: 1.5,\n })}\n >\n <Box sx={{ minWidth: 0 }}>\n {title ? (\n <Typography variant=\"caption\" sx={{ display: 'block', color: 'text.secondary' }}>\n {title}\n </Typography>\n ) : null}\n <Typography variant=\"body2\" noWrap sx={{ fontWeight: 600 }}>\n {activeLabel ?? ''}\n </Typography>\n </Box>\n <ExpandMoreIcon\n fontSize=\"small\"\n sx={{\n flex: '0 0 auto',\n color: 'text.secondary',\n transition: 'transform 150ms ease',\n transform: open ? 'rotate(180deg)' : 'none',\n '@media (prefers-reduced-motion: reduce)': { transition: 'none' },\n }}\n />\n </Box>\n );\n}\n\n/** The empty-search state, with the way out of it rendered inside. */\nfunction SettingsSearchEmpty({\n label,\n action,\n onClear,\n testIdPrefix,\n}: {\n label: React.ReactNode;\n action?: SettingsEmptySearchAction;\n onClear: () => void;\n testIdPrefix: string;\n}): React.JSX.Element {\n return (\n <Box data-testid={`${testIdPrefix}-empty`} sx={{ px: 1, py: 2 }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {label}\n </Typography>\n {action ? (\n <Button\n size=\"small\"\n variant=\"outlined\"\n onClick={() => {\n onClear();\n action.onClear?.();\n }}\n data-testid={`${testIdPrefix}-empty-action`}\n sx={{ mt: 1.5, minHeight: sxRem(TOUCH_TARGET) }}\n >\n {action.label}\n </Button>\n ) : null}\n </Box>\n );\n}\n\nexport interface RailBodyProps extends RailShape {\n navOpen: boolean;\n query: string;\n onQueryChange: (value: string) => void;\n searchPlaceholder: string;\n emptySearchLabel: React.ReactNode;\n emptySearchAction?: SettingsEmptySearchAction;\n filteredGroups: SettingsNavGroup[];\n activeItemId?: string;\n linkComponent?: SettingsLayoutProps['linkComponent'];\n onSelectItem?: (id: string) => void;\n onNavigate?: () => void;\n testIdPrefix: string;\n /** Whether the search field is drawn (`SettingsLayoutProps.searchable`). */\n searchable: boolean;\n}\n\n/** The rail's search field. */\nfunction RailSearch({\n query,\n onQueryChange,\n searchPlaceholder,\n testIdPrefix,\n}: Pick<RailBodyProps, 'query' | 'onQueryChange' | 'searchPlaceholder' | 'testIdPrefix'>): React.JSX.Element {\n return (\n <TextField\n value={query}\n onChange={(event) => onQueryChange(event.target.value)}\n placeholder={searchPlaceholder}\n size=\"small\"\n fullWidth\n aria-label={searchPlaceholder}\n data-testid={`${testIdPrefix}-search`}\n InputProps={{\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchIcon fontSize=\"small\" sx={{ color: 'text.secondary' }} />\n </InputAdornment>\n ),\n }}\n sx={{ mb: 2 }}\n />\n );\n}\n\n/** The rail body: the search field when the area has one, then the groups. */\nfunction SettingsRailBody({\n navOpen,\n query,\n onQueryChange,\n searchPlaceholder,\n emptySearchLabel,\n emptySearchAction,\n filteredGroups,\n activeItemId,\n linkComponent,\n onSelectItem,\n onNavigate,\n testIdPrefix,\n searchable,\n ...shape\n}: RailBodyProps): React.JSX.Element {\n // `drilldown` has no disclosure to be closed behind: below the breakpoint the\n // body is the page, above it the rail. Only `switcher` hides it.\n const hidden = navOpen ? 'block' : 'none';\n return (\n <Box\n data-testid={`${testIdPrefix}-rail-body`}\n sx={(theme) =>\n shape.variant === 'drilldown'\n ? { display: 'block' }\n : displayAcrossRail(theme, shape.breakpoint, hidden, 'block')\n }\n >\n {searchable ? (\n <RailSearch\n query={query}\n onQueryChange={onQueryChange}\n searchPlaceholder={searchPlaceholder}\n testIdPrefix={testIdPrefix}\n />\n ) : null}\n {filteredGroups.length === 0 ? (\n <SettingsSearchEmpty\n label={emptySearchLabel}\n action={emptySearchAction}\n onClear={() => onQueryChange('')}\n testIdPrefix={testIdPrefix}\n />\n ) : (\n filteredGroups.map((group) => (\n <SettingsRailGroup\n key={group.id}\n group={group}\n activeItemId={activeItemId}\n linkComponent={linkComponent}\n onSelectItem={onSelectItem}\n onNavigate={onNavigate}\n testIdPrefix={testIdPrefix}\n {...shape}\n />\n ))\n )}\n </Box>\n );\n}\n\n/** Props for {@link SettingsRail}: the rail body's inputs plus the mobile chrome. */\nexport type SettingsRailProps = RailBodyProps & {\n title?: React.ReactNode;\n activeLabel?: string;\n onToggleNav: () => void;\n /** Scroll inside the rail rather than with the page. See `fillHeight`. */\n fillHeight?: boolean;\n /** How the rail's own column is drawn. See `SettingsLayoutProps.railVariant`. */\n railVariant?: SettingsRailVariant;\n};\n\n/** The rail's own column, as the variant draws it: ruled off, or a card. */\nfunction railColumnSx(theme: Theme, railVariant: SettingsRailVariant): Record<string, unknown> {\n if (railVariant === 'card') {\n const width = railCardWidth(theme);\n return {\n flex: `0 0 ${width}`,\n width,\n alignSelf: 'flex-start',\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: sxRem(14),\n bgcolor: 'background.paper',\n px: sxRem(12),\n py: sxRem(16),\n };\n }\n const width = railWidth(theme);\n return { flex: `0 0 ${width}`, width, borderRight: `1px solid ${theme.palette.divider}`, pr: sxRem(16) };\n}\n\n/** The navigation column: title, the `switcher`'s disclosure, and the body. */\nexport function SettingsRail({\n title,\n activeLabel,\n navOpen,\n onToggleNav,\n testIdPrefix,\n fillHeight = false,\n railVariant = 'divided',\n ...bodyProps\n}: SettingsRailProps): React.JSX.Element {\n const { variant, breakpoint, atIndex } = bodyProps;\n // In `drilldown` the rail is the index's list below the breakpoint and the\n // left column above it — so inside a section it steps aside for the chip\n // strip. It is `display: none`, never unmounted: the two navigation forms\n // both stay in the DOM at every width, which is what makes \"the narrow width\n // offers what the wide one offers\" true by construction instead of by review.\n const hiddenWhileInSection = variant === 'drilldown' && !atIndex;\n\n return (\n <Box\n component=\"nav\"\n aria-label={typeof title === 'string' ? title : 'Settings'}\n data-testid={`${testIdPrefix}-rail`}\n data-rail-variant={railVariant}\n sx={(theme) => ({\n display: hiddenWhileInSection ? 'none' : 'block',\n flex: '0 0 auto',\n width: '100%',\n [atLeastRail(theme, breakpoint)]: {\n display: 'block',\n ...railColumnSx(theme, railVariant),\n // Its own scrollbar, so a settings area with twenty categories does\n // not make the thing you NAVIGATE with scroll away while you read the\n // panel. `minHeight: 0` is the load-bearing half: without it a flex\n // child refuses to shrink below its content and `overflow` never\n // engages.\n ...(fillHeight\n ? { height: '100%', minHeight: 0, overflowY: 'auto' as const, overscrollBehavior: 'contain' as const }\n : {}),\n },\n })}\n >\n {title ? (\n <Typography\n variant=\"h6\"\n data-testid={`${testIdPrefix}-title`}\n sx={(theme) => ({\n ...(variant === 'drilldown'\n ? { display: 'block' }\n : displayAcrossRail(theme, breakpoint, 'none', 'block')),\n fontWeight: 700,\n mb: 1.5,\n })}\n >\n {title}\n </Typography>\n ) : null}\n {variant === 'switcher' ? (\n <SettingsRailToggle\n title={title}\n activeLabel={activeLabel}\n open={navOpen}\n onToggle={onToggleNav}\n breakpoint={breakpoint}\n testIdPrefix={testIdPrefix}\n />\n ) : null}\n <SettingsRailBody navOpen={navOpen} testIdPrefix={testIdPrefix} {...bodyProps} />\n </Box>\n );\n}\n"],"mappings":"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","names":["width"]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  TOUCH_TARGET,
3
3
  displayAcrossRail
4
- } from "./chunk-NYFNF7I5.js";
4
+ } from "./chunk-NK4T624E.js";
5
5
  import {
6
6
  rem,
7
7
  sxRem
@@ -122,4 +122,4 @@ function SettingsSectionHeader({
122
122
  export {
123
123
  SettingsSectionHeader
124
124
  };
125
- //# sourceMappingURL=chunk-6KEXHOIF.js.map
125
+ //# sourceMappingURL=chunk-WOXNVM52.js.map
@@ -1,7 +1,7 @@
1
1
  import "../chunk-BH5GSBR3.js";
2
2
  import {
3
3
  Textarea
4
- } from "../chunk-X47MWURD.js";
4
+ } from "../chunk-Q6MZHT2F.js";
5
5
  import "../chunk-IPC426NS.js";
6
6
  import "../chunk-RGVNXES5.js";
7
7
  import "../chunk-GDN2LUTZ.js";