11import {
22 Accessor ,
33 For ,
4+ Match ,
45 type ParentProps ,
6+ Show ,
7+ Switch ,
58 children ,
9+ createMemo ,
610 createSignal ,
711 splitProps ,
812} from "solid-js" ;
@@ -22,58 +26,68 @@ export { ImageLinks } from "~/ui/image-links";
2226
2327const EraserLinkImpl = clientOnly ( ( ) => import ( "../ui/eraser-link" ) ) ;
2428
29+ type CalloutType = "info" | "tip" | "danger" | "caution" ;
30+
2531export const DirectiveContainer = (
2632 props : {
27- type : "info" | "tip" | "danger" | "caution" | " tab-group" | "tab" ;
33+ type : "tab-group" | "tab" | CalloutType ;
2834 title ?: string ;
2935 codeGroup ?: string ;
3036 tabNames ?: string ;
3137 } & ParentProps
3238) => {
3339 const _children = children ( ( ) => props . children ) . toArray ( ) ;
3440
35- if ( props . type === "tab" ) {
36- return _children ;
37- }
38-
39- if ( props . type === "tab-group" ) {
40- const tabNames = props . tabNames ?. split ( "\0" ) ?? [ ] ;
41+ const tabNames = createMemo ( ( ) => props . tabNames ?. split ( "\0" ) ?? [ ] ) ;
4142
42- const tabs = ( value ?: Accessor < string > , onChange ?: ( s : string ) => void ) => (
43- < Tabs >
44- < TabList >
45- < For each = { tabNames } >
46- { ( title ) => (
47- < Tab
48- value = { title }
49- class = "px-5 py-1 relative top-0.5 transition-colors duration-300 aria-selected:font-bold aria-selected:dark:text-slate-300 aria-selected:text-blue-500 aria-selected:border-b-2 aria-selected:border-blue-400"
50- >
51- { title }
52- </ Tab >
53- ) }
54- </ For >
55- </ TabList >
56- < For each = { tabNames } >
57- { ( title , idx ) => (
58- < TabPanel value = { title } forceMount = { true } >
59- { _children [ idx ( ) ] }
60- </ TabPanel >
43+ const tabs = ( value ?: Accessor < string > , onChange ?: ( s : string ) => void ) => (
44+ < Tabs value = { value ?.( ) } onChange = { onChange } >
45+ < TabList >
46+ < For each = { tabNames ( ) } >
47+ { ( title ) => (
48+ < Tab
49+ value = { title }
50+ class = "px-5 py-1 relative top-0.5 transition-colors duration-300 aria-selected:font-bold aria-selected:dark:text-slate-300 aria-selected:text-blue-500 aria-selected:border-b-2 aria-selected:border-blue-400"
51+ >
52+ { title }
53+ </ Tab >
6154 ) }
6255 </ For >
63- </ Tabs >
64- ) ;
65-
66- if ( ! props . title ) return tabs ( ) ;
56+ </ TabList >
57+ < For each = { tabNames ( ) } >
58+ { ( title , idx ) => (
59+ < TabPanel value = { title } forceMount = { true } >
60+ { _children [ idx ( ) ] }
61+ </ TabPanel >
62+ ) }
63+ </ For >
64+ </ Tabs >
65+ ) ;
6766
68- const [ openTab , setOpenTab ] = makePersisted ( createSignal ( tabNames [ 0 ] ! ) , {
67+ const tabsWithPersistence = ( ) => {
68+ // eslint-disable-next-line solid/reactivity
69+ const [ openTab , setOpenTab ] = makePersisted ( createSignal ( tabNames ( ) [ 0 ] ) , {
6970 name : `tab-group:${ props . title } ` ,
7071 sync : messageSync ( new BroadcastChannel ( "tab-group" ) ) ,
7172 } ) ;
7273
7374 return tabs ( openTab , setOpenTab ) ;
74- }
75+ } ;
7576
76- return < Callout type = { props . type } children = { props . children } /> ;
77+ return (
78+ < Switch
79+ fallback = {
80+ < Callout type = { props . type as CalloutType } children = { props . children } />
81+ }
82+ >
83+ < Match when = { props . type === "tab" } > { _children } </ Match >
84+ < Match when = { props . type === "tab-group" } >
85+ < Show when = { props . title } fallback = { tabs ( ) } >
86+ { tabsWithPersistence ( ) }
87+ </ Show >
88+ </ Match >
89+ </ Switch >
90+ ) ;
7791} ;
7892
7993export const strong = ( props : ParentProps ) => (
0 commit comments