@wildo-ai/presets-components 1.1.1 → 1.1.2

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 (100) hide show
  1. package/dist/esm/components/actions/action-button.d.ts +1 -4
  2. package/dist/esm/components/actions/action-button.d.ts.map +1 -1
  3. package/dist/esm/components/actions/action-button.js +21 -5
  4. package/dist/esm/components/actions/action-button.js.map +1 -1
  5. package/dist/esm/components/ai-elements/artifacts/artifact-browser.d.ts.map +1 -1
  6. package/dist/esm/components/ai-elements/artifacts/artifact-browser.js +7 -3
  7. package/dist/esm/components/ai-elements/artifacts/artifact-browser.js.map +1 -1
  8. package/dist/esm/components/ai-elements/execution/task.d.ts.map +1 -1
  9. package/dist/esm/components/ai-elements/execution/task.js +10 -2
  10. package/dist/esm/components/ai-elements/execution/task.js.map +1 -1
  11. package/dist/esm/components/app/app-layout-main-container.labels.d.ts.map +1 -1
  12. package/dist/esm/components/app/app-layout-main-container.labels.js +10 -2
  13. package/dist/esm/components/app/app-layout-main-container.labels.js.map +1 -1
  14. package/dist/esm/components/app/public-layout-main-container.d.ts.map +1 -1
  15. package/dist/esm/components/app/public-layout-main-container.js +52 -5
  16. package/dist/esm/components/app/public-layout-main-container.js.map +1 -1
  17. package/dist/esm/components/data-display/description-list.d.ts.map +1 -1
  18. package/dist/esm/components/data-display/description-list.js +10 -7
  19. package/dist/esm/components/data-display/description-list.js.map +1 -1
  20. package/dist/esm/components/data-display/formatters/display-field-string.d.ts.map +1 -1
  21. package/dist/esm/components/data-display/formatters/display-field-string.js +3 -0
  22. package/dist/esm/components/data-display/formatters/display-field-string.js.map +1 -1
  23. package/dist/esm/components/form/chromes/form-primitive.labels.js +2 -2
  24. package/dist/esm/components/form/chromes/form-primitive.labels.js.map +1 -1
  25. package/dist/esm/components/navigation/app-level/menu-user-org.d.ts.map +1 -1
  26. package/dist/esm/components/navigation/app-level/menu-user-org.js +8 -2
  27. package/dist/esm/components/navigation/app-level/menu-user-org.js.map +1 -1
  28. package/dist/esm/components/navigation/app-level/sidebar.d.ts.map +1 -1
  29. package/dist/esm/components/navigation/app-level/sidebar.js +32 -15
  30. package/dist/esm/components/navigation/app-level/sidebar.js.map +1 -1
  31. package/dist/esm/components/overlays/containers/sheet.d.ts.map +1 -1
  32. package/dist/esm/components/overlays/containers/sheet.js +2 -2
  33. package/dist/esm/components/overlays/containers/sheet.js.map +1 -1
  34. package/dist/esm/components/sections/accordion.d.ts.map +1 -1
  35. package/dist/esm/components/sections/accordion.js +43 -13
  36. package/dist/esm/components/sections/accordion.js.map +1 -1
  37. package/dist/esm/components/sections/collapsible.d.ts.map +1 -1
  38. package/dist/esm/components/sections/collapsible.js +17 -3
  39. package/dist/esm/components/sections/collapsible.js.map +1 -1
  40. package/dist/esm/components/sections/content-section.d.ts.map +1 -1
  41. package/dist/esm/components/sections/content-section.js +11 -7
  42. package/dist/esm/components/sections/content-section.js.map +1 -1
  43. package/dist/esm/components/sections/disclosure-nesting.d.ts +20 -0
  44. package/dist/esm/components/sections/disclosure-nesting.d.ts.map +1 -0
  45. package/dist/esm/components/sections/disclosure-nesting.js +20 -0
  46. package/dist/esm/components/sections/disclosure-nesting.js.map +1 -0
  47. package/dist/esm/components/sections/tabs.d.ts.map +1 -1
  48. package/dist/esm/components/sections/tabs.js +141 -10
  49. package/dist/esm/components/sections/tabs.js.map +1 -1
  50. package/dist/esm/config/preset-kits.d.ts.map +1 -1
  51. package/dist/esm/config/preset-kits.js +0 -4
  52. package/dist/esm/config/preset-kits.js.map +1 -1
  53. package/dist/esm/config/preset-shell.d.ts.map +1 -1
  54. package/dist/esm/config/preset-shell.js +0 -4
  55. package/dist/esm/config/preset-shell.js.map +1 -1
  56. package/dist/esm/config/presets.d.ts.map +1 -1
  57. package/dist/esm/config/presets.js +0 -1
  58. package/dist/esm/config/presets.js.map +1 -1
  59. package/dist/esm/config/resources/application.resource-presets.d.ts.map +1 -1
  60. package/dist/esm/config/resources/application.resource-presets.js +6 -6
  61. package/dist/esm/config/resources/application.resource-presets.js.map +1 -1
  62. package/dist/esm/config/resources/billing.resource-presets.d.ts.map +1 -1
  63. package/dist/esm/config/resources/billing.resource-presets.js +8 -8
  64. package/dist/esm/config/resources/billing.resource-presets.js.map +1 -1
  65. package/dist/esm/config/resources/guidance.resource-presets.d.ts.map +1 -1
  66. package/dist/esm/config/resources/guidance.resource-presets.js +7 -7
  67. package/dist/esm/config/resources/guidance.resource-presets.js.map +1 -1
  68. package/dist/esm/config/resources/identity.resource-presets.d.ts.map +1 -1
  69. package/dist/esm/config/resources/identity.resource-presets.js +7 -7
  70. package/dist/esm/config/resources/identity.resource-presets.js.map +1 -1
  71. package/dist/esm/config/resources/organizations.resource-presets.d.ts.map +1 -1
  72. package/dist/esm/config/resources/organizations.resource-presets.js +8 -8
  73. package/dist/esm/config/resources/organizations.resource-presets.js.map +1 -1
  74. package/dist/esm/config/resources/security.resource-presets.d.ts.map +1 -1
  75. package/dist/esm/config/resources/security.resource-presets.js +9 -9
  76. package/dist/esm/config/resources/security.resource-presets.js.map +1 -1
  77. package/dist/esm/themes/cozy.theme.d.ts.map +1 -1
  78. package/dist/esm/themes/cozy.theme.js +8 -3
  79. package/dist/esm/themes/cozy.theme.js.map +1 -1
  80. package/dist/esm/themes/dense.theme.d.ts.map +1 -1
  81. package/dist/esm/themes/dense.theme.js +8 -5
  82. package/dist/esm/themes/dense.theme.js.map +1 -1
  83. package/dist/esm/themes/editorial.theme.d.ts.map +1 -1
  84. package/dist/esm/themes/editorial.theme.js +8 -3
  85. package/dist/esm/themes/editorial.theme.js.map +1 -1
  86. package/dist/esm/themes/glass.theme.d.ts.map +1 -1
  87. package/dist/esm/themes/glass.theme.js +10 -4
  88. package/dist/esm/themes/glass.theme.js.map +1 -1
  89. package/dist/esm/themes/neo-brutalist.theme.d.ts.map +1 -1
  90. package/dist/esm/themes/neo-brutalist.theme.js +8 -3
  91. package/dist/esm/themes/neo-brutalist.theme.js.map +1 -1
  92. package/dist/esm/themes/terminal.theme.d.ts.map +1 -1
  93. package/dist/esm/themes/terminal.theme.js +8 -3
  94. package/dist/esm/themes/terminal.theme.js.map +1 -1
  95. package/dist/esm/themes/trading.theme.d.ts.map +1 -1
  96. package/dist/esm/themes/trading.theme.js +8 -3
  97. package/dist/esm/themes/trading.theme.js.map +1 -1
  98. package/dist/tsconfig.build.tsbuildinfo +1 -1
  99. package/package.json +7 -7
  100. package/dist/esm/.builder.pid +0 -9
