@psnext/design-system 2.3.0 → 2.4.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.
- package/DESIGN.md +466 -4
- package/README.md +3 -3
- package/SKILL.md +83 -5
- package/bin/install-agent-skill.mjs +39 -7
- package/dist/Header.cjs +151 -20
- package/dist/Header.cjs.map +1 -1
- package/dist/Header.js +151 -20
- package/dist/Header.js.map +1 -1
- package/dist/Icon.cjs +40 -8
- package/dist/Icon.cjs.map +1 -1
- package/dist/Icon.js +40 -8
- package/dist/Icon.js.map +1 -1
- package/dist/MultiColumn.cjs +354 -0
- package/dist/MultiColumn.cjs.map +1 -0
- package/dist/MultiColumn.js +335 -0
- package/dist/MultiColumn.js.map +1 -0
- package/dist/Sidebar.cjs +4 -3
- package/dist/Sidebar.cjs.map +1 -1
- package/dist/Sidebar.js +4 -3
- package/dist/Sidebar.js.map +1 -1
- package/dist/index.cjs +5 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index10.d.cts +6 -6
- package/dist/index10.d.ts +6 -6
- package/dist/index11.d.cts +3 -3
- package/dist/index11.d.cts.map +1 -1
- package/dist/index11.d.ts +3 -3
- package/dist/index11.d.ts.map +1 -1
- package/dist/index12.d.cts +12 -12
- package/dist/index12.d.cts.map +1 -1
- package/dist/index12.d.ts +13 -13
- package/dist/index13.d.cts +6 -6
- package/dist/index13.d.cts.map +1 -1
- package/dist/index13.d.ts +6 -6
- package/dist/index13.d.ts.map +1 -1
- package/dist/index14.d.cts +5 -5
- package/dist/index14.d.ts +5 -5
- package/dist/index15.d.cts +3 -3
- package/dist/index15.d.cts.map +1 -1
- package/dist/index15.d.ts +3 -3
- package/dist/index15.d.ts.map +1 -1
- package/dist/index16.d.cts +2 -2
- package/dist/index16.d.cts.map +1 -1
- package/dist/index16.d.ts +2 -2
- package/dist/index16.d.ts.map +1 -1
- package/dist/index17.d.cts +4 -4
- package/dist/index17.d.cts.map +1 -1
- package/dist/index17.d.ts +4 -4
- package/dist/index18.d.cts +11 -11
- package/dist/index18.d.cts.map +1 -1
- package/dist/index18.d.ts +11 -11
- package/dist/index18.d.ts.map +1 -1
- package/dist/index19.d.cts +10 -10
- package/dist/index19.d.cts.map +1 -1
- package/dist/index19.d.ts +10 -10
- package/dist/index19.d.ts.map +1 -1
- package/dist/index2.d.cts +8 -8
- package/dist/index2.d.cts.map +1 -1
- package/dist/index2.d.ts +9 -9
- package/dist/index2.d.ts.map +1 -1
- package/dist/index20.d.cts +16 -16
- package/dist/index20.d.cts.map +1 -1
- package/dist/index20.d.ts +16 -16
- package/dist/index20.d.ts.map +1 -1
- package/dist/index21.d.cts +4 -4
- package/dist/index21.d.cts.map +1 -1
- package/dist/index21.d.ts +4 -4
- package/dist/index21.d.ts.map +1 -1
- package/dist/index22.d.cts +11 -11
- package/dist/index22.d.ts +11 -11
- package/dist/index23.d.cts +16 -16
- package/dist/index23.d.cts.map +1 -1
- package/dist/index23.d.ts +16 -16
- package/dist/index23.d.ts.map +1 -1
- package/dist/index24.d.cts +10 -10
- package/dist/index24.d.cts.map +1 -1
- package/dist/index24.d.ts +11 -11
- package/dist/index24.d.ts.map +1 -1
- package/dist/index25.d.cts +2 -2
- package/dist/index25.d.ts +2 -2
- package/dist/index25.d.ts.map +1 -1
- package/dist/index26.d.cts +13 -13
- package/dist/index26.d.cts.map +1 -1
- package/dist/index26.d.ts +14 -14
- package/dist/index26.d.ts.map +1 -1
- package/dist/index27.d.cts +7 -7
- package/dist/index27.d.cts.map +1 -1
- package/dist/index27.d.ts +7 -7
- package/dist/index27.d.ts.map +1 -1
- package/dist/index28.d.cts +6 -6
- package/dist/index28.d.cts.map +1 -1
- package/dist/index28.d.ts +5 -5
- package/dist/index28.d.ts.map +1 -1
- package/dist/index29.d.cts +4 -4
- package/dist/index29.d.ts +4 -4
- package/dist/index29.d.ts.map +1 -1
- package/dist/index3.d.cts +13 -13
- package/dist/index3.d.cts.map +1 -1
- package/dist/index3.d.ts +13 -13
- package/dist/index30.d.cts +41 -12
- package/dist/index30.d.cts.map +1 -1
- package/dist/index30.d.ts +42 -13
- package/dist/index30.d.ts.map +1 -1
- package/dist/index31.d.cts +5 -5
- package/dist/index31.d.cts.map +1 -1
- package/dist/index31.d.ts +6 -6
- package/dist/index31.d.ts.map +1 -1
- package/dist/index32.d.cts +5 -5
- package/dist/index32.d.cts.map +1 -1
- package/dist/index32.d.ts +6 -6
- package/dist/index33.d.cts +10 -10
- package/dist/index33.d.cts.map +1 -1
- package/dist/index33.d.ts +11 -11
- package/dist/index33.d.ts.map +1 -1
- package/dist/index34.d.cts +5 -5
- package/dist/index34.d.cts.map +1 -1
- package/dist/index34.d.ts +5 -5
- package/dist/index34.d.ts.map +1 -1
- package/dist/index35.d.cts +16 -16
- package/dist/index35.d.cts.map +1 -1
- package/dist/index35.d.ts +17 -17
- package/dist/index35.d.ts.map +1 -1
- package/dist/index36.d.cts +3 -3
- package/dist/index36.d.cts.map +1 -1
- package/dist/index36.d.ts +3 -3
- package/dist/index36.d.ts.map +1 -1
- package/dist/index37.d.cts +5 -5
- package/dist/index37.d.ts +3 -3
- package/dist/index38.d.cts +2 -2
- package/dist/index38.d.cts.map +1 -1
- package/dist/index38.d.ts +2 -2
- package/dist/index39.d.cts +17 -17
- package/dist/index39.d.cts.map +1 -1
- package/dist/index39.d.ts +17 -17
- package/dist/index39.d.ts.map +1 -1
- package/dist/index4.d.cts +2 -2
- package/dist/index4.d.ts +2 -2
- package/dist/index4.d.ts.map +1 -1
- package/dist/index40.d.cts +5 -5
- package/dist/index40.d.cts.map +1 -1
- package/dist/index40.d.ts +6 -6
- package/dist/index40.d.ts.map +1 -1
- package/dist/index41.d.cts +11 -11
- package/dist/index41.d.cts.map +1 -1
- package/dist/index41.d.ts +11 -11
- package/dist/index41.d.ts.map +1 -1
- package/dist/index42.d.cts +8 -8
- package/dist/index42.d.cts.map +1 -1
- package/dist/index42.d.ts +8 -8
- package/dist/index43.d.cts +9 -9
- package/dist/index43.d.cts.map +1 -1
- package/dist/index43.d.ts +9 -9
- package/dist/index43.d.ts.map +1 -1
- package/dist/index45.d.cts +8 -8
- package/dist/index45.d.cts.map +1 -1
- package/dist/index45.d.ts +8 -8
- package/dist/index45.d.ts.map +1 -1
- package/dist/index46.d.cts +2 -2
- package/dist/index46.d.cts.map +1 -1
- package/dist/index46.d.ts +2 -2
- package/dist/index46.d.ts.map +1 -1
- package/dist/index47.d.cts +4 -4
- package/dist/index47.d.cts.map +1 -1
- package/dist/index47.d.ts +4 -4
- package/dist/index47.d.ts.map +1 -1
- package/dist/index48.d.cts +4 -4
- package/dist/index48.d.cts.map +1 -1
- package/dist/index48.d.ts +4 -4
- package/dist/index48.d.ts.map +1 -1
- package/dist/index49.d.cts +3 -3
- package/dist/index49.d.ts +3 -3
- package/dist/index5.d.cts +7 -7
- package/dist/index5.d.ts +7 -7
- package/dist/index50.d.cts +11 -11
- package/dist/index50.d.cts.map +1 -1
- package/dist/index50.d.ts +11 -11
- package/dist/index50.d.ts.map +1 -1
- package/dist/index51.d.cts +9 -9
- package/dist/index51.d.cts.map +1 -1
- package/dist/index51.d.ts +9 -9
- package/dist/index51.d.ts.map +1 -1
- package/dist/index52.d.cts +5 -5
- package/dist/index52.d.ts +5 -5
- package/dist/index53.d.cts +27 -27
- package/dist/index53.d.cts.map +1 -1
- package/dist/index53.d.ts +28 -28
- package/dist/index53.d.ts.map +1 -1
- package/dist/index54.d.cts +5 -5
- package/dist/index54.d.ts +5 -5
- package/dist/index54.d.ts.map +1 -1
- package/dist/index55.d.cts +2 -2
- package/dist/index55.d.cts.map +1 -1
- package/dist/index55.d.ts +2 -2
- package/dist/index55.d.ts.map +1 -1
- package/dist/index56.d.cts +2 -2
- package/dist/index56.d.cts.map +1 -1
- package/dist/index56.d.ts +2 -2
- package/dist/index56.d.ts.map +1 -1
- package/dist/index57.d.cts +2 -2
- package/dist/index57.d.cts.map +1 -1
- package/dist/index57.d.ts +2 -2
- package/dist/index57.d.ts.map +1 -1
- package/dist/index58.d.cts +4 -4
- package/dist/index58.d.cts.map +1 -1
- package/dist/index58.d.ts +4 -4
- package/dist/index58.d.ts.map +1 -1
- package/dist/index59.d.cts +9 -9
- package/dist/index59.d.ts +9 -9
- package/dist/index59.d.ts.map +1 -1
- package/dist/index6.d.cts +5 -5
- package/dist/index6.d.cts.map +1 -1
- package/dist/index6.d.ts +6 -6
- package/dist/index60.d.cts +9 -9
- package/dist/index60.d.ts +9 -9
- package/dist/index60.d.ts.map +1 -1
- package/dist/index61.d.cts +8 -8
- package/dist/index61.d.cts.map +1 -1
- package/dist/index61.d.ts +7 -7
- package/dist/index61.d.ts.map +1 -1
- package/dist/index62.d.cts +4 -4
- package/dist/index62.d.cts.map +1 -1
- package/dist/index62.d.ts +5 -5
- package/dist/index63.d.cts +2 -2
- package/dist/index63.d.ts +2 -2
- package/dist/index64.d.cts +4 -4
- package/dist/index64.d.ts +7 -7
- package/dist/index64.d.ts.map +1 -1
- package/dist/index65.d.cts +3 -3
- package/dist/index65.d.ts +4 -4
- package/dist/index66.d.cts +4 -4
- package/dist/index66.d.ts +5 -5
- package/dist/index67.d.cts +83 -11
- package/dist/index67.d.cts.map +1 -1
- package/dist/index67.d.ts +83 -11
- package/dist/index67.d.ts.map +1 -1
- package/dist/index68.d.cts +12 -30
- package/dist/index68.d.cts.map +1 -1
- package/dist/index68.d.ts +12 -30
- package/dist/index68.d.ts.map +1 -1
- package/dist/index69.d.cts +28 -27
- package/dist/index69.d.cts.map +1 -1
- package/dist/index69.d.ts +29 -28
- package/dist/index69.d.ts.map +1 -1
- package/dist/index7.d.cts +8 -8
- package/dist/index7.d.cts.map +1 -1
- package/dist/index7.d.ts +8 -8
- package/dist/index7.d.ts.map +1 -1
- package/dist/index70.d.cts +33 -78
- package/dist/index70.d.cts.map +1 -1
- package/dist/index70.d.ts +33 -78
- package/dist/index70.d.ts.map +1 -1
- package/dist/index71.d.cts +77 -260
- package/dist/index71.d.cts.map +1 -1
- package/dist/index71.d.ts +77 -260
- package/dist/index71.d.ts.map +1 -1
- package/dist/index72.d.cts +278 -0
- package/dist/index72.d.cts.map +1 -0
- package/dist/index72.d.ts +278 -0
- package/dist/index72.d.ts.map +1 -0
- package/dist/index8.d.cts +4 -4
- package/dist/index8.d.cts.map +1 -1
- package/dist/index8.d.ts +5 -5
- package/dist/index9.d.cts +2 -2
- package/dist/index9.d.cts.map +1 -1
- package/dist/index9.d.ts +2 -2
- package/dist/index9.d.ts.map +1 -1
- package/dist/layouts/Container/index.cjs +2 -1
- package/dist/layouts/Container/index.cjs.map +1 -1
- package/dist/layouts/Container/index.js +1 -1
- package/dist/layouts/MultiColumn/index.cjs +5 -0
- package/dist/layouts/MultiColumn/index.d.cts +2 -0
- package/dist/layouts/MultiColumn/index.d.ts +2 -0
- package/dist/layouts/MultiColumn/index.js +2 -0
- package/dist/layouts/PageBackground/index.d.cts +1 -1
- package/dist/layouts/PageBackground/index.d.ts +1 -1
- package/dist/layouts/Stack/index.cjs +2 -1
- package/dist/layouts/Stack/index.cjs.map +1 -1
- package/dist/layouts/Stack/index.d.cts +1 -1
- package/dist/layouts/Stack/index.d.ts +1 -1
- package/dist/layouts/Stack/index.js +1 -1
- package/dist/layouts/TwoColumn/index.cjs +2 -1
- package/dist/layouts/TwoColumn/index.cjs.map +1 -1
- package/dist/layouts/TwoColumn/index.d.cts +1 -1
- package/dist/layouts/TwoColumn/index.d.ts +1 -1
- package/dist/layouts/TwoColumn/index.js +1 -1
- package/dist/layouts/index.cjs +4 -0
- package/dist/layouts/index.d.cts +5 -4
- package/dist/layouts/index.d.ts +5 -4
- package/dist/layouts/index.js +2 -1
- package/dist/patterns/DataTable/index.cjs +6 -2
- package/dist/patterns/DataTable/index.cjs.map +1 -1
- package/dist/patterns/DataTable/index.d.cts +3 -3
- package/dist/patterns/DataTable/index.d.cts.map +1 -1
- package/dist/patterns/DataTable/index.d.ts +3 -3
- package/dist/patterns/DataTable/index.d.ts.map +1 -1
- package/dist/patterns/DataTable/index.js +6 -2
- package/dist/patterns/DataTable/index.js.map +1 -1
- package/dist/patterns/Footer/index.d.cts +7 -7
- package/dist/patterns/Footer/index.d.cts.map +1 -1
- package/dist/patterns/Footer/index.d.ts +7 -7
- package/dist/patterns/Footer/index.d.ts.map +1 -1
- package/dist/patterns/Header/index.d.cts +1 -1
- package/dist/patterns/Header/index.d.ts +1 -1
- package/dist/patterns/MediaObject/index.cjs +1 -1
- package/dist/patterns/MediaObject/index.d.cts +11 -11
- package/dist/patterns/MediaObject/index.d.ts +12 -12
- package/dist/patterns/MediaObject/index.js +1 -1
- package/dist/patterns/NavRail/index.cjs +4 -2
- package/dist/patterns/NavRail/index.cjs.map +1 -1
- package/dist/patterns/NavRail/index.js +4 -2
- package/dist/patterns/NavRail/index.js.map +1 -1
- package/dist/patterns/SectionCard/index.d.cts +2 -2
- package/dist/patterns/SectionCard/index.d.ts +2 -2
- package/dist/patterns/SectionHeading/index.d.cts +2 -2
- package/dist/patterns/index.d.cts +1 -1
- package/dist/patterns/index.d.ts +1 -1
- package/dist/primitives/Accordion/index.cjs +6 -2
- package/dist/primitives/Accordion/index.cjs.map +1 -1
- package/dist/primitives/Accordion/index.js +6 -2
- package/dist/primitives/Accordion/index.js.map +1 -1
- package/dist/primitives/Alert/index.cjs +2 -1
- package/dist/primitives/Alert/index.cjs.map +1 -1
- package/dist/primitives/Alert/index.js +1 -1
- package/dist/primitives/AlertDialog/index.cjs +1 -1
- package/dist/primitives/AlertDialog/index.js +1 -1
- package/dist/primitives/AspectRatio/index.cjs +1 -1
- package/dist/primitives/AspectRatio/index.js +1 -1
- package/dist/primitives/Avatar/index.cjs +1 -1
- package/dist/primitives/Avatar/index.js +1 -1
- package/dist/primitives/Badge/index.cjs +3 -2
- package/dist/primitives/Badge/index.cjs.map +1 -1
- package/dist/primitives/Badge/index.js +2 -2
- package/dist/primitives/Breadcrumb/index.cjs +7 -3
- package/dist/primitives/Breadcrumb/index.cjs.map +1 -1
- package/dist/primitives/Breadcrumb/index.js +7 -3
- package/dist/primitives/Breadcrumb/index.js.map +1 -1
- package/dist/primitives/Button/index.cjs +3 -2
- package/dist/primitives/Button/index.cjs.map +1 -1
- package/dist/primitives/Button/index.js +2 -2
- package/dist/primitives/ButtonGroup/index.cjs +3 -2
- package/dist/primitives/ButtonGroup/index.cjs.map +1 -1
- package/dist/primitives/ButtonGroup/index.js +2 -2
- package/dist/primitives/Calendar/index.cjs +12 -11
- package/dist/primitives/Calendar/index.cjs.map +1 -1
- package/dist/primitives/Calendar/index.js +12 -11
- package/dist/primitives/Calendar/index.js.map +1 -1
- package/dist/primitives/Card/index.cjs +2 -1
- package/dist/primitives/Card/index.cjs.map +1 -1
- package/dist/primitives/Card/index.js +1 -1
- package/dist/primitives/Carousel/index.cjs +4 -3
- package/dist/primitives/Carousel/index.cjs.map +1 -1
- package/dist/primitives/Carousel/index.js +4 -3
- package/dist/primitives/Carousel/index.js.map +1 -1
- package/dist/primitives/Checkbox/index.cjs +9 -2
- package/dist/primitives/Checkbox/index.cjs.map +1 -1
- package/dist/primitives/Checkbox/index.js +9 -2
- package/dist/primitives/Checkbox/index.js.map +1 -1
- package/dist/primitives/CheckboxTree/index.cjs +6 -2
- package/dist/primitives/CheckboxTree/index.cjs.map +1 -1
- package/dist/primitives/CheckboxTree/index.js +6 -2
- package/dist/primitives/CheckboxTree/index.js.map +1 -1
- package/dist/primitives/Collapsible/index.cjs +1 -1
- package/dist/primitives/Collapsible/index.js +1 -1
- package/dist/primitives/Command/index.cjs +6 -2
- package/dist/primitives/Command/index.cjs.map +1 -1
- package/dist/primitives/Command/index.js +6 -2
- package/dist/primitives/Command/index.js.map +1 -1
- package/dist/primitives/ContextMenu/index.cjs +14 -4
- package/dist/primitives/ContextMenu/index.cjs.map +1 -1
- package/dist/primitives/ContextMenu/index.js +14 -4
- package/dist/primitives/ContextMenu/index.js.map +1 -1
- package/dist/primitives/Credits/index.cjs +8 -3
- package/dist/primitives/Credits/index.cjs.map +1 -1
- package/dist/primitives/Credits/index.js +7 -3
- package/dist/primitives/Credits/index.js.map +1 -1
- package/dist/primitives/Dialog/index.cjs +3 -2
- package/dist/primitives/Dialog/index.cjs.map +1 -1
- package/dist/primitives/Dialog/index.js +3 -2
- package/dist/primitives/Dialog/index.js.map +1 -1
- package/dist/primitives/DropdownMenu/index.cjs +14 -4
- package/dist/primitives/DropdownMenu/index.cjs.map +1 -1
- package/dist/primitives/DropdownMenu/index.js +14 -4
- package/dist/primitives/DropdownMenu/index.js.map +1 -1
- package/dist/primitives/Empty/index.cjs +1 -1
- package/dist/primitives/Empty/index.js +1 -1
- package/dist/primitives/Field/index.cjs +1 -1
- package/dist/primitives/Field/index.js +1 -1
- package/dist/primitives/Form/index.cjs +1 -1
- package/dist/primitives/Form/index.js +1 -1
- package/dist/primitives/Heading/index.cjs +2 -1
- package/dist/primitives/Heading/index.cjs.map +1 -1
- package/dist/primitives/Heading/index.js +1 -1
- package/dist/primitives/HoverCard/index.cjs +1 -1
- package/dist/primitives/HoverCard/index.js +1 -1
- package/dist/primitives/InfoBanner/index.cjs +6 -3
- package/dist/primitives/InfoBanner/index.cjs.map +1 -1
- package/dist/primitives/InfoBanner/index.js +5 -3
- package/dist/primitives/InfoBanner/index.js.map +1 -1
- package/dist/primitives/Input/index.cjs +2 -1
- package/dist/primitives/Input/index.cjs.map +1 -1
- package/dist/primitives/Input/index.js +1 -1
- package/dist/primitives/InputGroup/index.cjs +1 -1
- package/dist/primitives/InputGroup/index.js +1 -1
- package/dist/primitives/InputOtp/index.cjs +3 -2
- package/dist/primitives/InputOtp/index.cjs.map +1 -1
- package/dist/primitives/InputOtp/index.js +3 -2
- package/dist/primitives/InputOtp/index.js.map +1 -1
- package/dist/primitives/Item/index.cjs +2 -2
- package/dist/primitives/Item/index.js +2 -2
- package/dist/primitives/Label/index.cjs +1 -1
- package/dist/primitives/Label/index.js +1 -1
- package/dist/primitives/Link/index.cjs +3 -2
- package/dist/primitives/Link/index.cjs.map +1 -1
- package/dist/primitives/Link/index.js +2 -2
- package/dist/primitives/Menubar/index.cjs +14 -4
- package/dist/primitives/Menubar/index.cjs.map +1 -1
- package/dist/primitives/Menubar/index.js +14 -4
- package/dist/primitives/Menubar/index.js.map +1 -1
- package/dist/primitives/NativeSelect/index.cjs +6 -3
- package/dist/primitives/NativeSelect/index.cjs.map +1 -1
- package/dist/primitives/NativeSelect/index.js +5 -3
- package/dist/primitives/NativeSelect/index.js.map +1 -1
- package/dist/primitives/NavigationMenu/index.cjs +5 -3
- package/dist/primitives/NavigationMenu/index.cjs.map +1 -1
- package/dist/primitives/NavigationMenu/index.js +5 -3
- package/dist/primitives/NavigationMenu/index.js.map +1 -1
- package/dist/primitives/Pagination/index.cjs +6 -2
- package/dist/primitives/Pagination/index.cjs.map +1 -1
- package/dist/primitives/Pagination/index.js +6 -2
- package/dist/primitives/Pagination/index.js.map +1 -1
- package/dist/primitives/Popover/index.cjs +1 -1
- package/dist/primitives/Popover/index.js +1 -1
- package/dist/primitives/Progress/index.cjs +1 -1
- package/dist/primitives/Progress/index.js +1 -1
- package/dist/primitives/RadioGroup/index.cjs +6 -2
- package/dist/primitives/RadioGroup/index.cjs.map +1 -1
- package/dist/primitives/RadioGroup/index.js +6 -2
- package/dist/primitives/RadioGroup/index.js.map +1 -1
- package/dist/primitives/Resizable/index.cjs +6 -2
- package/dist/primitives/Resizable/index.cjs.map +1 -1
- package/dist/primitives/Resizable/index.js +6 -2
- package/dist/primitives/Resizable/index.js.map +1 -1
- package/dist/primitives/ScrollArea/index.cjs +1 -1
- package/dist/primitives/ScrollArea/index.js +1 -1
- package/dist/primitives/Select/index.cjs +18 -5
- package/dist/primitives/Select/index.cjs.map +1 -1
- package/dist/primitives/Select/index.js +18 -5
- package/dist/primitives/Select/index.js.map +1 -1
- package/dist/primitives/Separator/index.cjs +1 -1
- package/dist/primitives/Separator/index.js +1 -1
- package/dist/primitives/Sheet/index.cjs +6 -2
- package/dist/primitives/Sheet/index.cjs.map +1 -1
- package/dist/primitives/Sheet/index.js +6 -2
- package/dist/primitives/Sheet/index.js.map +1 -1
- package/dist/primitives/Slider/index.cjs +1 -1
- package/dist/primitives/Slider/index.js +1 -1
- package/dist/primitives/Sonner/index.cjs +22 -6
- package/dist/primitives/Sonner/index.cjs.map +1 -1
- package/dist/primitives/Sonner/index.js +22 -6
- package/dist/primitives/Sonner/index.js.map +1 -1
- package/dist/primitives/Spinner/index.cjs +4 -2
- package/dist/primitives/Spinner/index.cjs.map +1 -1
- package/dist/primitives/Spinner/index.js +4 -2
- package/dist/primitives/Spinner/index.js.map +1 -1
- package/dist/primitives/Switch/index.cjs +1 -1
- package/dist/primitives/Switch/index.js +1 -1
- package/dist/primitives/Tabs/index.cjs +2 -2
- package/dist/primitives/Tabs/index.js +2 -2
- package/dist/primitives/Text/index.cjs +2 -1
- package/dist/primitives/Text/index.cjs.map +1 -1
- package/dist/primitives/Text/index.js +1 -1
- package/dist/primitives/Textarea/index.cjs +2 -1
- package/dist/primitives/Textarea/index.cjs.map +1 -1
- package/dist/primitives/Textarea/index.js +1 -1
- package/dist/primitives/Toggle/index.cjs +3 -2
- package/dist/primitives/Toggle/index.cjs.map +1 -1
- package/dist/primitives/Toggle/index.js +2 -2
- package/dist/primitives/ToggleGroup/index.cjs +1 -1
- package/dist/primitives/ToggleGroup/index.js +1 -1
- package/dist/primitives/Tooltip/index.cjs +1 -1
- package/dist/primitives/Tooltip/index.js +1 -1
- package/dist/primitives/index.cjs +1 -1
- package/dist/primitives/index.js +1 -1
- package/package.json +2 -1
package/SKILL.md
CHANGED
|
@@ -12,18 +12,44 @@ component catalog, full token inventory, theming model — is in
|
|
|
12
12
|
|
|
13
13
|
## Decision order
|
|
14
14
|
|
|
15
|
+
Work down this ladder in order — each step is only allowed after the one above it
|
|
16
|
+
demonstrably can't produce the design:
|
|
17
|
+
|
|
15
18
|
1. **Pattern first**: does a pattern (`patterns/Header`, `DataTable`, `Footer`,
|
|
16
19
|
`SectionCard`, `SectionHeading`, `MediaObject`) or layout (`Container`, `Stack`,
|
|
17
|
-
`TwoColumn`, `PageBackground`) already solve it? Use it.
|
|
20
|
+
`TwoColumn`, `MultiColumn`, `PageBackground`) already solve it? Use it.
|
|
18
21
|
2. **Primitive second**: compose from `primitives/*` (64 of them — check the catalog
|
|
19
22
|
in DESIGN.md §6 before writing anything custom).
|
|
20
|
-
3. **
|
|
21
|
-
|
|
23
|
+
3. **Stock rendering**: render the chosen component with its variants/props as
|
|
24
|
+
designed. Pick the variant from its "Choosing a variant" table in DESIGN.md
|
|
25
|
+
(intent + light/dark look + tell) — don't guess from the variant name.
|
|
26
|
+
4. **Layout tweaks only**: `className` may place and size the component in its
|
|
27
|
+
context — margin, width, flex/grid placement, alignment. It must never repaint
|
|
28
|
+
it (no `bg-*`/`text-*` color/`border-*` color/`hover:*` on a variant).
|
|
29
|
+
5. **Exception — last resort, and marked**: only when 1–4 can't get there:
|
|
30
|
+
- **Component missing from the DS** → build custom from token utilities only
|
|
31
|
+
(tokens, px-named radii, `ring-focus`; never raw colors, never `dark:`,
|
|
32
|
+
never a parallel component that shadows an existing one).
|
|
33
|
+
- **Component exists but no variant fits** → do NOT re-skin it (see the
|
|
34
|
+
anti-pattern below); add or request a variant. If you must ship now, mark
|
|
35
|
+
the deviation at the call site so it stays auditable:
|
|
36
|
+
`// DS-EXCEPTION: <why> — <what the DS should provide instead>`
|
|
37
|
+
|
|
38
|
+
Every `DS-EXCEPTION` is a design-system backlog item — sweep them with
|
|
39
|
+
`grep -rn "DS-EXCEPTION"` and either upstream the need into a real
|
|
40
|
+
variant/component or remove the deviation. Exceptions feed the DS; they must
|
|
41
|
+
never silently erode it.
|
|
22
42
|
|
|
23
43
|
Import per subpath: `@psnext/design-system/primitives/Button`. The DS bundles Radix,
|
|
24
44
|
cva, lucide-react, recharts, sonner, react-hook-form, zod — import primitives from the
|
|
25
|
-
DS, not from those libraries directly (exception: `toast()` from `"sonner"
|
|
26
|
-
|
|
45
|
+
DS, not from those libraries directly (exception: `toast()` from `"sonner"`).
|
|
46
|
+
|
|
47
|
+
**Icons**: prefer the DS `Icon` — `<Icon icon="search" />` (typed lucide name, lazy /
|
|
48
|
+
code-split) for content icons, or `<Icon as={Search} />` (sync, bare `<svg>`) with a
|
|
49
|
+
lucide **or a custom** icon component, e.g. inside a component's icon slot. `Icon`
|
|
50
|
+
inherits the surrounding text color by default, so it's correct on a Button; pass
|
|
51
|
+
`color` or a `text-*` class to override. Raw `lucide-react` icons still work as icon-slot
|
|
52
|
+
children (`<Button><Search /></Button>`) — those slots style a direct-child `[&>svg]`.
|
|
27
53
|
|
|
28
54
|
## Class-writing rules (do / don't)
|
|
29
55
|
|
|
@@ -38,10 +64,41 @@ DS, not from those libraries directly (exception: `toast()` from `"sonner"`, and
|
|
|
38
64
|
| `text-danger-txt` for errors | `text-destructive`, `text-red-500` | severity family is info/success/warning/danger |
|
|
39
65
|
| `cn(...)` from the DS for merged classes | template-string concat | cn's tailwind-merge knows the numeric radius scale |
|
|
40
66
|
| suffix matches property: `bg-*-bg`, `text-*-txt` | `text-primary-bg` | token suffix encodes the valid context |
|
|
67
|
+
| pick the variant that already looks right | re-skin a variant with paint classes | variants bundle hover/active/focus states — overrides break them (see below) |
|
|
41
68
|
|
|
42
69
|
Figma → code: px ÷ 4 = spacing step (16px → `p-4`); radius px maps 1:1 (`rounded-12`);
|
|
43
70
|
heading levels map to `<Heading size={n}>`.
|
|
44
71
|
|
|
72
|
+
## Never re-skin a variant (anti-pattern)
|
|
73
|
+
|
|
74
|
+
A component variant is a **package deal**: rest + hover + active + focus + disabled
|
|
75
|
+
states, tuned together. Overriding its paint with `className` only changes the rest
|
|
76
|
+
state — the interaction states still belong to the original variant, and the result
|
|
77
|
+
is visibly broken.
|
|
78
|
+
|
|
79
|
+
Real failure seen in the wild:
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
// ✗ WRONG — outline button "made primary" with a bg override
|
|
83
|
+
<Button variant="outline" className="bg-primary-invert-bg text-primary-invert-txt">
|
|
84
|
+
// Looks primary at rest. On hover, outline's own hover:bg-outline-hover-bg fires
|
|
85
|
+
// and the fill flickers to a translucent gray — broken hover, broken contrast.
|
|
86
|
+
|
|
87
|
+
// ✓ RIGHT — that look already exists as a variant
|
|
88
|
+
<Button variant="default">
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Rules:
|
|
92
|
+
|
|
93
|
+
- **`className` on a DS component is for layout only** — margin, width, flex/grid
|
|
94
|
+
placement, alignment. Never for paint: `bg-*`, `text-*` color, `border-*` color,
|
|
95
|
+
`hover:*`, `rounded-*` that fight the variant.
|
|
96
|
+
- **If the look you want isn't a variant, that's a DS gap** — don't patch it at the
|
|
97
|
+
call site. Add/request a variant (cva) so the states are designed together.
|
|
98
|
+
- This applies to **every** cva-styled component (Button, Badge, Tabs, Card, Alert, …),
|
|
99
|
+
not just Button. If you catch yourself writing a paint class on one, stop and check
|
|
100
|
+
the component's variant table in DESIGN.md first.
|
|
101
|
+
|
|
45
102
|
## Recipes
|
|
46
103
|
|
|
47
104
|
**Page scaffold**
|
|
@@ -85,6 +142,27 @@ tokens inside flip; do not hand-pick dark colors.
|
|
|
85
142
|
with `cn`); don't wrap in extra divs to fight specificity.
|
|
86
143
|
- **`!important` on library-styled elements** (e.g. toast classNames) will override
|
|
87
144
|
richColors/severity styling — scope with `data-[type=…]` variants instead.
|
|
145
|
+
- **App-defined `@layer base` wiping the tokens**: an app that declares its own
|
|
146
|
+
base-layer `:root`/`body` rules (or a reset) can silently override the DS token
|
|
147
|
+
variables — every component then renders colorless while classes look correct.
|
|
148
|
+
Don't redefine base-layer custom properties; put app-level overrides *after* the
|
|
149
|
+
DS styles import, outside `@layer base`.
|
|
150
|
+
|
|
151
|
+
**If the DS token variables are missing entirely** (components render but
|
|
152
|
+
`--primary-bg` etc. aren't on `:root`), walk this tree in order:
|
|
153
|
+
|
|
154
|
+
1. Devtools → inspect `<html>` → computed styles → search `--primary-bg`.
|
|
155
|
+
Present? The tokens are fine — suspect a wrong class name or missing `@source`.
|
|
156
|
+
2. Absent → check the Tailwind entry CSS: `@import "tailwindcss"` then
|
|
157
|
+
`@import "@psnext/design-system/styles"`, and **all `@import`s before any other
|
|
158
|
+
statement** (including `@source` — a misplaced import can abort the rest).
|
|
159
|
+
3. Confirm Tailwind is **v4** and this file is actually compiled by
|
|
160
|
+
`@tailwindcss/vite` / `@tailwindcss/postcss` (not served as plain CSS).
|
|
161
|
+
4. Check nothing *later* redefines the vars: app `@layer base` blocks, resets, or
|
|
162
|
+
`:root` rules after the import (see the pitfall above — this has happened).
|
|
163
|
+
5. Isolation test: `@import "@psnext/design-system/dist/styles/tokens/mode-light.css"`.
|
|
164
|
+
If vars appear now, the `/styles` subpath isn't resolving in your bundler —
|
|
165
|
+
report that, don't ship the workaround.
|
|
88
166
|
- **Logo**: never recolor; wordmark ink follows mode automatically; no ThemeProvider
|
|
89
167
|
needed.
|
|
90
168
|
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
// Install the design-system agent docs (SKILL.md + DESIGN.md) into a consumer
|
|
3
3
|
// project as an Agent Skill, so coding agents load them for UI work.
|
|
4
4
|
//
|
|
5
|
-
// npx @psnext/design-system → .
|
|
5
|
+
// npx @psnext/design-system → .agent/skills/design-system/
|
|
6
6
|
// npx @psnext/design-system <dir> → <dir>/ (explicit destination)
|
|
7
7
|
//
|
|
8
8
|
// The two docs are copied verbatim from the installed package; SKILL.md links to
|
|
9
9
|
// DESIGN.md as a sibling, so they must land in the same folder (this does that).
|
|
10
10
|
|
|
11
|
-
import { copyFileSync, existsSync, mkdirSync } from "node:fs";
|
|
12
|
-
import { dirname, join, resolve } from "node:path";
|
|
11
|
+
import { copyFileSync, existsSync, mkdirSync, statSync } from "node:fs";
|
|
12
|
+
import { dirname, join, resolve, sep } from "node:path";
|
|
13
13
|
import { fileURLToPath } from "node:url";
|
|
14
14
|
|
|
15
15
|
const PKG_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
@@ -20,7 +20,7 @@ if (args.includes("--help") || args.includes("-h")) {
|
|
|
20
20
|
console.log(`Install @psnext/design-system agent docs as an Agent Skill.
|
|
21
21
|
|
|
22
22
|
Usage:
|
|
23
|
-
npx @psnext/design-system Copy SKILL.md + DESIGN.md into .
|
|
23
|
+
npx @psnext/design-system Copy SKILL.md + DESIGN.md into .agent/skills/design-system/
|
|
24
24
|
npx @psnext/design-system <dir> Copy into an explicit destination folder
|
|
25
25
|
npx @psnext/design-system --help Show this help
|
|
26
26
|
|
|
@@ -32,7 +32,7 @@ The agent then loads the skill when writing or reviewing UI in this project.`);
|
|
|
32
32
|
const positional = args.find((a) => !a.startsWith("-"));
|
|
33
33
|
const dest = positional
|
|
34
34
|
? resolve(process.cwd(), positional)
|
|
35
|
-
: resolve(process.cwd(), ".
|
|
35
|
+
: resolve(process.cwd(), ".agent/skills/design-system");
|
|
36
36
|
|
|
37
37
|
for (const doc of DOCS) {
|
|
38
38
|
const src = join(PKG_ROOT, doc);
|
|
@@ -42,13 +42,45 @@ for (const doc of DOCS) {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
// Whether the skill was already installed here (a re-run just refreshes the two
|
|
46
|
+
// docs in place) — checked before we create anything.
|
|
47
|
+
const isRefresh = DOCS.every((doc) => existsSync(join(dest, doc)));
|
|
48
|
+
|
|
49
|
+
// Validate/create the destination one level at a time (for the default that's
|
|
50
|
+
// .agent → skills → design-system): reuse a folder that already exists, create
|
|
51
|
+
// the ones that don't, and bail with a clear message if a segment is occupied
|
|
52
|
+
// by a file — otherwise mkdir would fail cryptically. Only walk segments under
|
|
53
|
+
// the cwd; anything outside falls through to the recursive mkdir below.
|
|
54
|
+
const chain = [];
|
|
55
|
+
for (let cur = dest; cur.startsWith(process.cwd() + sep); cur = dirname(cur)) {
|
|
56
|
+
chain.unshift(cur);
|
|
57
|
+
}
|
|
58
|
+
for (const dir of chain) {
|
|
59
|
+
if (existsSync(dir)) {
|
|
60
|
+
if (!statSync(dir).isDirectory()) {
|
|
61
|
+
console.error(`✗ ${dir} already exists but is not a directory — move it aside and re-run.`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
continue; // reuse the existing folder
|
|
65
|
+
}
|
|
66
|
+
mkdirSync(dir); // parent already ensured by the outer→inner order
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
mkdirSync(dest, { recursive: true }); // covers a destination outside the cwd
|
|
71
|
+
} catch (err) {
|
|
72
|
+
console.error(`✗ Could not create ${dest}: ${err.message}`);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
|
|
46
76
|
for (const doc of DOCS) {
|
|
47
77
|
copyFileSync(join(PKG_ROOT, doc), join(dest, doc));
|
|
48
78
|
}
|
|
49
79
|
|
|
50
80
|
const rel = dest.startsWith(process.cwd()) ? `.${dest.slice(process.cwd().length)}` : dest;
|
|
51
|
-
console.log(
|
|
81
|
+
console.log(
|
|
82
|
+
`✓ ${isRefresh ? "Refreshed" : "Installed"} @psnext/design-system agent skill → ${rel}/`,
|
|
83
|
+
);
|
|
52
84
|
console.log(" • SKILL.md — workflow playbook (the Agent Skill entry point)");
|
|
53
85
|
console.log(" • DESIGN.md — full token + component reference");
|
|
54
86
|
console.log("\nRe-run this after upgrading the package to refresh the docs.");
|
package/dist/Header.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const require_chunk = require("./chunk.cjs");
|
|
2
2
|
const require_cn = require("./cn.cjs");
|
|
3
|
+
const require_Icon = require("./Icon.cjs");
|
|
3
4
|
const require_primitives_Button_index = require("./primitives/Button/index.cjs");
|
|
4
5
|
const require_primitives_Avatar_index = require("./primitives/Avatar/index.cjs");
|
|
5
6
|
const require_primitives_Credits_index = require("./primitives/Credits/index.cjs");
|
|
@@ -12,8 +13,8 @@ const require_primitives_ThemeProvider_index = require("./primitives/ThemeProvid
|
|
|
12
13
|
let react = require("react");
|
|
13
14
|
let react$1 = require_chunk.__toESM(react, 1);
|
|
14
15
|
react = require_chunk.__toESM(react);
|
|
15
|
-
let lucide_react = require("lucide-react");
|
|
16
16
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
17
|
+
let lucide_react = require("lucide-react");
|
|
17
18
|
let _tanstack_react_query = require("@tanstack/react-query");
|
|
18
19
|
//#region src/patterns/Header/project-tree.ts
|
|
19
20
|
/** True when a node with the given id exists anywhere in the tree. */
|
|
@@ -77,7 +78,10 @@ function ProjectPicker({ projectsTree, selectedProjectId, selectedProjectName, o
|
|
|
77
78
|
children: [projectLabel, ":"]
|
|
78
79
|
}),
|
|
79
80
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_primitives_Skeleton_index.Skeleton, { className: "h-3 flex-1" }),
|
|
80
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
81
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Icon.Icon, {
|
|
82
|
+
as: lucide_react.ChevronDown,
|
|
83
|
+
className: "size-4 shrink-0 text-muted-txt opacity-40"
|
|
84
|
+
})
|
|
81
85
|
]
|
|
82
86
|
});
|
|
83
87
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_primitives_Popover_index.Popover, {
|
|
@@ -98,7 +102,10 @@ function ProjectPicker({ projectsTree, selectedProjectId, selectedProjectName, o
|
|
|
98
102
|
className: require_cn.cn("max-w-36 truncate", selectedName ? "font-medium" : "text-muted-txt"),
|
|
99
103
|
children: selectedName ?? projectPlaceholder
|
|
100
104
|
}),
|
|
101
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
105
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Icon.Icon, {
|
|
106
|
+
as: lucide_react.ChevronDown,
|
|
107
|
+
className: "ml-1 size-4 shrink-0 text-muted-txt"
|
|
108
|
+
})
|
|
102
109
|
]
|
|
103
110
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_primitives_Popover_index.PopoverContent, {
|
|
104
111
|
align: "start",
|
|
@@ -109,7 +116,10 @@ function ProjectPicker({ projectsTree, selectedProjectId, selectedProjectName, o
|
|
|
109
116
|
className: "border-b p-2",
|
|
110
117
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
111
118
|
className: "relative",
|
|
112
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
119
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Icon.Icon, {
|
|
120
|
+
as: lucide_react.Search,
|
|
121
|
+
className: "absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2 text-muted-txt"
|
|
122
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_primitives_Input_index.Input, {
|
|
113
123
|
size: "sm",
|
|
114
124
|
className: "pl-8",
|
|
115
125
|
placeholder: searchPlaceholder,
|
|
@@ -151,7 +161,13 @@ function TreeNode({ node, depth, selectedId, onSelect, collapsedIds, onToggleCol
|
|
|
151
161
|
"aria-label": isCollapsed ? `Expand ${node.name}` : `Collapse ${node.name}`,
|
|
152
162
|
onClick: () => onToggleCollapse(node.id),
|
|
153
163
|
className: "shrink-0 text-muted-txt hover:text-primary-txt",
|
|
154
|
-
children: isCollapsed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
164
|
+
children: isCollapsed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Icon.Icon, {
|
|
165
|
+
as: lucide_react.ChevronRight,
|
|
166
|
+
className: "size-3.5"
|
|
167
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Icon.Icon, {
|
|
168
|
+
as: lucide_react.ChevronDown,
|
|
169
|
+
className: "size-3.5"
|
|
170
|
+
})
|
|
155
171
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "inline-block w-3.5 shrink-0" }),
|
|
156
172
|
node.isContextOnly ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
157
173
|
className: "flex-1 text-left",
|
|
@@ -162,7 +178,10 @@ function TreeNode({ node, depth, selectedId, onSelect, collapsedIds, onToggleCol
|
|
|
162
178
|
className: "flex-1 text-left",
|
|
163
179
|
children: node.name
|
|
164
180
|
}),
|
|
165
|
-
isSelected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
181
|
+
isSelected && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Icon.Icon, {
|
|
182
|
+
as: lucide_react.Check,
|
|
183
|
+
className: "ml-auto size-3.5 shrink-0 text-primary"
|
|
184
|
+
})
|
|
166
185
|
]
|
|
167
186
|
}), !isCollapsed && hasChildren && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
168
187
|
role: "group",
|
|
@@ -189,8 +208,8 @@ const DEFAULT_LABELS = {
|
|
|
189
208
|
profileMenuLabel: "Profile menu",
|
|
190
209
|
logoutLabel: "Logout"
|
|
191
210
|
};
|
|
192
|
-
|
|
193
|
-
|
|
211
|
+
/** Hard cap on project pages fetched — guards against a runaway loop. */
|
|
212
|
+
const PROJECTS_MAX_PAGES = 40;
|
|
194
213
|
const PATHS = {
|
|
195
214
|
token: "/api/v1/studio-auth/sessions/token",
|
|
196
215
|
logout: "/api/v1/studio-auth/sessions/logout",
|
|
@@ -215,16 +234,77 @@ async function fetchToken(endpoints, fetcher) {
|
|
|
215
234
|
const { accessToken } = await res.json();
|
|
216
235
|
return accessToken;
|
|
217
236
|
}
|
|
237
|
+
/**
|
|
238
|
+
* Return `url` with the `page` query param set to the given page (and `limit`
|
|
239
|
+
* backfilled when absent). Pagination stays owned by the header: host-provided
|
|
240
|
+
* endpoint URLs don't need — and can't break — the paging params. Handles
|
|
241
|
+
* absolute and relative URLs.
|
|
242
|
+
*/
|
|
243
|
+
function withPageParam(url, page) {
|
|
244
|
+
const isAbsolute = /^[a-z][a-z0-9+.-]*:\/\//i.test(url);
|
|
245
|
+
try {
|
|
246
|
+
const u = new URL(url, isAbsolute ? void 0 : "http://relative.invalid");
|
|
247
|
+
u.searchParams.set("page", String(page));
|
|
248
|
+
if (!u.searchParams.has("limit")) u.searchParams.set("limit", String(50));
|
|
249
|
+
return isAbsolute ? u.toString() : `${u.pathname}${u.search}${u.hash}`;
|
|
250
|
+
} catch {
|
|
251
|
+
return url;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/** The `limit` query param already on a URL, else the default page size. */
|
|
255
|
+
function readLimitParam(url) {
|
|
256
|
+
try {
|
|
257
|
+
const limit = Number(new URL(url, "http://relative.invalid").searchParams.get("limit"));
|
|
258
|
+
return Number.isInteger(limit) && limit > 0 ? limit : 50;
|
|
259
|
+
} catch {
|
|
260
|
+
return 50;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/** Total node count in a tree page (roots + descendants). */
|
|
264
|
+
function countNodes(tree) {
|
|
265
|
+
return tree.reduce((sum, node) => sum + 1 + countNodes(node.children ?? []), 0);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Merge a page's tree into the accumulated tree. Nodes repeated across pages
|
|
269
|
+
* (e.g. a context-only ancestor whose children span a page boundary) are
|
|
270
|
+
* merged by id instead of duplicated.
|
|
271
|
+
*/
|
|
272
|
+
function mergeTrees(into, page) {
|
|
273
|
+
for (const node of page) {
|
|
274
|
+
const existing = into.find((n) => n.id === node.id);
|
|
275
|
+
if (existing) mergeTrees(existing.children, node.children ?? []);
|
|
276
|
+
else into.push({
|
|
277
|
+
...node,
|
|
278
|
+
children: [...node.children ?? []]
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Fetch ALL pages of the paginated projects endpoint and merge them into a
|
|
284
|
+
* single tree, so users with more projects than one page still see everything.
|
|
285
|
+
* The response carries no pagination metadata, so the first page that comes
|
|
286
|
+
* back with fewer than `limit` nodes is treated as the last one.
|
|
287
|
+
*/
|
|
218
288
|
async function fetchProjects(endpoints, clientId, accessToken, fetcher) {
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
289
|
+
const projectsTree = [];
|
|
290
|
+
let organizationName;
|
|
291
|
+
const baseUrl = endpoints.projects(clientId);
|
|
292
|
+
const pageLimit = readLimitParam(baseUrl);
|
|
293
|
+
for (let page = 1; page <= PROJECTS_MAX_PAGES; page++) {
|
|
294
|
+
const res = await fetcher(withPageParam(baseUrl, page), {
|
|
295
|
+
credentials: "include",
|
|
296
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
297
|
+
});
|
|
298
|
+
if (!res.ok) throw new Error(`projects request failed: ${res.status}`);
|
|
299
|
+
const body = await res.json();
|
|
300
|
+
const pageTree = body.response?.data?.projectsTree ?? [];
|
|
301
|
+
mergeTrees(projectsTree, pageTree);
|
|
302
|
+
organizationName ??= body.response?.data?.organization?.name;
|
|
303
|
+
if (countNodes(pageTree) < pageLimit) break;
|
|
304
|
+
}
|
|
225
305
|
return {
|
|
226
|
-
projectsTree
|
|
227
|
-
organizationName
|
|
306
|
+
projectsTree,
|
|
307
|
+
organizationName
|
|
228
308
|
};
|
|
229
309
|
}
|
|
230
310
|
async function fetchCredits(endpoints, accessToken, fetcher) {
|
|
@@ -249,6 +329,7 @@ async function callLogout(endpoints, fetcher) {
|
|
|
249
329
|
//#region src/patterns/Header/storage.ts
|
|
250
330
|
const PROJECT_KEY = "ds-header-project";
|
|
251
331
|
const LAST_PROJECT_KEY = "lastSelectedProject";
|
|
332
|
+
const PROJECTS_CACHE_KEY = "ds-header-projects-cache";
|
|
252
333
|
function getStoredProject() {
|
|
253
334
|
try {
|
|
254
335
|
const raw = sessionStorage.getItem(PROJECT_KEY);
|
|
@@ -281,6 +362,38 @@ function setLastSelectedProject(project) {
|
|
|
281
362
|
localStorage.setItem(LAST_PROJECT_KEY, JSON.stringify(project));
|
|
282
363
|
} catch {}
|
|
283
364
|
}
|
|
365
|
+
function projectsCacheKey(clientId, userId) {
|
|
366
|
+
return `${PROJECTS_CACHE_KEY}:${clientId}:${userId}`;
|
|
367
|
+
}
|
|
368
|
+
/** The session-cached projects result for this client + user, or null on miss. */
|
|
369
|
+
function getCachedProjects(clientId, userId) {
|
|
370
|
+
try {
|
|
371
|
+
const raw = sessionStorage.getItem(projectsCacheKey(clientId, userId));
|
|
372
|
+
if (!raw) return null;
|
|
373
|
+
const cached = JSON.parse(raw);
|
|
374
|
+
if (!Array.isArray(cached.projectsTree)) return null;
|
|
375
|
+
return {
|
|
376
|
+
projectsTree: cached.projectsTree,
|
|
377
|
+
organizationName: cached.organizationName
|
|
378
|
+
};
|
|
379
|
+
} catch {
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
function setCachedProjects(clientId, userId, data) {
|
|
384
|
+
try {
|
|
385
|
+
sessionStorage.setItem(projectsCacheKey(clientId, userId), JSON.stringify(data));
|
|
386
|
+
} catch {}
|
|
387
|
+
}
|
|
388
|
+
/** Drop every cached projects entry (all clients/users) — used on logout. */
|
|
389
|
+
function clearCachedProjects() {
|
|
390
|
+
try {
|
|
391
|
+
for (let i = sessionStorage.length - 1; i >= 0; i--) {
|
|
392
|
+
const key = sessionStorage.key(i);
|
|
393
|
+
if (key?.startsWith(PROJECTS_CACHE_KEY)) sessionStorage.removeItem(key);
|
|
394
|
+
}
|
|
395
|
+
} catch {}
|
|
396
|
+
}
|
|
284
397
|
//#endregion
|
|
285
398
|
//#region src/patterns/Header/header-store.ts
|
|
286
399
|
function initialState() {
|
|
@@ -464,7 +577,7 @@ function isSessionValid(environmentId) {
|
|
|
464
577
|
const TOGGLE_PROJECT_DROPDOWN_EVENT = "toggle-project-dropdown";
|
|
465
578
|
const DEFAULT_STALE_TIME = 5 * 6e4;
|
|
466
579
|
const DEFAULT_GC_TIME = 10 * 6e4;
|
|
467
|
-
function useGlobalHeader({ apiBaseUrl, environmentId, clientId, _dangerouslyInjectAccessToken: injectedToken, showProjectDropdown = false, showProfile = false, showOrg = false, showCredits = false, endpoints: endpointOverrides, fetcher: fetcherProp, staleTime = DEFAULT_STALE_TIME, gcTime = DEFAULT_GC_TIME, onProjectChange }) {
|
|
580
|
+
function useGlobalHeader({ apiBaseUrl, environmentId, clientId, defaultProjectId, _dangerouslyInjectAccessToken: injectedToken, showProjectDropdown = false, showProfile = false, showOrg = false, showCredits = false, endpoints: endpointOverrides, fetcher: fetcherProp, staleTime = DEFAULT_STALE_TIME, gcTime = DEFAULT_GC_TIME, onProjectChange }) {
|
|
468
581
|
const fetcher = react$1.useMemo(() => fetcherProp ?? ((input, init) => fetch(input, init)), [fetcherProp]);
|
|
469
582
|
const endpoints = react$1.useMemo(() => buildEndpoints(apiBaseUrl, endpointOverrides), [apiBaseUrl, endpointOverrides]);
|
|
470
583
|
const isAuthenticated = isSessionValid(environmentId);
|
|
@@ -482,15 +595,25 @@ function useGlobalHeader({ apiBaseUrl, environmentId, clientId, _dangerouslyInje
|
|
|
482
595
|
});
|
|
483
596
|
const token = injectedToken ?? tokenQuery.data;
|
|
484
597
|
const effectiveClientId = clientId ?? claims?.clientId;
|
|
598
|
+
const wantsProjects = showProjectDropdown || showOrg;
|
|
599
|
+
const userId = claims?.userId ?? "";
|
|
485
600
|
const projectsQuery = (0, _tanstack_react_query.useQuery)({
|
|
486
601
|
queryKey: [
|
|
487
602
|
"ds-header",
|
|
488
603
|
"projects",
|
|
489
604
|
effectiveClientId,
|
|
605
|
+
userId,
|
|
490
606
|
token
|
|
491
607
|
],
|
|
492
|
-
queryFn: () =>
|
|
493
|
-
|
|
608
|
+
queryFn: async () => {
|
|
609
|
+
const id = effectiveClientId;
|
|
610
|
+
const cached = getCachedProjects(id, userId);
|
|
611
|
+
if (cached) return cached;
|
|
612
|
+
const fresh = await fetchProjects(endpoints, id, token, fetcher);
|
|
613
|
+
setCachedProjects(id, userId, fresh);
|
|
614
|
+
return fresh;
|
|
615
|
+
},
|
|
616
|
+
enabled: isAuthenticated && !!token && !!effectiveClientId && wantsProjects,
|
|
494
617
|
staleTime,
|
|
495
618
|
gcTime
|
|
496
619
|
});
|
|
@@ -535,6 +658,9 @@ function useGlobalHeader({ apiBaseUrl, environmentId, clientId, _dangerouslyInje
|
|
|
535
658
|
const fallback = last && nodeExistsInTree(tree, last.id) ? {
|
|
536
659
|
id: last.id,
|
|
537
660
|
name: findProjectName(tree, last.id) ?? last.name
|
|
661
|
+
} : defaultProjectId && nodeExistsInTree(tree, defaultProjectId) ? {
|
|
662
|
+
id: defaultProjectId,
|
|
663
|
+
name: findProjectName(tree, defaultProjectId) ?? ""
|
|
538
664
|
} : firstSelectableProject(tree);
|
|
539
665
|
if (fallback) {
|
|
540
666
|
headerStore.setProject(fallback.id, fallback.name, effectiveClientId, { remember: false });
|
|
@@ -542,7 +668,11 @@ function useGlobalHeader({ apiBaseUrl, environmentId, clientId, _dangerouslyInje
|
|
|
542
668
|
} else if (id) headerStore.clearProject();
|
|
543
669
|
}
|
|
544
670
|
headerStore.setOrganization(projectsQuery.data.organizationName, effectiveClientId);
|
|
545
|
-
}, [
|
|
671
|
+
}, [
|
|
672
|
+
projectsQuery.data,
|
|
673
|
+
effectiveClientId,
|
|
674
|
+
defaultProjectId
|
|
675
|
+
]);
|
|
546
676
|
react$1.useEffect(() => {
|
|
547
677
|
if (creditsQuery.data !== void 0) headerStore.setCredits(creditsQuery.data);
|
|
548
678
|
}, [creditsQuery.data]);
|
|
@@ -553,6 +683,7 @@ function useGlobalHeader({ apiBaseUrl, environmentId, clientId, _dangerouslyInje
|
|
|
553
683
|
};
|
|
554
684
|
const logout = () => {
|
|
555
685
|
headerStore.clearProject();
|
|
686
|
+
clearCachedProjects();
|
|
556
687
|
callLogout(endpoints, fetcher);
|
|
557
688
|
};
|
|
558
689
|
const [projectDropdownVisible, setProjectDropdownVisible] = react$1.useState(showProjectDropdown);
|