generated from t3-oss/create-t3-turbo
-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5c8c9d7
commit c7d89cd
Showing
241 changed files
with
12,510 additions
and
23,618 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"platforms": "native-only", | ||
"aliases": { | ||
"components": "~/components", | ||
"lib": "~/lib" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { | ||
AlignJustify, | ||
Check, | ||
ChevronDown, | ||
ChevronRight, | ||
ChevronUp, | ||
type LucideIcon, MoonStar, | ||
Sun, | ||
X, | ||
} from "lucide-react-native"; | ||
import { cssInterop } from "nativewind"; | ||
|
||
function interopIcon(icon: LucideIcon) { | ||
cssInterop(icon, { | ||
interopIcon: true, | ||
}); | ||
// // class: { | ||
// // target: 'style', | ||
// // nativeStyleToProp: { | ||
// // color: true, | ||
// // opacity: true, | ||
// // }, | ||
// // }, | ||
// }); | ||
} | ||
|
||
interopIcon(ChevronUp); | ||
interopIcon(ChevronDown); | ||
interopIcon(Check); | ||
interopIcon(AlignJustify); | ||
interopIcon(ChevronRight); | ||
interopIcon(Sun); | ||
interopIcon(MoonStar); | ||
interopIcon(X); | ||
|
||
|
||
export { Check, ChevronDown, ChevronUp, AlignJustify, Sun, MoonStar, ChevronRight, X }; | ||
export type { LucideIcon }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
216 changes: 216 additions & 0 deletions
216
apps/native/src/components/primitives/accordion/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
import * as React from 'react'; | ||
import { Pressable, View, type GestureResponderEvent } from 'react-native'; | ||
import * as Slot from '~/components/primitives/slot'; | ||
import type { | ||
PressableRef, | ||
SlottablePressableProps, | ||
SlottableViewProps, | ||
ViewRef, | ||
} from '~/components/primitives/types'; | ||
import type { | ||
AccordionContentProps, | ||
AccordionItemProps, | ||
AccordionRootProps, | ||
RootContext, | ||
} from './types'; | ||
import { useControllableState } from '~/components/primitives/hooks'; | ||
|
||
const AccordionContext = React.createContext<RootContext | null>(null); | ||
|
||
const Root = React.forwardRef<ViewRef, SlottableViewProps & AccordionRootProps>( | ||
( | ||
{ | ||
asChild, | ||
type, | ||
disabled, | ||
collapsible = true, | ||
value: valueProp, | ||
onValueChange: onValueChangeProps, | ||
defaultValue, | ||
...viewProps | ||
}, | ||
ref | ||
) => { | ||
const [value = type === 'multiple' ? [] : undefined, onValueChange] = useControllableState< | ||
(string | undefined) | string[] | ||
>({ | ||
prop: valueProp, | ||
defaultProp: defaultValue, | ||
onChange: onValueChangeProps as (state: string | string[] | undefined) => void, | ||
}); | ||
|
||
const Component = asChild ? Slot.View : View; | ||
return ( | ||
<AccordionContext.Provider | ||
value={{ | ||
type, | ||
disabled, | ||
collapsible, | ||
value, | ||
onValueChange, | ||
}} | ||
> | ||
<Component ref={ref} {...viewProps} /> | ||
</AccordionContext.Provider> | ||
); | ||
} | ||
); | ||
|
||
Root.displayName = 'RootNativeAccordion'; | ||
|
||
function useRootContext() { | ||
const context = React.useContext(AccordionContext); | ||
if (!context) { | ||
throw new Error( | ||
'Accordion compound components cannot be rendered outside the Accordion component' | ||
); | ||
} | ||
return context; | ||
} | ||
|
||
type AccordionItemContext = AccordionItemProps & { | ||
nativeID: string; | ||
isExpanded: boolean; | ||
}; | ||
|
||
const AccordionItemContext = React.createContext<AccordionItemContext | null>(null); | ||
|
||
const Item = React.forwardRef<ViewRef, SlottableViewProps & AccordionItemProps>( | ||
({ asChild, value, disabled, ...viewProps }, ref) => { | ||
const { value: rootValue } = useRootContext(); | ||
const nativeID = React.useId(); | ||
|
||
const Component = asChild ? Slot.View : View; | ||
return ( | ||
<AccordionItemContext.Provider | ||
value={{ | ||
value, | ||
disabled, | ||
nativeID, | ||
isExpanded: isItemExpanded(rootValue, value), | ||
}} | ||
> | ||
<Component ref={ref} {...viewProps} /> | ||
</AccordionItemContext.Provider> | ||
); | ||
} | ||
); | ||
|
||
Item.displayName = 'ItemNativeAccordion'; | ||
|
||
function useItemContext() { | ||
const context = React.useContext(AccordionItemContext); | ||
if (!context) { | ||
throw new Error( | ||
'AccordionItem compound components cannot be rendered outside the AccordionItem component' | ||
); | ||
} | ||
return context; | ||
} | ||
|
||
const Header = React.forwardRef<ViewRef, SlottableViewProps>(({ asChild, ...props }, ref) => { | ||
const { disabled: rootDisabled } = useRootContext(); | ||
const { disabled: itemDisabled, isExpanded } = useItemContext(); | ||
|
||
const Component = asChild ? Slot.View : View; | ||
return ( | ||
<Component | ||
ref={ref} | ||
role='heading' | ||
aria-expanded={isExpanded} | ||
aria-disabled={rootDisabled ?? itemDisabled} | ||
{...props} | ||
/> | ||
); | ||
}); | ||
|
||
Header.displayName = 'HeaderNativeAccordion'; | ||
|
||
const Trigger = React.forwardRef<PressableRef, SlottablePressableProps>( | ||
({ asChild, onPress: onPressProp, disabled: disabledProp, ...props }, ref) => { | ||
const { | ||
disabled: rootDisabled, | ||
type, | ||
onValueChange, | ||
value: rootValue, | ||
collapsible, | ||
} = useRootContext(); | ||
const { nativeID, disabled: itemDisabled, value, isExpanded } = useItemContext(); | ||
|
||
function onPress(ev: GestureResponderEvent) { | ||
if (rootDisabled || itemDisabled) return; | ||
if (type === 'single') { | ||
const newValue = collapsible ? (value === rootValue ? undefined : value) : value; | ||
onValueChange(newValue); | ||
} | ||
if (type === 'multiple') { | ||
const rootToArray = toStringArray(rootValue); | ||
const newValue = collapsible | ||
? rootToArray.includes(value) | ||
? rootToArray.filter((val) => val !== value) | ||
: rootToArray.concat(value) | ||
: [...new Set(rootToArray.concat(value))]; | ||
// @ts-ignore - `newValue` is of type `string[]` which is OK | ||
onValueChange(newValue); | ||
} | ||
onPressProp?.(ev); | ||
} | ||
|
||
const isDisabled = disabledProp || rootDisabled || itemDisabled; | ||
const Component = asChild ? Slot.Pressable : Pressable; | ||
return ( | ||
<Component | ||
ref={ref} | ||
key={`${nativeID}-${JSON.stringify(rootValue)}-${isDisabled}-${collapsible}-${type}`} | ||
nativeID={nativeID} | ||
aria-disabled={isDisabled} | ||
role='button' | ||
onPress={onPress} | ||
accessibilityState={{ | ||
expanded: isExpanded, | ||
disabled: isDisabled, | ||
}} | ||
disabled={isDisabled} | ||
{...props} | ||
/> | ||
); | ||
} | ||
); | ||
|
||
Trigger.displayName = 'TriggerNativeAccordion'; | ||
|
||
const Content = React.forwardRef<ViewRef, SlottableViewProps & AccordionContentProps>( | ||
({ asChild, forceMount, ...props }, ref) => { | ||
const { type } = useRootContext(); | ||
const { nativeID, isExpanded } = useItemContext(); | ||
|
||
if (!forceMount) { | ||
if (!isExpanded) { | ||
return null; | ||
} | ||
} | ||
|
||
const Component = asChild ? Slot.View : View; | ||
return ( | ||
<Component | ||
ref={ref} | ||
aria-hidden={!(forceMount || isExpanded)} | ||
aria-labelledby={nativeID} | ||
role={type === 'single' ? 'region' : 'summary'} | ||
{...props} | ||
/> | ||
); | ||
} | ||
); | ||
|
||
Content.displayName = 'ContentNativeAccordion'; | ||
|
||
export { Content, Header, Item, Root, Trigger, useRootContext, useItemContext }; | ||
|
||
function toStringArray(value?: string | string[]) { | ||
return Array.isArray(value) ? value : value ? [value] : []; | ||
} | ||
|
||
function isItemExpanded(rootValue: string | string[] | undefined, value: string) { | ||
return Array.isArray(rootValue) ? rootValue.includes(value) : rootValue === value; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import type { ForceMountable } from "~/components/primitives/types"; | ||
|
||
type RootContext = { | ||
type: "single" | "multiple"; | ||
value: (string | undefined) | string[]; | ||
onValueChange: | ||
| ((value: string | undefined) => void) | ||
| ((value: string[]) => void); | ||
collapsible: boolean; | ||
disabled?: boolean; | ||
}; | ||
|
||
type SingleRootProps = { | ||
type: "single"; | ||
defaultValue?: string | undefined; | ||
value?: string | undefined; | ||
onValueChange?: (value: string | undefined) => void; | ||
}; | ||
|
||
type MultipleRootProps = { | ||
type: "multiple"; | ||
defaultValue?: string[]; | ||
value?: string[]; | ||
onValueChange?: (value: string[]) => void; | ||
}; | ||
|
||
type AccordionRootProps = (SingleRootProps | MultipleRootProps) & { | ||
defaultValue?: string | string[]; | ||
disabled?: boolean; | ||
collapsible?: boolean; | ||
/** | ||
* Platform: WEB ONLY | ||
*/ | ||
dir?: "ltr" | "rtl"; | ||
/** | ||
* Platform: WEB ONLY | ||
*/ | ||
orientation?: "vertical" | "horizontal"; | ||
}; | ||
|
||
type AccordionItemProps = { | ||
value: string; | ||
disabled?: boolean; | ||
}; | ||
type AccordionContentProps = ForceMountable; | ||
|
||
export type { | ||
AccordionContentProps, | ||
AccordionItemProps, | ||
AccordionRootProps, | ||
RootContext, | ||
}; |
Oops, something went wrong.