@@ -1 +1 @@
1
- {"version":3,"file":"collapsible.js","sourceRoot":"","sources":["../../../../../src/components/sections/collapsible.tsx"],"names":[],"mappings":";AACA,OAAO,KAAK,oBAAoB,MAAM,6BAA6B,CAAA;AAEnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAGlE,SAAS,eAAe,CAAC,EACvB,GAAG,KAAK,EAC+C;IACvD,OAAO,KAAC,oBAAoB,CAAC,IAAI,iBAAW,aAAa,KAAK,KAAK,GAAI,CAAA;AACzE,CAAC;AAED,SAAS,kBAAkB,CAAC,EAC1B,GAAG,KAAK,EAC6D;IACrE,OAAO,CACL,KAAC,oBAAoB,CAAC,kBAAkB,iBAC5B,qBAAqB,KAC3B,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,EAC1B,GAAG,KAAK,EAC6D;IACrE,OAAO,CACL,KAAC,oBAAoB,CAAC,kBAAkB,iBAC5B,qBAAqB,KAC3B,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,oBAAoB,CAAsB,eAAe,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAA","sourcesContent":["import * as React from \"react\"\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\"\nimport type { CollapsibleCompound } from '@wildo-ai/saas-frontend-lib'\nimport { createCompoundPreset } from \"@wildo-ai/saas-frontend-lib\"\nimport { FrontendComponentType } from \"@wildo-ai/presets-components-models\"\n\nfunction CollapsibleRoot({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.Root>): React.JSX.Element {\n return <CollapsiblePrimitive.Root data-slot=\"collapsible\" {...props} />\n}\n\nfunction CollapsibleTrigger({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>): React.JSX.Element {\n return (\n <CollapsiblePrimitive.CollapsibleTrigger\n data-slot=\"collapsible-trigger\"\n {...props}\n />\n )\n}\n\nfunction CollapsibleContent({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>): React.JSX.Element {\n return (\n <CollapsiblePrimitive.CollapsibleContent\n data-slot=\"collapsible-content\"\n {...props}\n />\n )\n}\n\nexport const Collapsible = createCompoundPreset<CollapsibleCompound>(CollapsibleRoot, { Trigger: CollapsibleTrigger, Content: CollapsibleContent })\n"]}
1
+ {"version":3,"file":"collapsible.js","sourceRoot":"","sources":["../../../../../src/components/sections/collapsible.tsx"],"names":[],"mappings":";AACA,OAAO,KAAK,oBAAoB,MAAM,6BAA6B,CAAA;AAEnE,OAAO,EAAE,oBAAoB,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAA;AAEtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AAE/D,SAAS,eAAe,CAAC,EACvB,GAAG,KAAK,EAC+C;IACvD,OAAO,KAAC,oBAAoB,CAAC,IAAI,iBAAW,aAAa,KAAK,KAAK,GAAI,CAAA;AACzE,CAAC;AAED,SAAS,kBAAkB,CAAC,EAC1B,GAAG,KAAK,EAC6D;IACrE,OAAO,CACL,KAAC,oBAAoB,CAAC,kBAAkB,iBAC5B,qBAAqB,KAC3B,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,GAAG,KAAK,EAC6D;IACrE,OAAO;IACL;;;;;;;;;;;OAWG;IACH,KAAC,wBAAwB,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,YAiB5C,KAAC,oBAAoB,CAAC,kBAAkB,iBAC5B,qBAAqB,EAC/B,SAAS,EAAE,EAAE,CACX,mGAAmG,EACnG,SAAS,CACV,KACG,KAAK,GACT,GACgC,CACrC,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,oBAAoB,CAAsB,eAAe,EAAE,EAAE,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAA","sourcesContent":["import * as React from \"react\"\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\"\nimport type { CollapsibleCompound } from '@wildo-ai/saas-frontend-lib'\nimport { createCompoundPreset, cn } from \"@wildo-ai/saas-frontend-lib\"\nimport { FrontendComponentType } from \"@wildo-ai/presets-components-models\"\nimport { DisclosureNestingContext } from \"./disclosure-nesting\"\n\nfunction CollapsibleRoot({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.Root>): React.JSX.Element {\n return <CollapsiblePrimitive.Root data-slot=\"collapsible\" {...props} />\n}\n\nfunction CollapsibleTrigger({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>): React.JSX.Element {\n return (\n <CollapsiblePrimitive.CollapsibleTrigger\n data-slot=\"collapsible-trigger\"\n {...props}\n />\n )\n}\n\nfunction CollapsibleContent({\n className,\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>): React.JSX.Element {\n return (\n /*\n * A collapsible panel is a disclosure panel: anything nesting-aware below it (today, an\n * Accordion) reads this fact and applies the themed nesting guide. Providing the fact is not\n * styling — this component stays headless.\n *\n * The provider wraps OUTSIDE the primitive, deliberately. Wrapping `children` INSIDE it shipped\n * a crash: with `asChild` (AI_PlanContent does exactly this) Radix's Slot merges its props and\n * measuring ref onto the single child element — which had become the Provider, not a DOM\n * element — so the ref resolved to nothing and `ResizeObserver.observe()` threw \"parameter 1 is\n * not of type 'Element'\". Context reaches descendants identically from out here, and the\n * children slot stays exactly what the caller authored.\n */\n <DisclosureNestingContext.Provider value={true}>\n {/*\n * The panel ANIMATES its height open and closed, which it did not until 2026-09-02: the\n * trigger's chevron rotated over 200ms and the content it revealed appeared instantly, so a\n * fold read as a jump and a reader lost track of what had moved.\n *\n * Same idiom as the sibling `AccordionContent`, deliberately — both are disclosure panels\n * and there is no reason for one to move and the other to snap. The keyframes come from\n * `tw-animate-css` (which an application already imports for every overlay transition) and\n * interpolate `--radix-collapsible-content-height`, the variable Radix measures onto the\n * element; `overflow-hidden` is what makes an interpolated height clip rather than spill.\n *\n * `className` is destructured only so the animation can MERGE with a caller's classes\n * (`content-section` passes `space-y-field p-card pt-0` here). It was never dropped — the\n * previous `{...props}` spread forwarded it — so this is not a fix, just what merging\n * requires.\n */}\n <CollapsiblePrimitive.CollapsibleContent\n data-slot=\"collapsible-content\"\n className={cn(\n 'overflow-hidden data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down',\n className,\n )}\n {...props}\n />\n </DisclosureNestingContext.Provider>\n )\n}\n\nexport const Collapsible = createCompoundPreset<CollapsibleCompound>(CollapsibleRoot, { Trigger: CollapsibleTrigger, Content: CollapsibleContent })\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"content-section.d.ts","sourceRoot":"","sources":["../../../../../src/components/sections/content-section.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAYL,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC/B,MAAM,6BAA6B,CAAC;AAKrC;;;;GAIG;AACH,iBAAS,oBAAoB,CAAC,EAC5B,SAAS,EACT,OAAkB,EAClB,GAAG,KAAK,EACT,EAAE,yBAAyB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAc/C;AAED;;;;;GAKG;AACH,iBAAS,mBAAmB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,wBAAwB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAWjG;AAiBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,iBAAS,cAAc,CAAC,EACtB,SAAS,EACT,UAAgC,EAChC,MAAM,EACN,WAAW,EACX,WAAkB,EAClB,QAAQ,EACR,KAAa,EACb,IAAI,EACJ,UAAU,EACV,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,mBAAmB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAuQzC;AAED,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,CAAA"}
1
+ {"version":3,"file":"content-section.d.ts","sourceRoot":"","sources":["../../../../../src/components/sections/content-section.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAYL,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC/B,MAAM,6BAA6B,CAAC;AAKrC;;;;GAIG;AACH,iBAAS,oBAAoB,CAAC,EAC5B,SAAS,EACT,OAAkB,EAClB,GAAG,KAAK,EACT,EAAE,yBAAyB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAc/C;AAED;;;;;GAKG;AACH,iBAAS,mBAAmB,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,wBAAwB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAWjG;AAiBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,iBAAS,cAAc,CAAC,EACtB,SAAS,EACT,UAAgC,EAChC,MAAM,EACN,WAAW,EACX,WAAkB,EAClB,QAAQ,EACR,KAAa,EACb,IAAI,EACJ,UAAU,EACV,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,mBAAmB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAkRzC;AAED,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,CAAA"}
@@ -120,14 +120,18 @@ function ContentSection({ className, appearance = SectionMode.DEFAULT, legend, d
120
120
  ? props.style
121
121
  : { borderWidth: 0, background: 'transparent', boxShadow: 'none', borderRadius: 0, padding: 0, ...props.style }, children: [hasHeading && (_jsxs("div", { className: isCardEach ? 'p-card border-b' : 'space-y-item-xs', children: [(legend != null || icon != null) && (_jsxs(Heading, { level: headingLevel, className: "text-base font-semibold", children: [icon != null && _jsx("span", { className: "me-element inline-flex items-center", children: icon }), legend] })), description != null && _jsx(Text, { variant: TextVariant.MUTED, size: TextSize.SM, children: description })] })), _jsx("div", { className: isCardEach ? 'p-card' : undefined, children: children })] }) }));
122
122
  }
123
- // COLLAPSIBLE — toggle with the legend as the clickable trigger. Plain div (no
124
- // Surface/frame), matching the prior Section.tsx behavior exactly.
123
+ // COLLAPSIBLE — toggle with the legend as the clickable trigger, framed as a CARD
124
+ // (decided 2026-08-31; it was a flat div first). A fold needs a boundary: the closed
125
+ // header must read as an affordance with an extent, and an open one must say where its
126
+ // content ends — a frameless collapsed row was indistinguishable from a plain heading.
127
+ // Item-level content inside stays UNframed (the display pipeline's entry items draw a
128
+ // left accent line, not a card), so the frame stays the SECTION's alone.
125
129
  if (appearance === SectionMode.COLLAPSIBLE) {
126
- return (_jsx(Collapsible, { defaultOpen: defaultOpen, children: _jsxs("div", { className: cn('space-y-field', className), ...divPassthrough, children: [structuredLegend && (
127
- // No `asChild` + raw <button>: Radix's CollapsibleTrigger renders its
128
- // own <button data-slot="collapsible-trigger"> — the framework element,
129
- // no bespoke button chrome to add.
130
- _jsxs(CollapsibleTrigger, { className: "flex w-full items-center justify-between text-left", children: [structuredLegend, _jsx(CollapsibleChevron, {})] })), structuredDescription, _jsx(CollapsibleContent, { children: children })] }) }));
130
+ return (_jsx(Collapsible, { defaultOpen: defaultOpen, children: _jsx(Surface, { asChild: true, emitPolicyVars: false, variant: SurfaceVariant.CARD, policyOverride: { nesting: { framingMode: 'always' } }, children: _jsxs("div", { className: cn(cardRecipe.base, className), ...divPassthrough, children: [structuredLegend && (
131
+ // No `asChild` + raw <button>: Radix's CollapsibleTrigger renders its
132
+ // own <button data-slot="collapsible-trigger"> — the framework element,
133
+ // no bespoke button chrome to add.
134
+ _jsxs(CollapsibleTrigger, { className: "flex w-full items-center justify-between p-card text-left", children: [structuredLegend, _jsx(CollapsibleChevron, {})] })), structuredDescription && _jsx("div", { className: "px-card pb-card-sm", children: structuredDescription }), _jsx(CollapsibleContent, { className: "space-y-field p-card pt-0", children: children })] }) }) }));
131
135
  }
132
136
  // GHOST — flat div, no fieldset/frame. The form-level <fieldset> (Form.tsx)
133
137
  // already owns the disabled cascade, so a flat section loses nothing.
@@ -1 +1 @@
1
- {"version":3,"file":"content-section.js","sourceRoot":"","sources":["../../../../../src/components/sections/content-section.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from \"react\"\n\nimport {\n cn,\n useUI,\n useIconRegistry,\n StandardIconReference,\n IconSize,\n Surface,\n Heading,\n Text,\n Collapsible,\n CollapsibleTrigger,\n CollapsibleContent,\n type ContentSectionProps,\n type ContentSectionGroupProps,\n type ContentSectionLegendProps,\n} from '@wildo-ai/saas-frontend-lib';\n\nimport { SectionMode } from \"@wildo-ai/zod-decorators\"\nimport { SurfaceVariant, UIBehavior, TextVariant, TextSize } from \"@wildo-ai/presets-components-models\"\n\n/**\n * ContentSectionLegend preset — section heading. DOM-identical to the legacy\n * FieldLegend preset (`data-slot=\"field-legend\"` + classes) so existing CSS and\n * the `FieldDescription` legend-adjacency rule keep working unchanged.\n */\nfunction ContentSectionLegend({\n className,\n variant = \"legend\",\n ...props\n}: ContentSectionLegendProps): React.JSX.Element {\n return (\n <legend\n data-slot=\"field-legend\"\n data-variant={variant}\n className={cn(\n \"mb-field-sm font-medium\",\n \"data-[variant=legend]:text-base\",\n \"data-[variant=label]:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\n/**\n * ContentSectionGroup preset — child-grouping container. DOM-identical to the\n * legacy FieldGroup preset (`data-slot=\"field-group\"`, `@container/field-group`,\n * `group/field-group`) so the responsive `Field` orientation + `FieldSeparator`\n * selectors keyed off those container/group names keep resolving.\n */\nfunction ContentSectionGroup({ className, ...props }: ContentSectionGroupProps): React.JSX.Element {\n return (\n <div\n data-slot=\"field-group\"\n className={cn(\n \"group/field-group @container/field-group flex w-full flex-col gap-section-lg data-[slot=checkbox-group]:gap-field-sm [&>[data-slot=field-group]]:gap-field\",\n className\n )}\n {...props}\n />\n )\n}\n\n/**\n * Collapsible heading chevron — rendered through the icon registry\n * (`StandardIconReference.CHEVRON_DOWN`) instead of a hand-drawn `<svg>`, so it\n * tracks the app's icon set. The `[[data-state=open]_&]` selector rotates it\n * when the ancestor `CollapsibleTrigger` is open (Radix sets `data-state=open`).\n */\nfunction CollapsibleChevron(): React.ReactNode {\n const { renderIcon } = useIconRegistry();\n return renderIcon(StandardIconReference.CHEVRON_DOWN, {\n size: IconSize.SM,\n className:\n \"shrink-0 text-muted-foreground transition-transform duration-200 [[data-state=open]_&]:rotate-180\",\n });\n}\n\n/**\n * ContentSection preset — the section chrome workhorse.\n *\n * DEFAULT / CARD: ported verbatim from the FieldSet preset — a `<Surface>`-wrapped\n * native `<fieldset>` (the `disabled` cascade carrier) with the `when-orphan`\n * frame de-duplication, the inter-field `gap-field` ownership + checkbox/radio +\n * settings-row flush exceptions, and truthful SurfacePolicy publication\n * (`framingMode` = `when-orphan` for framed modes, `never` for flat). DOM is\n * byte-identical to the old FieldSet (`data-slot=\"field-set\"`), so there is no\n * CSS / visual / test regression by construction.\n *\n * GHOST: a flat `<div>` (no fieldset/frame), and COLLAPSIBLE: a `Collapsible`\n * toggle with the legend as the clickable trigger — both ported from the\n * hand-branched solo-mode logic that used to live in `Section.tsx`, so all four\n * solo appearances now flow through this one primitive.\n *\n * `legend` / `description` are structured props (rendered in the mode-appropriate\n * position). When omitted, the imperative composite/record/array sites pass\n * `<ContentSectionLegend>` / `<ContentSectionGroup>` as children instead — both\n * shapes produce the same fieldset DOM for DEFAULT.\n */\nfunction ContentSection({\n className,\n appearance = SectionMode.DEFAULT,\n legend,\n description,\n defaultOpen = true,\n disabled,\n panel = false,\n icon,\n headingTag,\n children,\n ...props\n}: ContentSectionProps): React.JSX.Element {\n const { getRecipe } = useUI();\n // CARD sections paint the active theme's CARD recipe — an elevated\n // `surface-raised` fill + border (or a translucent liquid-glass tile under the\n // glass theme). Resolved once per render.\n const cardRecipe = getRecipe(UIBehavior.SURFACE, SurfaceVariant.CARD);\n // Stable id for the CARD group heading ↔ fieldset `aria-labelledby` wiring.\n // Called unconditionally (hooks rule) even though only the CARD branch uses it.\n const reactId = React.useId();\n\n // CARD body full-bleed detection. A CARD whose body hosts SETTINGS_ROW\n // list-items drops its inline padding so each row's `border-b` divider runs\n // corner-to-corner; free-form content keeps `p-card`. The natural expression\n // is a CSS `has-[>[data-chrome-mode=settings_row]]:p-0` variant, but that is a\n // NET-NEW arbitrary-variant class string, and Tailwind v4 only scans engine\n // `@source` dirs at dev-server STARTUP — so a new variant class does not\n // compile on hot-reload (only on a full restart / production build). To stay\n // reliable on every reload we instead detect the settings-row children at\n // runtime and toggle between ALREADY-EMITTED utilities (`p-0`/`p-card`). The\n // effect runs each commit with a change-guard (no re-render loop); `bodyRef`\n // is null for the non-CARD branches, so this is inert there.\n const cardBodyRef = React.useRef<HTMLDivElement>(null);\n const [cardBodyIsSettingsList, setCardBodyIsSettingsList] = React.useState(false);\n React.useLayoutEffect(() => {\n const el = cardBodyRef.current;\n const next = !!el && !!el.querySelector(':scope > [data-chrome-mode=\"settings_row\"]');\n setCardBodyIsSettingsList((prev) => (prev === next ? prev : next));\n });\n\n // Explicit CARD sections — solo AND container-panel `card-each` — ALWAYS paint\n // their themed card chrome (elevated fill + border). The `when-orphan` frame\n // de-dup is intentionally NOT applied to an authored card: the author chose a\n // card, so it stays a card in every context (dialog, page, nested). DEFAULT /\n // GHOST stay flat; COLLAPSIBLE is its own toggle.\n\n // GHOST / COLLAPSIBLE render a <div>, not a <fieldset>. `props` is typed for a\n // fieldset (ref/form/name); the only passthrough the section render sites use\n // on these modes is data-*/aria-*/className, all valid on a div — so narrow the\n // type for the div branches. (The <fieldset> branch keeps the full fieldset props.)\n const divPassthrough = props as unknown as React.HTMLAttributes<HTMLDivElement>;\n\n const structuredLegend =\n legend != null && legend !== false ? <ContentSectionLegend>{legend}</ContentSectionLegend> : null;\n const structuredDescription =\n description != null && description !== false ? (\n <Text variant={TextVariant.MUTED} size={TextSize.SM}>{description}</Text>\n ) : null;\n\n // CONTAINER-PANEL chrome (ContentSectionContainer's tabs/grid/accordion/… panels).\n // Renders a heading element (not a <legend>) with a header-bar/divider layout.\n // Per appearance: CARD = card-each, which paints the SAME themed card chrome as\n // a solo CARD section (the elevated `surface-raised` fill + border + radius from\n // the active theme's CARD recipe), ALWAYS — so a grid/columns of cards reads as\n // distinct cards in every context; DEFAULT = flat. Stays a <fieldset> so the\n // disabled cascade applies — the consolidation that lets container panels share\n // the section primitive. Heading omitted entirely when there is no title/icon/\n // description (content-only panels, e.g. tab bodies whose heading is the tab).\n if (panel) {\n // Semantic heading level (h3 default; h4 when nested under a collapsible-all\n // <h3>), rendered via the Heading primitive. `text-base` pins the size to the\n // prior inherited size — the heading recipe's default h3 size would be larger.\n const headingLevel = headingTag === 'h4' ? 4 : 3;\n const isCardEach = appearance === SectionMode.CARD;\n const hasHeading = legend != null || icon != null || description != null;\n return (\n <Surface\n asChild\n emitPolicyVars={false}\n variant={isCardEach ? SurfaceVariant.CARD : SurfaceVariant.BASE}\n policyOverride={{\n nesting: { framingMode: isCardEach ? ('always' as const) : ('never' as const) },\n }}\n >\n <fieldset\n data-slot=\"field-set\"\n data-appearance={appearance}\n data-section-frame={isCardEach ? 'rendered' : 'suppressed'}\n disabled={disabled}\n // Non-card panels are FLAT: neutralize the Surface-painted BASE recipe\n // (a bordered card panel in every theme) on the element itself — the\n // wrapper is kept for the policy context only. See the solo DEFAULT\n // branch below for the full account of this trap.\n className={cn(\n isCardEach ? cardRecipe.base : 'space-y-field rounded-none border-0 bg-transparent p-0 shadow-none',\n className,\n )}\n {...props}\n style={\n isCardEach\n ? props.style\n : { borderWidth: 0, background: 'transparent', boxShadow: 'none', borderRadius: 0, padding: 0, ...props.style }\n }\n >\n {hasHeading && (\n <div className={isCardEach ? 'p-card border-b' : 'space-y-item-xs'}>\n {(legend != null || icon != null) && (\n <Heading level={headingLevel} className=\"text-base font-semibold\">\n {icon != null && <span className=\"me-element inline-flex items-center\">{icon}</span>}\n {legend}\n </Heading>\n )}\n {description != null && <Text variant={TextVariant.MUTED} size={TextSize.SM}>{description}</Text>}\n </div>\n )}\n <div className={isCardEach ? 'p-card' : undefined}>{children}</div>\n </fieldset>\n </Surface>\n );\n }\n\n // COLLAPSIBLE — toggle with the legend as the clickable trigger. Plain div (no\n // Surface/frame), matching the prior Section.tsx behavior exactly.\n if (appearance === SectionMode.COLLAPSIBLE) {\n return (\n <Collapsible defaultOpen={defaultOpen}>\n <div className={cn('space-y-field', className)} {...divPassthrough}>\n {structuredLegend && (\n // No `asChild` + raw <button>: Radix's CollapsibleTrigger renders its\n // own <button data-slot=\"collapsible-trigger\"> — the framework element,\n // no bespoke button chrome to add.\n <CollapsibleTrigger className=\"flex w-full items-center justify-between text-left\">\n {structuredLegend}\n <CollapsibleChevron />\n </CollapsibleTrigger>\n )}\n {structuredDescription}\n <CollapsibleContent>{children}</CollapsibleContent>\n </div>\n </Collapsible>\n );\n }\n\n // GHOST — flat div, no fieldset/frame. The form-level <fieldset> (Form.tsx)\n // already owns the disabled cascade, so a flat section loses nothing.\n if (appearance === SectionMode.GHOST) {\n return (\n <div className={cn('space-y-field', className)} {...divPassthrough}>\n {structuredLegend}\n {structuredDescription}\n {children}\n </div>\n );\n }\n\n const isCard = appearance === SectionMode.CARD;\n // ⚠ The settings-row match is `^=settings` (prefix), NOT `=settings_row`:\n // Tailwind converts an unescaped `_` inside an arbitrary variant to a SPACE,\n // so the original `…=settings_row]]:gap-0` spelling emitted the invalid\n // selector `[data-chrome-mode=settings row]` and was silently DEAD CSS\n // (verified against the served stylesheet, 2026-08-19). Only `settings_row`\n // starts with `settings`, so the prefix match is exact.\n const baseStyles =\n \"flex flex-col gap-field has-[>[data-slot=checkbox-group]]:gap-field-sm has-[>[data-slot=radio-group]]:gap-field-sm has-[>[data-chrome-mode^=settings]]:gap-0\";\n\n // DEFAULT — a flat fieldset that owns only inter-field spacing (no frame). The\n // form-level <fieldset> already owns the disabled cascade; the legend renders\n // in place at the top. Truthfully publishes `framingMode: 'never'` to descendants.\n //\n // The Surface wrapper exists for the POLICY context only, but `Surface` always\n // paints its variant recipe (policy and appearance are separate axes), and\n // every theme paints `SurfaceVariant.BASE` as a bordered card panel (it is the\n // anchor card surface). Without the frame neutralizers below, this \"flat\"\n // section rendered a card frame whose native <legend> straddled the top border\n // (the todo-lists READ \"header section glitch\", 2026-08-19). Same idiom as the\n // CARD branch's transparent fieldset: neutralize the paint on the element, keep\n // the policy context. The inline style is the deterministic half: recipe vs\n // neutralizer utility classes race on STYLESHEET order (measured: `shadow-sm`\n // beat `shadow-none`), while an inline declaration always wins; caller-passed\n // style still overrides via the trailing spread.\n if (!isCard) {\n return (\n <Surface asChild emitPolicyVars={false} variant={SurfaceVariant.BASE} policyOverride={{ nesting: { framingMode: 'never' as const } }}>\n <fieldset\n data-slot=\"field-set\"\n data-appearance={appearance}\n data-section-frame=\"suppressed\"\n disabled={disabled}\n className={cn(baseStyles, 'rounded-none border-0 bg-transparent p-0 shadow-none', className)}\n {...props}\n style={{ borderWidth: 0, background: 'transparent', boxShadow: 'none', borderRadius: 0, padding: 0, ...props.style }}\n >\n {structuredLegend}\n {structuredDescription}\n {children}\n </fieldset>\n </Surface>\n );\n }\n\n // CARD — the section title + description sit ABOVE the card as a group heading\n // (the macOS/iOS/Linear \"settings group\" pattern), and the themed card chrome\n // (elevated fill + border + radius from the active theme's CARD recipe) wraps\n // ONLY the body. The <fieldset> stays the outer element so its `disabled`\n // cascade still reaches every control, and it is `aria-labelledby` the heading\n // so the group keeps its accessible name.\n //\n // An explicit CARD ALWAYS paints its themed chrome (the `when-orphan` de-dup\n // does NOT apply — the author chose a card, so it stays a card in every\n // context, truthfully publishing `framingMode: 'always'` to descendants).\n //\n // Body padding is CONTENT-AWARE (see `cardBodyIsSettingsList` above): a body\n // hosting SETTINGS_ROW list-items drops its inline padding and clips, so each\n // row's hairline `border-b` divider runs corner-to-corner (full-bleed) instead\n // of floating inset; the rows then re-inset their own content with `px-card`\n // (owned by the SETTINGS_ROW chrome). Free-form content keeps a comfortable\n // `p-card`.\n const headingId = `${reactId}-legend`;\n const hasHeading = legend != null && legend !== false;\n return (\n <Surface asChild emitPolicyVars={false} variant={SurfaceVariant.CARD} policyOverride={{ nesting: { framingMode: 'always' as const } }}>\n <fieldset\n data-slot=\"field-set\"\n data-appearance={appearance}\n data-section-frame=\"rendered\"\n disabled={disabled}\n aria-labelledby={hasHeading ? headingId : undefined}\n className={cn(\"flex flex-col gap-field-sm border-0 bg-transparent p-0\", className)}\n {...props}\n >\n {hasHeading && (\n <div className=\"space-y-item-xs\">\n {/*\n Group heading ABOVE the card body. Rendered via the Heading primitive\n at semantic level 3; `id` (the fieldset's aria-labelledby target),\n `data-slot=\"field-legend\"` + `data-variant=\"legend\"` (CSS hooks) are\n forwarded, and `text-base font-medium` pins the size (the heading\n recipe's default h3 size would be larger).\n */}\n <Heading\n level={3}\n id={headingId}\n data-slot=\"field-legend\"\n data-variant=\"legend\"\n className=\"text-base font-medium leading-tight\"\n >\n {legend}\n </Heading>\n {structuredDescription}\n </div>\n )}\n <div\n ref={cardBodyRef}\n data-slot=\"section-card-body\"\n data-settings-list={cardBodyIsSettingsList || undefined}\n className={cn(\n cardRecipe.base,\n \"flex flex-col\",\n // Settings-row list → zero body padding + clip so each row's\n // `border-b` runs full-bleed to the rounded card edge (rows re-inset\n // with their own `px-card`, owned by the SETTINGS_ROW chrome).\n // Free-form content → comfortable `p-card`. All utilities here are\n // already-emitted (no new arbitrary-variant strings), so the toggle\n // works on hot-reload — see `cardBodyIsSettingsList` above.\n cardBodyIsSettingsList\n ? \"gap-0 p-0 overflow-hidden\"\n : \"gap-field p-card has-[>[data-slot=checkbox-group]]:gap-field-sm has-[>[data-slot=radio-group]]:gap-field-sm\",\n )}\n >\n {children}\n </div>\n </fieldset>\n </Surface>\n );\n}\n\nexport { ContentSection, ContentSectionGroup, ContentSectionLegend }\n"]}
1
+ {"version":3,"file":"content-section.js","sourceRoot":"","sources":["../../../../../src/components/sections/content-section.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from \"react\"\n\nimport {\n cn,\n useUI,\n useIconRegistry,\n StandardIconReference,\n IconSize,\n Surface,\n Heading,\n Text,\n Collapsible,\n CollapsibleTrigger,\n CollapsibleContent,\n type ContentSectionProps,\n type ContentSectionGroupProps,\n type ContentSectionLegendProps,\n} from '@wildo-ai/saas-frontend-lib';\n\nimport { SectionMode } from \"@wildo-ai/zod-decorators\"\nimport { SurfaceVariant, UIBehavior, TextVariant, TextSize } from \"@wildo-ai/presets-components-models\"\n\n/**\n * ContentSectionLegend preset — section heading. DOM-identical to the legacy\n * FieldLegend preset (`data-slot=\"field-legend\"` + classes) so existing CSS and\n * the `FieldDescription` legend-adjacency rule keep working unchanged.\n */\nfunction ContentSectionLegend({\n className,\n variant = \"legend\",\n ...props\n}: ContentSectionLegendProps): React.JSX.Element {\n return (\n <legend\n data-slot=\"field-legend\"\n data-variant={variant}\n className={cn(\n \"mb-field-sm font-medium\",\n \"data-[variant=legend]:text-base\",\n \"data-[variant=label]:text-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\n/**\n * ContentSectionGroup preset — child-grouping container. DOM-identical to the\n * legacy FieldGroup preset (`data-slot=\"field-group\"`, `@container/field-group`,\n * `group/field-group`) so the responsive `Field` orientation + `FieldSeparator`\n * selectors keyed off those container/group names keep resolving.\n */\nfunction ContentSectionGroup({ className, ...props }: ContentSectionGroupProps): React.JSX.Element {\n return (\n <div\n data-slot=\"field-group\"\n className={cn(\n \"group/field-group @container/field-group flex w-full flex-col gap-section-lg data-[slot=checkbox-group]:gap-field-sm [&>[data-slot=field-group]]:gap-field\",\n className\n )}\n {...props}\n />\n )\n}\n\n/**\n * Collapsible heading chevron — rendered through the icon registry\n * (`StandardIconReference.CHEVRON_DOWN`) instead of a hand-drawn `<svg>`, so it\n * tracks the app's icon set. The `[[data-state=open]_&]` selector rotates it\n * when the ancestor `CollapsibleTrigger` is open (Radix sets `data-state=open`).\n */\nfunction CollapsibleChevron(): React.ReactNode {\n const { renderIcon } = useIconRegistry();\n return renderIcon(StandardIconReference.CHEVRON_DOWN, {\n size: IconSize.SM,\n className:\n \"shrink-0 text-muted-foreground transition-transform duration-200 [[data-state=open]_&]:rotate-180\",\n });\n}\n\n/**\n * ContentSection preset — the section chrome workhorse.\n *\n * DEFAULT / CARD: ported verbatim from the FieldSet preset — a `<Surface>`-wrapped\n * native `<fieldset>` (the `disabled` cascade carrier) with the `when-orphan`\n * frame de-duplication, the inter-field `gap-field` ownership + checkbox/radio +\n * settings-row flush exceptions, and truthful SurfacePolicy publication\n * (`framingMode` = `when-orphan` for framed modes, `never` for flat). DOM is\n * byte-identical to the old FieldSet (`data-slot=\"field-set\"`), so there is no\n * CSS / visual / test regression by construction.\n *\n * GHOST: a flat `<div>` (no fieldset/frame), and COLLAPSIBLE: a `Collapsible`\n * toggle with the legend as the clickable trigger — both ported from the\n * hand-branched solo-mode logic that used to live in `Section.tsx`, so all four\n * solo appearances now flow through this one primitive.\n *\n * `legend` / `description` are structured props (rendered in the mode-appropriate\n * position). When omitted, the imperative composite/record/array sites pass\n * `<ContentSectionLegend>` / `<ContentSectionGroup>` as children instead — both\n * shapes produce the same fieldset DOM for DEFAULT.\n */\nfunction ContentSection({\n className,\n appearance = SectionMode.DEFAULT,\n legend,\n description,\n defaultOpen = true,\n disabled,\n panel = false,\n icon,\n headingTag,\n children,\n ...props\n}: ContentSectionProps): React.JSX.Element {\n const { getRecipe } = useUI();\n // CARD sections paint the active theme's CARD recipe — an elevated\n // `surface-raised` fill + border (or a translucent liquid-glass tile under the\n // glass theme). Resolved once per render.\n const cardRecipe = getRecipe(UIBehavior.SURFACE, SurfaceVariant.CARD);\n // Stable id for the CARD group heading ↔ fieldset `aria-labelledby` wiring.\n // Called unconditionally (hooks rule) even though only the CARD branch uses it.\n const reactId = React.useId();\n\n // CARD body full-bleed detection. A CARD whose body hosts SETTINGS_ROW\n // list-items drops its inline padding so each row's `border-b` divider runs\n // corner-to-corner; free-form content keeps `p-card`. The natural expression\n // is a CSS `has-[>[data-chrome-mode=settings_row]]:p-0` variant, but that is a\n // NET-NEW arbitrary-variant class string, and Tailwind v4 only scans engine\n // `@source` dirs at dev-server STARTUP — so a new variant class does not\n // compile on hot-reload (only on a full restart / production build). To stay\n // reliable on every reload we instead detect the settings-row children at\n // runtime and toggle between ALREADY-EMITTED utilities (`p-0`/`p-card`). The\n // effect runs each commit with a change-guard (no re-render loop); `bodyRef`\n // is null for the non-CARD branches, so this is inert there.\n const cardBodyRef = React.useRef<HTMLDivElement>(null);\n const [cardBodyIsSettingsList, setCardBodyIsSettingsList] = React.useState(false);\n React.useLayoutEffect(() => {\n const el = cardBodyRef.current;\n const next = !!el && !!el.querySelector(':scope > [data-chrome-mode=\"settings_row\"]');\n setCardBodyIsSettingsList((prev) => (prev === next ? prev : next));\n });\n\n // Explicit CARD sections — solo AND container-panel `card-each` — ALWAYS paint\n // their themed card chrome (elevated fill + border). The `when-orphan` frame\n // de-dup is intentionally NOT applied to an authored card: the author chose a\n // card, so it stays a card in every context (dialog, page, nested). DEFAULT /\n // GHOST stay flat; COLLAPSIBLE is its own toggle.\n\n // GHOST / COLLAPSIBLE render a <div>, not a <fieldset>. `props` is typed for a\n // fieldset (ref/form/name); the only passthrough the section render sites use\n // on these modes is data-*/aria-*/className, all valid on a div — so narrow the\n // type for the div branches. (The <fieldset> branch keeps the full fieldset props.)\n const divPassthrough = props as unknown as React.HTMLAttributes<HTMLDivElement>;\n\n const structuredLegend =\n legend != null && legend !== false ? <ContentSectionLegend>{legend}</ContentSectionLegend> : null;\n const structuredDescription =\n description != null && description !== false ? (\n <Text variant={TextVariant.MUTED} size={TextSize.SM}>{description}</Text>\n ) : null;\n\n // CONTAINER-PANEL chrome (ContentSectionContainer's tabs/grid/accordion/… panels).\n // Renders a heading element (not a <legend>) with a header-bar/divider layout.\n // Per appearance: CARD = card-each, which paints the SAME themed card chrome as\n // a solo CARD section (the elevated `surface-raised` fill + border + radius from\n // the active theme's CARD recipe), ALWAYS — so a grid/columns of cards reads as\n // distinct cards in every context; DEFAULT = flat. Stays a <fieldset> so the\n // disabled cascade applies — the consolidation that lets container panels share\n // the section primitive. Heading omitted entirely when there is no title/icon/\n // description (content-only panels, e.g. tab bodies whose heading is the tab).\n if (panel) {\n // Semantic heading level (h3 default; h4 when nested under a collapsible-all\n // <h3>), rendered via the Heading primitive. `text-base` pins the size to the\n // prior inherited size — the heading recipe's default h3 size would be larger.\n const headingLevel = headingTag === 'h4' ? 4 : 3;\n const isCardEach = appearance === SectionMode.CARD;\n const hasHeading = legend != null || icon != null || description != null;\n return (\n <Surface\n asChild\n emitPolicyVars={false}\n variant={isCardEach ? SurfaceVariant.CARD : SurfaceVariant.BASE}\n policyOverride={{\n nesting: { framingMode: isCardEach ? ('always' as const) : ('never' as const) },\n }}\n >\n <fieldset\n data-slot=\"field-set\"\n data-appearance={appearance}\n data-section-frame={isCardEach ? 'rendered' : 'suppressed'}\n disabled={disabled}\n // Non-card panels are FLAT: neutralize the Surface-painted BASE recipe\n // (a bordered card panel in every theme) on the element itself — the\n // wrapper is kept for the policy context only. See the solo DEFAULT\n // branch below for the full account of this trap.\n className={cn(\n isCardEach ? cardRecipe.base : 'space-y-field rounded-none border-0 bg-transparent p-0 shadow-none',\n className,\n )}\n {...props}\n style={\n isCardEach\n ? props.style\n : { borderWidth: 0, background: 'transparent', boxShadow: 'none', borderRadius: 0, padding: 0, ...props.style }\n }\n >\n {hasHeading && (\n <div className={isCardEach ? 'p-card border-b' : 'space-y-item-xs'}>\n {(legend != null || icon != null) && (\n <Heading level={headingLevel} className=\"text-base font-semibold\">\n {icon != null && <span className=\"me-element inline-flex items-center\">{icon}</span>}\n {legend}\n </Heading>\n )}\n {description != null && <Text variant={TextVariant.MUTED} size={TextSize.SM}>{description}</Text>}\n </div>\n )}\n <div className={isCardEach ? 'p-card' : undefined}>{children}</div>\n </fieldset>\n </Surface>\n );\n }\n\n // COLLAPSIBLE — toggle with the legend as the clickable trigger, framed as a CARD\n // (decided 2026-08-31; it was a flat div first). A fold needs a boundary: the closed\n // header must read as an affordance with an extent, and an open one must say where its\n // content ends — a frameless collapsed row was indistinguishable from a plain heading.\n // Item-level content inside stays UNframed (the display pipeline's entry items draw a\n // left accent line, not a card), so the frame stays the SECTION's alone.\n if (appearance === SectionMode.COLLAPSIBLE) {\n return (\n <Collapsible defaultOpen={defaultOpen}>\n <Surface\n asChild\n emitPolicyVars={false}\n variant={SurfaceVariant.CARD}\n policyOverride={{ nesting: { framingMode: 'always' as const } }}\n >\n <div className={cn(cardRecipe.base, className)} {...divPassthrough}>\n {structuredLegend && (\n // No `asChild` + raw <button>: Radix's CollapsibleTrigger renders its\n // own <button data-slot=\"collapsible-trigger\"> — the framework element,\n // no bespoke button chrome to add.\n <CollapsibleTrigger className=\"flex w-full items-center justify-between p-card text-left\">\n {structuredLegend}\n <CollapsibleChevron />\n </CollapsibleTrigger>\n )}\n {structuredDescription && <div className=\"px-card pb-card-sm\">{structuredDescription}</div>}\n <CollapsibleContent className=\"space-y-field p-card pt-0\">{children}</CollapsibleContent>\n </div>\n </Surface>\n </Collapsible>\n );\n }\n\n // GHOST — flat div, no fieldset/frame. The form-level <fieldset> (Form.tsx)\n // already owns the disabled cascade, so a flat section loses nothing.\n if (appearance === SectionMode.GHOST) {\n return (\n <div className={cn('space-y-field', className)} {...divPassthrough}>\n {structuredLegend}\n {structuredDescription}\n {children}\n </div>\n );\n }\n\n const isCard = appearance === SectionMode.CARD;\n // ⚠ The settings-row match is `^=settings` (prefix), NOT `=settings_row`:\n // Tailwind converts an unescaped `_` inside an arbitrary variant to a SPACE,\n // so the original `…=settings_row]]:gap-0` spelling emitted the invalid\n // selector `[data-chrome-mode=settings row]` and was silently DEAD CSS\n // (verified against the served stylesheet, 2026-08-19). Only `settings_row`\n // starts with `settings`, so the prefix match is exact.\n const baseStyles =\n \"flex flex-col gap-field has-[>[data-slot=checkbox-group]]:gap-field-sm has-[>[data-slot=radio-group]]:gap-field-sm has-[>[data-chrome-mode^=settings]]:gap-0\";\n\n // DEFAULT — a flat fieldset that owns only inter-field spacing (no frame). The\n // form-level <fieldset> already owns the disabled cascade; the legend renders\n // in place at the top. Truthfully publishes `framingMode: 'never'` to descendants.\n //\n // The Surface wrapper exists for the POLICY context only, but `Surface` always\n // paints its variant recipe (policy and appearance are separate axes), and\n // every theme paints `SurfaceVariant.BASE` as a bordered card panel (it is the\n // anchor card surface). Without the frame neutralizers below, this \"flat\"\n // section rendered a card frame whose native <legend> straddled the top border\n // (the todo-lists READ \"header section glitch\", 2026-08-19). Same idiom as the\n // CARD branch's transparent fieldset: neutralize the paint on the element, keep\n // the policy context. The inline style is the deterministic half: recipe vs\n // neutralizer utility classes race on STYLESHEET order (measured: `shadow-sm`\n // beat `shadow-none`), while an inline declaration always wins; caller-passed\n // style still overrides via the trailing spread.\n if (!isCard) {\n return (\n <Surface asChild emitPolicyVars={false} variant={SurfaceVariant.BASE} policyOverride={{ nesting: { framingMode: 'never' as const } }}>\n <fieldset\n data-slot=\"field-set\"\n data-appearance={appearance}\n data-section-frame=\"suppressed\"\n disabled={disabled}\n className={cn(baseStyles, 'rounded-none border-0 bg-transparent p-0 shadow-none', className)}\n {...props}\n style={{ borderWidth: 0, background: 'transparent', boxShadow: 'none', borderRadius: 0, padding: 0, ...props.style }}\n >\n {structuredLegend}\n {structuredDescription}\n {children}\n </fieldset>\n </Surface>\n );\n }\n\n // CARD — the section title + description sit ABOVE the card as a group heading\n // (the macOS/iOS/Linear \"settings group\" pattern), and the themed card chrome\n // (elevated fill + border + radius from the active theme's CARD recipe) wraps\n // ONLY the body. The <fieldset> stays the outer element so its `disabled`\n // cascade still reaches every control, and it is `aria-labelledby` the heading\n // so the group keeps its accessible name.\n //\n // An explicit CARD ALWAYS paints its themed chrome (the `when-orphan` de-dup\n // does NOT apply — the author chose a card, so it stays a card in every\n // context, truthfully publishing `framingMode: 'always'` to descendants).\n //\n // Body padding is CONTENT-AWARE (see `cardBodyIsSettingsList` above): a body\n // hosting SETTINGS_ROW list-items drops its inline padding and clips, so each\n // row's hairline `border-b` divider runs corner-to-corner (full-bleed) instead\n // of floating inset; the rows then re-inset their own content with `px-card`\n // (owned by the SETTINGS_ROW chrome). Free-form content keeps a comfortable\n // `p-card`.\n const headingId = `${reactId}-legend`;\n const hasHeading = legend != null && legend !== false;\n return (\n <Surface asChild emitPolicyVars={false} variant={SurfaceVariant.CARD} policyOverride={{ nesting: { framingMode: 'always' as const } }}>\n <fieldset\n data-slot=\"field-set\"\n data-appearance={appearance}\n data-section-frame=\"rendered\"\n disabled={disabled}\n aria-labelledby={hasHeading ? headingId : undefined}\n className={cn(\"flex flex-col gap-field-sm border-0 bg-transparent p-0\", className)}\n {...props}\n >\n {hasHeading && (\n <div className=\"space-y-item-xs\">\n {/*\n Group heading ABOVE the card body. Rendered via the Heading primitive\n at semantic level 3; `id` (the fieldset's aria-labelledby target),\n `data-slot=\"field-legend\"` + `data-variant=\"legend\"` (CSS hooks) are\n forwarded, and `text-base font-medium` pins the size (the heading\n recipe's default h3 size would be larger).\n */}\n <Heading\n level={3}\n id={headingId}\n data-slot=\"field-legend\"\n data-variant=\"legend\"\n className=\"text-base font-medium leading-tight\"\n >\n {legend}\n </Heading>\n {structuredDescription}\n </div>\n )}\n <div\n ref={cardBodyRef}\n data-slot=\"section-card-body\"\n data-settings-list={cardBodyIsSettingsList || undefined}\n className={cn(\n cardRecipe.base,\n \"flex flex-col\",\n // Settings-row list → zero body padding + clip so each row's\n // `border-b` runs full-bleed to the rounded card edge (rows re-inset\n // with their own `px-card`, owned by the SETTINGS_ROW chrome).\n // Free-form content → comfortable `p-card`. All utilities here are\n // already-emitted (no new arbitrary-variant strings), so the toggle\n // works on hot-reload — see `cardBodyIsSettingsList` above.\n cardBodyIsSettingsList\n ? \"gap-0 p-0 overflow-hidden\"\n : \"gap-field p-card has-[>[data-slot=checkbox-group]]:gap-field-sm has-[>[data-slot=radio-group]]:gap-field-sm\",\n )}\n >\n {children}\n </div>\n </fieldset>\n </Surface>\n );\n}\n\nexport { ContentSection, ContentSectionGroup, ContentSectionLegend }\n"]}
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ /**
3
+ * True below an OPEN disclosure panel — the fact a nesting-aware root reads to know it is nested.
4
+ *
5
+ * "Disclosure panel" is the shared role of `AccordionContent` and `CollapsibleContent`: content
6
+ * revealed by an activating control. Both PROVIDE this context; a root that wants the themed
7
+ * nesting treatment (`UIBehavior.DIVIDER` / `DividerVariant.NESTING_GUIDE`) consumes it.
8
+ *
9
+ * A React context rather than a CSS selector, for one reason: the nested look is a THEME RECIPE — a
10
+ * runtime value — and a selector cannot apply a runtime class string conditionally. The context
11
+ * carries the same property a selector would: nesting is a FACT of the tree, not an authoring
12
+ * decision, so a caller cannot forget it or declare it falsely.
13
+ *
14
+ * Consumption is deliberately opt-in per component. `AccordionRoot` consumes it; `CollapsibleRoot`
15
+ * does not (yet): the ai-element surfaces built on Collapsible (task, tool, queue, approval,
16
+ * execution-stream) hand-compose their own chrome, and an automatic guide on every nested
17
+ * collapsible there is a visual change that must be looked at, not deduced.
18
+ */
19
+ export declare const DisclosureNestingContext: React.Context<boolean>;
20
+ //# sourceMappingURL=disclosure-nesting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disclosure-nesting.d.ts","sourceRoot":"","sources":["../../../../../src/components/sections/disclosure-nesting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,wBAAwB,wBAA6B,CAAA"}
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ /**
3
+ * True below an OPEN disclosure panel — the fact a nesting-aware root reads to know it is nested.
4
+ *
5
+ * "Disclosure panel" is the shared role of `AccordionContent` and `CollapsibleContent`: content
6
+ * revealed by an activating control. Both PROVIDE this context; a root that wants the themed
7
+ * nesting treatment (`UIBehavior.DIVIDER` / `DividerVariant.NESTING_GUIDE`) consumes it.
8
+ *
9
+ * A React context rather than a CSS selector, for one reason: the nested look is a THEME RECIPE — a
10
+ * runtime value — and a selector cannot apply a runtime class string conditionally. The context
11
+ * carries the same property a selector would: nesting is a FACT of the tree, not an authoring
12
+ * decision, so a caller cannot forget it or declare it falsely.
13
+ *
14
+ * Consumption is deliberately opt-in per component. `AccordionRoot` consumes it; `CollapsibleRoot`
15
+ * does not (yet): the ai-element surfaces built on Collapsible (task, tool, queue, approval,
16
+ * execution-stream) hand-compose their own chrome, and an automatic guide on every nested
17
+ * collapsible there is a visual change that must be looked at, not deduced.
18
+ */
19
+ export const DisclosureNestingContext = React.createContext(false);
20
+ //# sourceMappingURL=disclosure-nesting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disclosure-nesting.js","sourceRoot":"","sources":["../../../../../src/components/sections/disclosure-nesting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA","sourcesContent":["import * as React from \"react\"\n\n/**\n * True below an OPEN disclosure panel — the fact a nesting-aware root reads to know it is nested.\n *\n * \"Disclosure panel\" is the shared role of `AccordionContent` and `CollapsibleContent`: content\n * revealed by an activating control. Both PROVIDE this context; a root that wants the themed\n * nesting treatment (`UIBehavior.DIVIDER` / `DividerVariant.NESTING_GUIDE`) consumes it.\n *\n * A React context rather than a CSS selector, for one reason: the nested look is a THEME RECIPE — a\n * runtime value — and a selector cannot apply a runtime class string conditionally. The context\n * carries the same property a selector would: nesting is a FACT of the tree, not an authoring\n * decision, so a caller cannot forget it or declare it falsely.\n *\n * Consumption is deliberately opt-in per component. `AccordionRoot` consumes it; `CollapsibleRoot`\n * does not (yet): the ai-element surfaces built on Collapsible (task, tool, queue, approval,\n * execution-stream) hand-compose their own chrome, and an automatic guide on every nested\n * collapsible there is a visual change that must be looked at, not deduced.\n */\nexport const DisclosureNestingContext = React.createContext(false)\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../../../src/components/sections/tabs.tsx"],"names":[],"mappings":"AAKA,OAAO,EACL,YAAY,EAKb,MAAM,6BAA6B,CAAC;AA8GrC,eAAO,MAAM,IAAI,cAA+G,CAAA"}
1
+ {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../../../../src/components/sections/tabs.tsx"],"names":[],"mappings":"AAMA,OAAO,EACL,YAAY,EAKb,MAAM,6BAA6B,CAAC;AAiRrC,eAAO,MAAM,IAAI,cAA+G,CAAA"}
@@ -1,7 +1,8 @@
1
1
  "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import * as TabsPrimitive from "@radix-ui/react-tabs";
5
+ import { ChevronLeft, ChevronRight } from "lucide-react";
5
6
  import { createCompoundPreset, cn, useUI, Surface, } from '@wildo-ai/saas-frontend-lib';
6
7
  import { SelectableVariant, SurfaceVariant, UIBehavior } from "@wildo-ai/presets-components-models";
7
8
  /**
@@ -21,15 +22,144 @@ function TabsRoot({ className, orientation = 'horizontal', ...props }) {
21
22
  const resolved = orientation === 'vertical' ? 'vertical' : 'horizontal';
22
23
  return (_jsx(TabsOrientationContext.Provider, { value: resolved, children: _jsx(TabsPrimitive.Root, { "data-slot": "tabs", orientation: orientation, className: cn("flex flex-col gap-element data-[orientation=vertical]:flex-row data-[orientation=vertical]:gap-card", className), ...props }) }));
23
24
  }
25
+ /**
26
+ * Overflow state of the horizontal scrollport — which edges have more content.
27
+ *
28
+ * Updated from three signals, because each misses a case the others catch: the
29
+ * `scroll` listener (user scrolled), a `ResizeObserver` on the list (viewport
30
+ * grew/shrank — the common "window resized" case), and a per-render effect
31
+ * (tab COUNT changed — children resizing does not move the list's own box, so
32
+ * the observer cannot see it).
33
+ */
34
+ function useHorizontalOverflow(ref) {
35
+ const [overflow, setOverflow] = React.useState({ start: false, end: false });
36
+ const update = React.useCallback(() => {
37
+ const el = ref.current;
38
+ if (!el)
39
+ return;
40
+ // 1px slack: fractional layout widths make scrollLeft/scrollWidth disagree by <1.
41
+ const start = el.scrollLeft > 1;
42
+ const end = el.scrollLeft + el.clientWidth < el.scrollWidth - 1;
43
+ setOverflow((prev) => (prev.start === start && prev.end === end ? prev : { start, end }));
44
+ }, [ref]);
45
+ React.useEffect(() => {
46
+ const el = ref.current;
47
+ if (!el)
48
+ return;
49
+ el.addEventListener('scroll', update, { passive: true });
50
+ const observer = new ResizeObserver(update);
51
+ observer.observe(el);
52
+ return () => {
53
+ el.removeEventListener('scroll', update);
54
+ observer.disconnect();
55
+ };
56
+ }, [ref, update]);
57
+ // No dependency array on purpose — re-measures after every render, which is
58
+ // what catches content-only changes (a tab added/removed, a label resolving
59
+ // from i18n). Three numeric reads; cheap enough not to gate.
60
+ React.useEffect(update);
61
+ return overflow;
62
+ }
63
+ /** Width of each fade/affordance zone. One constant so the mask and the button agree. */
64
+ const TABS_FADE_ZONE = '2.5rem';
65
+ /**
66
+ * The edge fade, as a MASK on the strip rather than a gradient painted over it.
67
+ *
68
+ * A painted gradient has to name the colour it fades FROM, and no colour is
69
+ * right: measured on the workbench, the strip sits on `bg-surface-raised`
70
+ * (oklch 0.208) while `--background` is oklch 0.129, so an overlay fading to
71
+ * the background token washed a visibly wrong band across the strip — and it
72
+ * would be wrong differently on every surface a tab strip can sit on (card,
73
+ * dialog, panel) and in every theme.
74
+ *
75
+ * Masking fades the CONTENT to transparency instead, revealing whatever is
76
+ * actually behind it. It needs no colour token, so it is correct on every
77
+ * surface and every theme by construction.
78
+ */
79
+ function edgeFadeMask(overflow) {
80
+ if (!overflow.start && !overflow.end)
81
+ return undefined;
82
+ const stops = [
83
+ overflow.start ? `transparent 0, black ${TABS_FADE_ZONE}` : 'black 0',
84
+ overflow.end ? `black calc(100% - ${TABS_FADE_ZONE}), transparent 100%` : 'black 100%',
85
+ ];
86
+ return `linear-gradient(to right, ${stops.join(', ')})`;
87
+ }
88
+ /**
89
+ * One edge's slide affordance: the DISCREET control the design asks for — a
90
+ * quiet chevron over the faded zone, with no box and no background of its own
91
+ * (the mask above is what makes room for it). Mouse-only by intent
92
+ * (`aria-hidden`, unfocusable): keyboard users already reach every tab through
93
+ * the tab list's roving arrow-key focus, so exposing this to the tab order
94
+ * would add a stop that does nothing arrows don't.
95
+ */
96
+ function TabsListSlideAffordance({ side, onSlide }) {
97
+ const Chevron = side === 'start' ? ChevronLeft : ChevronRight;
98
+ return (_jsx("button", { type: "button", tabIndex: -1, "aria-hidden": "true", "data-slot": "tabs-list-slide", "data-side": side, onClick: onSlide, style: { width: TABS_FADE_ZONE }, className: cn("absolute inset-y-0 z-10 flex cursor-pointer items-center border-0 bg-transparent p-0", side === 'start' ? "left-0 justify-start" : "right-0 justify-end"), children: _jsx(Chevron, { className: "size-4 text-muted-foreground opacity-60 transition-opacity hover:opacity-100" }) }));
99
+ }
24
100
  function TabsList({ className, ...props }) {
25
101
  const isVertical = React.useContext(TabsOrientationContext) === 'vertical';
26
- return (_jsx(TabsPrimitive.List, { "data-slot": "tabs-list", className: cn("flex", isVertical
102
+ const listRef = React.useRef(null);
103
+ const overflow = useHorizontalOverflow(listRef);
104
+ /*
105
+ * Vertical wheel input slides the strip horizontally — the strip is a
106
+ * one-axis surface, so a wheel over it can only mean "move along it". A
107
+ * NATIVE non-passive listener, not React `onWheel`: React registers wheel
108
+ * passively at the root, so `preventDefault()` there is ignored and every
109
+ * translated tick would also scroll the page behind the strip.
110
+ */
111
+ React.useEffect(() => {
112
+ const el = listRef.current;
113
+ if (!el || isVertical)
114
+ return;
115
+ const onWheel = (event) => {
116
+ if (el.scrollWidth <= el.clientWidth)
117
+ return;
118
+ const delta = Math.abs(event.deltaX) > Math.abs(event.deltaY) ? event.deltaX : event.deltaY;
119
+ if (delta === 0)
120
+ return;
121
+ el.scrollLeft += delta;
122
+ event.preventDefault();
123
+ };
124
+ el.addEventListener('wheel', onWheel, { passive: false });
125
+ return () => el.removeEventListener('wheel', onWheel);
126
+ }, [isVertical]);
127
+ const fadeMask = edgeFadeMask(overflow);
128
+ const slideBy = React.useCallback((direction) => {
129
+ const el = listRef.current;
130
+ if (!el)
131
+ return;
132
+ el.scrollBy({ left: direction * el.clientWidth * 0.6, behavior: 'smooth' });
133
+ }, []);
134
+ if (isVertical) {
135
+ return (_jsx(TabsPrimitive.List, { "data-slot": "tabs-list",
27
136
  // Vertical: clean nav rail (column of items, no boxed container).
28
- ? "flex-col items-stretch justify-start gap-item-xs"
29
- // Horizontal: underline tab bar — a full-width bottom rule that the
30
- // active tab's 2px indicator sits on. Separated items, NO connecting
31
- // tray (a tray would read as a segmented control).
32
- : "w-full items-center gap-card border-b", className), ...props }));
137
+ className: cn("flex flex-col items-stretch justify-start gap-item-xs", className), ...props }));
138
+ }
139
+ /*
140
+ * Horizontal: underline tab bar that SCROLLS when it overflows, instead of
141
+ * widening the page (measured on the workbench artifact list, whose concern
142
+ * tabs outgrew the viewport).
143
+ *
144
+ * ## Why the bottom rule is a wrapper layer, not `border-b` on the list
145
+ *
146
+ * Becoming a scrollport is what forces the restructure: `overflow-x: auto`
147
+ * makes `overflow-y` compute to a clipping value, and the old geometry —
148
+ * `border-b` on the list with `-mb-px` triggers overlapping their 2px
149
+ * indicator onto the 1px rule — needs the trigger to paint one pixel PAST
150
+ * the list's content edge, which a scrollport clips. So the rule is drawn by
151
+ * a non-scrolling absolutely-positioned layer in a wrapper, the triggers
152
+ * drop the overlap trick, and the indicator's bottom pixel lands on the rule
153
+ * because both sit on the wrapper's last pixel row. Same rendered result,
154
+ * scroll-safe.
155
+ *
156
+ * The scrollbar itself is suppressed on every engine (`scrollbar-width` for
157
+ * Firefox, the `::-webkit-scrollbar` pseudo elsewhere): a native horizontal
158
+ * scrollbar under a tab strip — Windows most visibly — reads as a broken
159
+ * layout, and the gradient affordances + wheel translation replace what it
160
+ * afforded.
161
+ */
162
+ return (_jsxs("div", { "data-slot": "tabs-list-scrollport", className: "relative w-full", children: [_jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute inset-x-0 bottom-0 h-px bg-border" }), _jsx(TabsPrimitive.List, { ref: listRef, "data-slot": "tabs-list", style: { maskImage: fadeMask, WebkitMaskImage: fadeMask }, className: cn("relative flex w-full items-center gap-card overflow-x-auto overscroll-x-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", className), ...props }), overflow.start && _jsx(TabsListSlideAffordance, { side: "start", onSlide: () => slideBy(-1) }), overflow.end && _jsx(TabsListSlideAffordance, { side: "end", onSlide: () => slideBy(1) })] }));
33
163
  }
34
164
  function TabsTrigger({ className, ...props }) {
35
165
  const isVertical = React.useContext(TabsOrientationContext) === 'vertical';
@@ -40,9 +170,10 @@ function TabsTrigger({ className, ...props }) {
40
170
  // Vertical: full-width, left-aligned rail item (FILLED recipe fills it).
41
171
  ? "w-full justify-start rounded-md px-card-sm py-item"
42
172
  // Horizontal: content-width underline tab (UNDERLINE recipe draws the
43
- // bottom border). `-mb-px` overlaps the tab's 2px indicator onto the
44
- // list's 1px rule so they read as one line.
45
- : "-mb-px justify-center px-card-sm py-item",
173
+ // bottom border). No `-mb-px` overlap here: the list is a scrollport
174
+ // (which would clip it) and the 1px rule is the wrapper's own layer,
175
+ // sharing the wrapper's last pixel row with this indicator.
176
+ : "justify-center px-card-sm py-item",
46
177
  // Style from the orientation-appropriate SELECTABLE recipe.
47
178
  recipe.base, recipe.states.focus, recipe.states.selected, recipe.states.disabled, recipe.motion.transition, className), ...props }));
48
179
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.js","sourceRoot":"","sources":["../../../../../src/components/sections/tabs.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport * as TabsPrimitive from \"@radix-ui/react-tabs\"\n\nimport {\n TabsCompound,\n createCompoundPreset,\n cn,\n useUI,\n Surface,\n} from '@wildo-ai/saas-frontend-lib';\n\nimport { FrontendComponentType, SelectableVariant, SurfaceVariant, UIBehavior } from \"@wildo-ai/presets-components-models\"\n\n/**\n * Orientation shared from TabsRoot down to List/Trigger so each sub-component can\n * choose the right `SELECTABLE` recipe. Radix exposes orientation only as a\n * `data-orientation` DOM attribute, but a recipe's utility strings (which already\n * carry `data-[state=active]:…`) can't be re-scoped per orientation from a class\n * list — so the choice is made in JS here.\n *\n * Horizontal tabs use `UNDERLINE` (a bottom-border indicator on separated items —\n * the canonical modern-SaaS navigation-tab look: \"separated = tabs, connected by\n * a track = segmented control\"). The vertical rail keeps `FILLED` (a soft fill on\n * the selected rail item).\n */\nconst TabsOrientationContext = React.createContext<'horizontal' | 'vertical'>('horizontal')\n\nfunction TabsRoot({\n className,\n orientation = 'horizontal',\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Root>): React.JSX.Element {\n const resolved = orientation === 'vertical' ? 'vertical' : 'horizontal'\n return (\n <TabsOrientationContext.Provider value={resolved}>\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n orientation={orientation}\n className={cn(\"flex flex-col gap-element data-[orientation=vertical]:flex-row data-[orientation=vertical]:gap-card\", className)}\n {...props}\n />\n </TabsOrientationContext.Provider>\n )\n}\n\nfunction TabsList({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.List>): React.JSX.Element {\n const isVertical = React.useContext(TabsOrientationContext) === 'vertical'\n\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n className={cn(\n \"flex\",\n isVertical\n // Vertical: clean nav rail (column of items, no boxed container).\n ? \"flex-col items-stretch justify-start gap-item-xs\"\n // Horizontal: underline tab bar — a full-width bottom rule that the\n // active tab's 2px indicator sits on. Separated items, NO connecting\n // tray (a tray would read as a segmented control).\n : \"w-full items-center gap-card border-b\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TabsTrigger({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Trigger>): React.JSX.Element {\n const isVertical = React.useContext(TabsOrientationContext) === 'vertical'\n const { getRecipe } = useUI()\n // Vertical rail → FILLED (soft fill on select); horizontal → UNDERLINE.\n const recipe = getRecipe(UIBehavior.SELECTABLE, isVertical ? SelectableVariant.FILLED : SelectableVariant.UNDERLINE)\n\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n \"inline-flex items-center gap-1.5 text-sm font-medium whitespace-nowrap [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n isVertical\n // Vertical: full-width, left-aligned rail item (FILLED recipe fills it).\n ? \"w-full justify-start rounded-md px-card-sm py-item\"\n // Horizontal: content-width underline tab (UNDERLINE recipe draws the\n // bottom border). `-mb-px` overlaps the tab's 2px indicator onto the\n // list's 1px rule so they read as one line.\n : \"-mb-px justify-center px-card-sm py-item\",\n // Style from the orientation-appropriate SELECTABLE recipe.\n recipe.base,\n recipe.states.focus,\n recipe.states.selected,\n recipe.states.disabled,\n recipe.motion.transition,\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TabsContent({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Content>): React.JSX.Element {\n return (\n <Surface asChild emitPolicyVars={false} variant={SurfaceVariant.TAB_PANEL}>\n <TabsPrimitive.Content\n data-slot=\"tabs-content\"\n className={cn(\"flex-1 outline-none\", className)}\n {...props}\n />\n </Surface>\n )\n}\n\nexport const Tabs = createCompoundPreset<TabsCompound>(TabsRoot, { List: TabsList, Trigger: TabsTrigger, Content: TabsContent })\n"]}
1
+ {"version":3,"file":"tabs.js","sourceRoot":"","sources":["../../../../../src/components/sections/tabs.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport * as TabsPrimitive from \"@radix-ui/react-tabs\"\nimport { ChevronLeft, ChevronRight } from \"lucide-react\"\n\nimport {\n TabsCompound,\n createCompoundPreset,\n cn,\n useUI,\n Surface,\n} from '@wildo-ai/saas-frontend-lib';\n\nimport { FrontendComponentType, SelectableVariant, SurfaceVariant, UIBehavior } from \"@wildo-ai/presets-components-models\"\n\n/**\n * Orientation shared from TabsRoot down to List/Trigger so each sub-component can\n * choose the right `SELECTABLE` recipe. Radix exposes orientation only as a\n * `data-orientation` DOM attribute, but a recipe's utility strings (which already\n * carry `data-[state=active]:…`) can't be re-scoped per orientation from a class\n * list — so the choice is made in JS here.\n *\n * Horizontal tabs use `UNDERLINE` (a bottom-border indicator on separated items —\n * the canonical modern-SaaS navigation-tab look: \"separated = tabs, connected by\n * a track = segmented control\"). The vertical rail keeps `FILLED` (a soft fill on\n * the selected rail item).\n */\nconst TabsOrientationContext = React.createContext<'horizontal' | 'vertical'>('horizontal')\n\nfunction TabsRoot({\n className,\n orientation = 'horizontal',\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Root>): React.JSX.Element {\n const resolved = orientation === 'vertical' ? 'vertical' : 'horizontal'\n return (\n <TabsOrientationContext.Provider value={resolved}>\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n orientation={orientation}\n className={cn(\"flex flex-col gap-element data-[orientation=vertical]:flex-row data-[orientation=vertical]:gap-card\", className)}\n {...props}\n />\n </TabsOrientationContext.Provider>\n )\n}\n\n/**\n * Overflow state of the horizontal scrollport — which edges have more content.\n *\n * Updated from three signals, because each misses a case the others catch: the\n * `scroll` listener (user scrolled), a `ResizeObserver` on the list (viewport\n * grew/shrank — the common \"window resized\" case), and a per-render effect\n * (tab COUNT changed — children resizing does not move the list's own box, so\n * the observer cannot see it).\n */\nfunction useHorizontalOverflow(ref: React.RefObject<HTMLElement | null>): { start: boolean; end: boolean } {\n const [overflow, setOverflow] = React.useState({ start: false, end: false })\n\n const update = React.useCallback(() => {\n const el = ref.current\n if (!el) return\n // 1px slack: fractional layout widths make scrollLeft/scrollWidth disagree by <1.\n const start = el.scrollLeft > 1\n const end = el.scrollLeft + el.clientWidth < el.scrollWidth - 1\n setOverflow((prev) => (prev.start === start && prev.end === end ? prev : { start, end }))\n }, [ref])\n\n React.useEffect(() => {\n const el = ref.current\n if (!el) return\n el.addEventListener('scroll', update, { passive: true })\n const observer = new ResizeObserver(update)\n observer.observe(el)\n return () => {\n el.removeEventListener('scroll', update)\n observer.disconnect()\n }\n }, [ref, update])\n\n // No dependency array on purpose — re-measures after every render, which is\n // what catches content-only changes (a tab added/removed, a label resolving\n // from i18n). Three numeric reads; cheap enough not to gate.\n React.useEffect(update)\n\n return overflow\n}\n\n/** Width of each fade/affordance zone. One constant so the mask and the button agree. */\nconst TABS_FADE_ZONE = '2.5rem'\n\n/**\n * The edge fade, as a MASK on the strip rather than a gradient painted over it.\n *\n * A painted gradient has to name the colour it fades FROM, and no colour is\n * right: measured on the workbench, the strip sits on `bg-surface-raised`\n * (oklch 0.208) while `--background` is oklch 0.129, so an overlay fading to\n * the background token washed a visibly wrong band across the strip — and it\n * would be wrong differently on every surface a tab strip can sit on (card,\n * dialog, panel) and in every theme.\n *\n * Masking fades the CONTENT to transparency instead, revealing whatever is\n * actually behind it. It needs no colour token, so it is correct on every\n * surface and every theme by construction.\n */\nfunction edgeFadeMask(overflow: { start: boolean; end: boolean }): string | undefined {\n if (!overflow.start && !overflow.end) return undefined\n const stops = [\n overflow.start ? `transparent 0, black ${TABS_FADE_ZONE}` : 'black 0',\n overflow.end ? `black calc(100% - ${TABS_FADE_ZONE}), transparent 100%` : 'black 100%',\n ]\n return `linear-gradient(to right, ${stops.join(', ')})`\n}\n\n/**\n * One edge's slide affordance: the DISCREET control the design asks for — a\n * quiet chevron over the faded zone, with no box and no background of its own\n * (the mask above is what makes room for it). Mouse-only by intent\n * (`aria-hidden`, unfocusable): keyboard users already reach every tab through\n * the tab list's roving arrow-key focus, so exposing this to the tab order\n * would add a stop that does nothing arrows don't.\n */\nfunction TabsListSlideAffordance({ side, onSlide }: { side: 'start' | 'end'; onSlide: () => void }): React.JSX.Element {\n const Chevron = side === 'start' ? ChevronLeft : ChevronRight\n return (\n <button\n type=\"button\"\n tabIndex={-1}\n aria-hidden=\"true\"\n data-slot=\"tabs-list-slide\"\n data-side={side}\n onClick={onSlide}\n style={{ width: TABS_FADE_ZONE }}\n className={cn(\n \"absolute inset-y-0 z-10 flex cursor-pointer items-center border-0 bg-transparent p-0\",\n side === 'start' ? \"left-0 justify-start\" : \"right-0 justify-end\",\n )}\n >\n <Chevron className=\"size-4 text-muted-foreground opacity-60 transition-opacity hover:opacity-100\" />\n </button>\n )\n}\n\nfunction TabsList({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.List>): React.JSX.Element {\n const isVertical = React.useContext(TabsOrientationContext) === 'vertical'\n const listRef = React.useRef<HTMLDivElement>(null)\n const overflow = useHorizontalOverflow(listRef)\n\n /*\n * Vertical wheel input slides the strip horizontally — the strip is a\n * one-axis surface, so a wheel over it can only mean \"move along it\". A\n * NATIVE non-passive listener, not React `onWheel`: React registers wheel\n * passively at the root, so `preventDefault()` there is ignored and every\n * translated tick would also scroll the page behind the strip.\n */\n React.useEffect(() => {\n const el = listRef.current\n if (!el || isVertical) return\n const onWheel = (event: WheelEvent) => {\n if (el.scrollWidth <= el.clientWidth) return\n const delta = Math.abs(event.deltaX) > Math.abs(event.deltaY) ? event.deltaX : event.deltaY\n if (delta === 0) return\n el.scrollLeft += delta\n event.preventDefault()\n }\n el.addEventListener('wheel', onWheel, { passive: false })\n return () => el.removeEventListener('wheel', onWheel)\n }, [isVertical])\n\n const fadeMask = edgeFadeMask(overflow)\n\n const slideBy = React.useCallback((direction: 1 | -1) => {\n const el = listRef.current\n if (!el) return\n el.scrollBy({ left: direction * el.clientWidth * 0.6, behavior: 'smooth' })\n }, [])\n\n if (isVertical) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n // Vertical: clean nav rail (column of items, no boxed container).\n className={cn(\"flex flex-col items-stretch justify-start gap-item-xs\", className)}\n {...props}\n />\n )\n }\n\n /*\n * Horizontal: underline tab bar that SCROLLS when it overflows, instead of\n * widening the page (measured on the workbench artifact list, whose concern\n * tabs outgrew the viewport).\n *\n * ## Why the bottom rule is a wrapper layer, not `border-b` on the list\n *\n * Becoming a scrollport is what forces the restructure: `overflow-x: auto`\n * makes `overflow-y` compute to a clipping value, and the old geometry —\n * `border-b` on the list with `-mb-px` triggers overlapping their 2px\n * indicator onto the 1px rule — needs the trigger to paint one pixel PAST\n * the list's content edge, which a scrollport clips. So the rule is drawn by\n * a non-scrolling absolutely-positioned layer in a wrapper, the triggers\n * drop the overlap trick, and the indicator's bottom pixel lands on the rule\n * because both sit on the wrapper's last pixel row. Same rendered result,\n * scroll-safe.\n *\n * The scrollbar itself is suppressed on every engine (`scrollbar-width` for\n * Firefox, the `::-webkit-scrollbar` pseudo elsewhere): a native horizontal\n * scrollbar under a tab strip — Windows most visibly — reads as a broken\n * layout, and the gradient affordances + wheel translation replace what it\n * afforded.\n */\n return (\n <div data-slot=\"tabs-list-scrollport\" className=\"relative w-full\">\n {/* The full-width rule lives OUTSIDE the masked strip, so the edge fade never eats it. */}\n <span aria-hidden=\"true\" className=\"pointer-events-none absolute inset-x-0 bottom-0 h-px bg-border\" />\n <TabsPrimitive.List\n ref={listRef}\n data-slot=\"tabs-list\"\n style={{ maskImage: fadeMask, WebkitMaskImage: fadeMask }}\n className={cn(\n \"relative flex w-full items-center gap-card overflow-x-auto overscroll-x-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\",\n className\n )}\n {...props}\n />\n {overflow.start && <TabsListSlideAffordance side=\"start\" onSlide={() => slideBy(-1)} />}\n {overflow.end && <TabsListSlideAffordance side=\"end\" onSlide={() => slideBy(1)} />}\n </div>\n )\n}\n\nfunction TabsTrigger({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Trigger>): React.JSX.Element {\n const isVertical = React.useContext(TabsOrientationContext) === 'vertical'\n const { getRecipe } = useUI()\n // Vertical rail → FILLED (soft fill on select); horizontal → UNDERLINE.\n const recipe = getRecipe(UIBehavior.SELECTABLE, isVertical ? SelectableVariant.FILLED : SelectableVariant.UNDERLINE)\n\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n \"inline-flex items-center gap-1.5 text-sm font-medium whitespace-nowrap [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n isVertical\n // Vertical: full-width, left-aligned rail item (FILLED recipe fills it).\n ? \"w-full justify-start rounded-md px-card-sm py-item\"\n // Horizontal: content-width underline tab (UNDERLINE recipe draws the\n // bottom border). No `-mb-px` overlap here: the list is a scrollport\n // (which would clip it) and the 1px rule is the wrapper's own layer,\n // sharing the wrapper's last pixel row with this indicator.\n : \"justify-center px-card-sm py-item\",\n // Style from the orientation-appropriate SELECTABLE recipe.\n recipe.base,\n recipe.states.focus,\n recipe.states.selected,\n recipe.states.disabled,\n recipe.motion.transition,\n className\n )}\n {...props}\n />\n )\n}\n\nfunction TabsContent({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Content>): React.JSX.Element {\n return (\n <Surface asChild emitPolicyVars={false} variant={SurfaceVariant.TAB_PANEL}>\n <TabsPrimitive.Content\n data-slot=\"tabs-content\"\n className={cn(\"flex-1 outline-none\", className)}\n {...props}\n />\n </Surface>\n )\n}\n\nexport const Tabs = createCompoundPreset<TabsCompound>(TabsRoot, { List: TabsList, Trigger: TabsTrigger, Content: TabsContent })\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"preset-kits.d.ts","sourceRoot":"","sources":["../../../../src/config/preset-kits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AA8B7E;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,EAAE,OAAO,CAAC,yBAAyB,CAExD,CAAC;AAGF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,yBAAyB,CAEzD,CAAC;AAGF;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,yBAAyB,CAE9D,CAAC;AAGF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,yBAAyB,CAGzD,CAAC;AAGF;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,OAAO,CAAC,yBAAyB,CAY3D,CAAC;AAGF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,OAAO,CAAC,yBAAyB,CAe5D,CAAC;AAOF;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,yBAAyB,CAiBzD,CAAC;AAGF;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,yBAAyB,CAM7D,CAAC;AAOF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,yBAAyB,CAyBzD,CAAC;AAGF;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,EAAE,OAAO,CAAC,yBAAyB,CAGtD,CAAC;AAGF;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,OAAO,CAAC,yBAAyB,CAM5D,CAAC;AAGF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,yBAAyB,CAqB9D,CAAC;AAGF;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,yBAAyB,CAU7D,CAAC;AAGF;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,yBAAyB,CAM7D,CAAC;AAGF;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,yBAAyB,CAoB7D,CAAC"}
1
+ {"version":3,"file":"preset-kits.d.ts","sourceRoot":"","sources":["../../../../src/config/preset-kits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AA8B7E;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,EAAE,OAAO,CAAC,yBAAyB,CAExD,CAAC;AAGF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,yBAAyB,CAEzD,CAAC;AAGF;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,yBAAyB,CAE9D,CAAC;AAGF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,yBAAyB,CAGzD,CAAC;AAGF;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,OAAO,CAAC,yBAAyB,CAY3D,CAAC;AAGF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,OAAO,CAAC,yBAAyB,CAc5D,CAAC;AAOF;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,yBAAyB,CAgBzD,CAAC;AAGF;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,yBAAyB,CAM7D,CAAC;AAOF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,OAAO,CAAC,yBAAyB,CAwBzD,CAAC;AAGF;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,EAAE,OAAO,CAAC,yBAAyB,CAGtD,CAAC;AAGF;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,OAAO,CAAC,yBAAyB,CAM5D,CAAC;AAGF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,OAAO,CAAC,yBAAyB,CAqB9D,CAAC;AAGF;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,yBAAyB,CAU7D,CAAC;AAGF;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,yBAAyB,CAM7D,CAAC;AAGF;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,yBAAyB,CAmB7D,CAAC"}
@@ -95,7 +95,6 @@ export const KIT_DRAG_DROP = {
95
95
  navSection('main', { showLabel: false, collapsible: false, nested: true, maxNestingDepth: 2 }),
96
96
  ],
97
97
  defaultSection: "main",
98
- showUncategorized: true,
99
98
  },
100
99
  }),
101
100
  };
@@ -121,7 +120,6 @@ export const KIT_TABLET = {
121
120
  navSection('tools'),
122
121
  ],
123
122
  defaultSection: "main",
124
- showUncategorized: true,
125
123
  },
126
124
  }),
127
125
  };
@@ -162,7 +160,6 @@ export const KIT_COLLAB = {
162
160
  navSection('settings', { defaultCollapsed: true }),
163
161
  ],
164
162
  defaultSection: "main",
165
- showUncategorized: true,
166
163
  },
167
164
  [ApplicationLevelComponentType.STATUS_BAR]: {
168
165
  showMemoryUsage: false,
@@ -283,7 +280,6 @@ export const KIT_AI_COPILOT = {
283
280
  navSection('settings', { defaultCollapsed: true }),
284
281
  ],
285
282
  defaultSection: "main",
286
- showUncategorized: true,
287
283
  },
288
284
  }),
289
285
  };