@studiocubics/components 0.0.21 → 0.0.23

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.
@@ -27,7 +27,7 @@ export interface CollectionItemCardBaseProps {
27
27
  footerContainer?: ComponentProps<"div">;
28
28
  };
29
29
  }
30
- declare const defaultElement = "a";
30
+ declare const defaultElement = "div";
31
31
  type DefaultElement = typeof defaultElement;
32
32
  /**
33
33
  * Polymorphic props for the CollectionItemCard component.
@@ -1,2 +1,2 @@
1
- "use client";import{jsxs as e,jsx as i}from"react/jsx-runtime";import t from"./CollectionItemCard.module.css.js";import{cn as s}from"@studiocubics/utils";import{ClampedText as a}from"../../Typography/ClampedText/ClampedText.js";import{Chip as l}from"../../Display/Chip/Chip.js";function o(o){const{as:r,className:c,ref:m,thumbnail:n,title:d,chip:p,subtitle:h,description:u,footer:N,slotProps:f={},...C}=o,b=r||"a",v=!!o.href||!!o.onClick,y={className:s(c,t.main),ref:m,...C};return e("div",{...f.root,className:s(t.root,v?t.clickable:"",f.root?.className),children:[n&&i("div",{...f.thumbnail,className:s(t.image,f.thumbnail?.className),children:n}),e(b,{...y,children:[e("div",{...f.titleContainer,className:s(t.title,f.titleContainer?.className),children:[p&&("string"==typeof p?i(l,{size:"sm",...f.chip,children:p}):p),i(a,{as:"h4",...f.title,children:d})]}),h&&i(a,{...f.subtitle,as:"div",className:s(t.subtitle,f.subtitle?.className),children:h}),u&&i(a,{...f.description,as:"div",className:s(t.description,f.description?.className),children:u})]}),N&&i("div",{...f.footerContainer,className:s(t.footer,f.footerContainer?.className),children:N})]})}o.displayName="CollectionItemCard";const r=o;export{r as CollectionItemCard};
1
+ "use client";import{jsxs as e,jsx as i}from"react/jsx-runtime";import t from"./CollectionItemCard.module.css.js";import{cn as s}from"@studiocubics/utils";import{ClampedText as a}from"../../Typography/ClampedText/ClampedText.js";import{Chip as l}from"../../Display/Chip/Chip.js";function r(r){const{as:o,className:c,ref:m,thumbnail:n,title:d,chip:p,subtitle:h,description:f,footer:u,slotProps:N={},...C}=r,b=o||(r.href?"a":"div"),v=!!r.href||!!r.onClick,y={className:s(c,t.main),ref:m,...C};return e("div",{...N.root,className:s(t.root,v?t.clickable:"",N.root?.className),children:[n&&i("div",{...N.thumbnail,className:s(t.image,N.thumbnail?.className),children:n}),e(b,{...y,children:[e("div",{...N.titleContainer,className:s(t.title,N.titleContainer?.className),children:[p&&("string"==typeof p?i(l,{size:"sm",...N.chip,children:p}):p),i(a,{as:"h4",...N.title,children:d})]}),h&&i(a,{...N.subtitle,as:"div",className:s(t.subtitle,N.subtitle?.className),children:h}),f&&i(a,{...N.description,as:"div",className:s(t.description,N.description?.className),children:f})]}),u&&i("div",{...N.footerContainer,className:s(t.footer,N.footerContainer?.className),children:u})]})}r.displayName="CollectionItemCard";const o=r;export{o as CollectionItemCard};
2
2
  //# sourceMappingURL=CollectionItemCard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CollectionItemCard.js","sources":["../../../src/Cards/CollectionItemCard/CollectionItemCard.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentProps, ElementType, ReactNode } from \"react\";\nimport styles from \"./CollectionItemCard.module.css\";\nimport type {\n PolymorphicComponentProps,\n PolymorphicComponentType,\n} from \"@studiocubics/types\";\nimport { cn } from \"@studiocubics/utils\";\nimport {\n ClampedText,\n type ClampedTextProps,\n} from \"../../Typography/ClampedText/ClampedText\";\nimport { Chip, type ChipProps } from \"../../Display/Chip/Chip\";\n/**\n * Props specific to the CollectionItemCard component.\n *\n * These extend the intrinsic element props of whatever element is passed via `as`.\n * @group CollectionItemCard\n * @category Cards\n */\nexport interface CollectionItemCardBaseProps {\n thumbnail?: ReactNode;\n title: ReactNode;\n chip?: ReactNode;\n subtitle?: ReactNode;\n description?: ReactNode;\n footer?: ReactNode;\n slotProps?: {\n // TODO rename to container\n root?: ComponentProps<\"div\">;\n chip?: ChipProps;\n thumbnail?: ComponentProps<\"div\">;\n titleContainer?: ComponentProps<\"div\">;\n title?: ClampedTextProps;\n subtitle?: ClampedTextProps;\n description?: ClampedTextProps;\n footerContainer?: ComponentProps<\"div\">;\n };\n}\nconst defaultElement = \"a\";\ntype DefaultElement = typeof defaultElement;\n/**\n * Polymorphic props for the CollectionItemCard component.\n *\n * `C` defines the element type rendered by the component (e.g. `\"CollectionItemCard\"`, `\"a\"`, `\"div\"`).\n * All intrinsic props for `C` are supported unless overridden by `CollectionItemCardBaseProps`.\n *\n * @group CollectionItemCard\n * @category Cards\n */\nexport type CollectionItemCardProps<C extends ElementType = DefaultElement> =\n PolymorphicComponentProps<C, CollectionItemCardBaseProps>;\n\n/**\n * Base implementation for the CollectionItemCard component.\n *\n * This is a polymorphic component that defaults to rendering a `<CollectionItemCard>`.\n * Use the `as` prop to change the underlying element.\n *\n * @typeParam C - The intrinsic or custom element type to render.\n *\n * @group CollectionItemCard\n * @category Cards\n */\nfunction CollectionItemCardBase<C extends ElementType = DefaultElement>(\n props: CollectionItemCardProps<C>,\n) {\n const {\n as,\n className,\n ref,\n thumbnail,\n title,\n chip,\n subtitle,\n description,\n footer,\n slotProps = {},\n ...restProps\n } = props;\n const Component = as || defaultElement;\n\n const clickable = !!props.href || !!props.onClick;\n const componentProps = {\n className: cn(className, styles.main),\n ref,\n ...restProps,\n };\n\n return (\n <div\n // TODO rename to container\n {...slotProps.root}\n className={cn(\n styles.root,\n clickable ? styles.clickable : \"\",\n slotProps.root?.className,\n )}\n >\n {thumbnail && (\n <div\n {...slotProps.thumbnail}\n className={cn(styles.image, slotProps.thumbnail?.className)}\n >\n {thumbnail}\n </div>\n )}\n <Component {...componentProps}>\n <div\n {...slotProps.titleContainer}\n className={cn(styles.title, slotProps.titleContainer?.className)}\n >\n {chip &&\n (typeof chip == \"string\" ? (\n <Chip size=\"sm\" {...slotProps.chip}>\n {chip}\n </Chip>\n ) : (\n chip\n ))}\n <ClampedText as=\"h4\" {...slotProps.title}>\n {title}\n </ClampedText>\n </div>\n {subtitle && (\n <ClampedText\n {...slotProps.subtitle}\n as=\"div\"\n className={cn(styles.subtitle, slotProps.subtitle?.className)}\n >\n {subtitle}\n </ClampedText>\n )}\n {description && (\n <ClampedText\n {...slotProps.description}\n as=\"div\"\n className={cn(styles.description, slotProps.description?.className)}\n >\n {description}\n </ClampedText>\n )}\n </Component>\n {footer && (\n <div\n {...slotProps.footerContainer}\n className={cn(styles.footer, slotProps.footerContainer?.className)}\n >\n {footer}\n </div>\n )}\n </div>\n );\n}\nCollectionItemCardBase.displayName = \"CollectionItemCard\";\n\n/**\n * A polymorphic CollectionItemCard component.\n *\n * By default it renders a `<CollectionItemCard>`, but any element can be used via the `as` prop:\n *\n * ```tsx\n * <CollectionItemCard as=\"a\" href=\"/docs\">Read docs</CollectionItemCard>\n * ```\n *\n * @group CollectionItemCard\n * @category Cards\n */\nexport const CollectionItemCard =\n CollectionItemCardBase as PolymorphicComponentType<\n CollectionItemCardBaseProps,\n DefaultElement\n >;\n"],"names":["CollectionItemCardBase","props","as","className","ref","thumbnail","title","chip","subtitle","description","footer","slotProps","restProps","Component","clickable","href","onClick","componentProps","cn","styles","main","_jsxs","root","children","_jsx","image","titleContainer","Chip","size","ClampedText","footerContainer","displayName","CollectionItemCard"],"mappings":"sRAiEA,SAASA,EACPC,GAEA,MAAMC,GACJA,EAAEC,UACFA,EAASC,IACTA,EAAGC,UACHA,EAASC,MACTA,EAAKC,KACLA,EAAIC,SACJA,EAAQC,YACRA,EAAWC,OACXA,EAAMC,UACNA,EAAY,CAAA,KACTC,GACDX,EACEY,EAAYX,GAzCG,IA2CfY,IAAcb,EAAMc,QAAUd,EAAMe,QACpCC,EAAiB,CACrBd,UAAWe,EAAGf,EAAWgB,EAAOC,MAChChB,SACGQ,GAGL,OACES,EAAA,MAAA,IAEMV,EAAUW,KACdnB,UAAWe,EACTC,EAAOG,KACPR,EAAYK,EAAOL,UAAY,GAC/BH,EAAUW,MAAMnB,WACjBoB,SAAA,CAEAlB,GACCmB,YACMb,EAAUN,UACdF,UAAWe,EAAGC,EAAOM,MAAOd,EAAUN,WAAWF,oBAEhDE,IAGLgB,EAACR,EAAS,IAAKI,EAAcM,SAAA,CAC3BF,EAAA,MAAA,IACMV,EAAUe,eACdvB,UAAWe,EAAGC,EAAOb,MAAOK,EAAUe,gBAAgBvB,qBAErDI,IACiB,iBAARA,EACNiB,EAACG,EAAI,CAACC,KAAK,QAASjB,EAAUJ,KAAIgB,SAC/BhB,IACI,GAIXiB,EAACK,EAAW,CAAC3B,GAAG,QAASS,EAAUL,eAChCA,OAGJE,GACCgB,EAACK,EAAW,IACNlB,EAAUH,SACdN,GAAG,MACHC,UAAWe,EAAGC,EAAOX,SAAUG,EAAUH,UAAUL,WAAUoB,SAE5Df,IAGJC,GACCe,EAACK,EAAW,IACNlB,EAAUF,YACdP,GAAG,MACHC,UAAWe,EAAGC,EAAOV,YAAaE,EAAUF,aAAaN,WAAUoB,SAElEd,OAINC,GACCc,EAAA,MAAA,IACMb,EAAUmB,gBACd3B,UAAWe,EAAGC,EAAOT,OAAQC,EAAUmB,iBAAiB3B,WAAUoB,SAEjEb,MAKX,CACAV,EAAuB+B,YAAc,qBAc9B,MAAMC,EACXhC"}
1
+ {"version":3,"file":"CollectionItemCard.js","sources":["../../../src/Cards/CollectionItemCard/CollectionItemCard.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentProps, ElementType, ReactNode } from \"react\";\nimport styles from \"./CollectionItemCard.module.css\";\nimport type {\n PolymorphicComponentProps,\n PolymorphicComponentType,\n} from \"@studiocubics/types\";\nimport { cn } from \"@studiocubics/utils\";\nimport {\n ClampedText,\n type ClampedTextProps,\n} from \"../../Typography/ClampedText/ClampedText\";\nimport { Chip, type ChipProps } from \"../../Display/Chip/Chip\";\n/**\n * Props specific to the CollectionItemCard component.\n *\n * These extend the intrinsic element props of whatever element is passed via `as`.\n * @group CollectionItemCard\n * @category Cards\n */\nexport interface CollectionItemCardBaseProps {\n thumbnail?: ReactNode;\n title: ReactNode;\n chip?: ReactNode;\n subtitle?: ReactNode;\n description?: ReactNode;\n footer?: ReactNode;\n slotProps?: {\n // TODO rename to container\n root?: ComponentProps<\"div\">;\n chip?: ChipProps;\n thumbnail?: ComponentProps<\"div\">;\n titleContainer?: ComponentProps<\"div\">;\n title?: ClampedTextProps;\n subtitle?: ClampedTextProps;\n description?: ClampedTextProps;\n footerContainer?: ComponentProps<\"div\">;\n };\n}\nconst defaultElement = \"div\";\ntype DefaultElement = typeof defaultElement;\n/**\n * Polymorphic props for the CollectionItemCard component.\n *\n * `C` defines the element type rendered by the component (e.g. `\"CollectionItemCard\"`, `\"a\"`, `\"div\"`).\n * All intrinsic props for `C` are supported unless overridden by `CollectionItemCardBaseProps`.\n *\n * @group CollectionItemCard\n * @category Cards\n */\nexport type CollectionItemCardProps<C extends ElementType = DefaultElement> =\n PolymorphicComponentProps<C, CollectionItemCardBaseProps>;\n\n/**\n * Base implementation for the CollectionItemCard component.\n *\n * This is a polymorphic component that defaults to rendering a `<CollectionItemCard>`.\n * Use the `as` prop to change the underlying element.\n *\n * @typeParam C - The intrinsic or custom element type to render.\n *\n * @group CollectionItemCard\n * @category Cards\n */\nfunction CollectionItemCardBase<C extends ElementType = DefaultElement>(\n props: CollectionItemCardProps<C>,\n) {\n const {\n as,\n className,\n ref,\n thumbnail,\n title,\n chip,\n subtitle,\n description,\n footer,\n slotProps = {},\n ...restProps\n } = props;\n const Component = as || (props.href ? \"a\" : defaultElement);\n\n const clickable = !!props.href || !!props.onClick;\n const componentProps = {\n className: cn(className, styles.main),\n ref,\n ...restProps,\n };\n\n return (\n <div\n // TODO rename to container\n {...slotProps.root}\n className={cn(\n styles.root,\n clickable ? styles.clickable : \"\",\n slotProps.root?.className,\n )}\n >\n {thumbnail && (\n <div\n {...slotProps.thumbnail}\n className={cn(styles.image, slotProps.thumbnail?.className)}\n >\n {thumbnail}\n </div>\n )}\n <Component {...componentProps}>\n <div\n {...slotProps.titleContainer}\n className={cn(styles.title, slotProps.titleContainer?.className)}\n >\n {chip &&\n (typeof chip == \"string\" ? (\n <Chip size=\"sm\" {...slotProps.chip}>\n {chip}\n </Chip>\n ) : (\n chip\n ))}\n <ClampedText as=\"h4\" {...slotProps.title}>\n {title}\n </ClampedText>\n </div>\n {subtitle && (\n <ClampedText\n {...slotProps.subtitle}\n as=\"div\"\n className={cn(styles.subtitle, slotProps.subtitle?.className)}\n >\n {subtitle}\n </ClampedText>\n )}\n {description && (\n <ClampedText\n {...slotProps.description}\n as=\"div\"\n className={cn(styles.description, slotProps.description?.className)}\n >\n {description}\n </ClampedText>\n )}\n </Component>\n {footer && (\n <div\n {...slotProps.footerContainer}\n className={cn(styles.footer, slotProps.footerContainer?.className)}\n >\n {footer}\n </div>\n )}\n </div>\n );\n}\nCollectionItemCardBase.displayName = \"CollectionItemCard\";\n\n/**\n * A polymorphic CollectionItemCard component.\n *\n * By default it renders a `<CollectionItemCard>`, but any element can be used via the `as` prop:\n *\n * ```tsx\n * <CollectionItemCard as=\"a\" href=\"/docs\">Read docs</CollectionItemCard>\n * ```\n *\n * @group CollectionItemCard\n * @category Cards\n */\nexport const CollectionItemCard =\n CollectionItemCardBase as PolymorphicComponentType<\n CollectionItemCardBaseProps,\n DefaultElement\n >;\n"],"names":["CollectionItemCardBase","props","as","className","ref","thumbnail","title","chip","subtitle","description","footer","slotProps","restProps","Component","href","clickable","onClick","componentProps","cn","styles","main","_jsxs","root","children","_jsx","image","titleContainer","Chip","size","ClampedText","footerContainer","displayName","CollectionItemCard"],"mappings":"sRAiEA,SAASA,EACPC,GAEA,MAAMC,GACJA,EAAEC,UACFA,EAASC,IACTA,EAAGC,UACHA,EAASC,MACTA,EAAKC,KACLA,EAAIC,SACJA,EAAQC,YACRA,EAAWC,OACXA,EAAMC,UACNA,EAAY,CAAA,KACTC,GACDX,EACEY,EAAYX,IAAOD,EAAMa,KAAO,IAzCjB,OA2CfC,IAAcd,EAAMa,QAAUb,EAAMe,QACpCC,EAAiB,CACrBd,UAAWe,EAAGf,EAAWgB,EAAOC,MAChChB,SACGQ,GAGL,OACES,EAAA,MAAA,IAEMV,EAAUW,KACdnB,UAAWe,EACTC,EAAOG,KACPP,EAAYI,EAAOJ,UAAY,GAC/BJ,EAAUW,MAAMnB,WACjBoB,SAAA,CAEAlB,GACCmB,YACMb,EAAUN,UACdF,UAAWe,EAAGC,EAAOM,MAAOd,EAAUN,WAAWF,oBAEhDE,IAGLgB,EAACR,EAAS,IAAKI,EAAcM,SAAA,CAC3BF,EAAA,MAAA,IACMV,EAAUe,eACdvB,UAAWe,EAAGC,EAAOb,MAAOK,EAAUe,gBAAgBvB,qBAErDI,IACiB,iBAARA,EACNiB,EAACG,EAAI,CAACC,KAAK,QAASjB,EAAUJ,KAAIgB,SAC/BhB,IACI,GAIXiB,EAACK,EAAW,CAAC3B,GAAG,QAASS,EAAUL,eAChCA,OAGJE,GACCgB,EAACK,EAAW,IACNlB,EAAUH,SACdN,GAAG,MACHC,UAAWe,EAAGC,EAAOX,SAAUG,EAAUH,UAAUL,WAAUoB,SAE5Df,IAGJC,GACCe,EAACK,EAAW,IACNlB,EAAUF,YACdP,GAAG,MACHC,UAAWe,EAAGC,EAAOV,YAAaE,EAAUF,aAAaN,WAAUoB,SAElEd,OAINC,GACCc,EAAA,MAAA,IACMb,EAAUmB,gBACd3B,UAAWe,EAAGC,EAAOT,OAAQC,EAAUmB,iBAAiB3B,WAAUoB,SAEjEb,MAKX,CACAV,EAAuB+B,YAAc,qBAc9B,MAAMC,EACXhC"}
@@ -1,2 +1,2 @@
1
- "use client";import{jsx as e}from"react/jsx-runtime";import{createContext as r,useState as n,useRef as t,useCallback as l}from"react";const o=r(null);function c({children:r,exclusive:c=!1,onChange:i}){const[u,s]=n([]),a=t(-1),d={values:u,register:l(()=>{const e=a.current++;return s(e=>[...e,!1]),e},[]),update:l((e,r)=>{console.log("index",e,r),s(n=>{let t=c&&r?new Array(n.length).fill(!1):[...n];return t[e]=r,i?.(t),t})},[c,i])};return e(o.Provider,{value:d,children:r})}export{c as Accordion,o as AccordionContext};
1
+ "use client";import{jsx as e}from"react/jsx-runtime";import{createContext as r,useState as t,useRef as n,useCallback as l}from"react";const u=r(null);function c({children:r,exclusive:c=!1,onChange:i}){const[o,s]=t([]),a=n(-1),m={values:o,register:l(()=>{const e=a.current++;return s(e=>[...e,!1]),e},[]),update:l((e,r)=>{s(t=>{let n=c&&r?new Array(t.length).fill(!1):[...t];return n[e]=r,i?.(n),n})},[c,i])};return e(u.Provider,{value:m,children:r})}export{c as Accordion,u as AccordionContext};
2
2
  //# sourceMappingURL=Accordion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Accordion.js","sources":["../../../src/Display/Accordion/Accordion.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\ninterface AccordionContextProps {\n values: boolean[];\n register: () => number;\n update: (index: number, checked: boolean) => void;\n}\ninterface AccordionProviderProps {\n children: ReactNode;\n exclusive?: boolean;\n onChange?: (checked: boolean[]) => void;\n}\n\nexport const AccordionContext = createContext<AccordionContextProps | null>(\n null,\n);\n\nexport function Accordion({\n children,\n exclusive = false,\n onChange,\n}: AccordionProviderProps) {\n const [values, setValues] = useState<boolean[]>([]);\n const indexRef = useRef(-1);\n\n const register = useCallback(() => {\n const index = indexRef.current++;\n setValues((prev) => [...prev, false]);\n return index;\n }, []);\n\n const update = useCallback(\n (index: number, checked: boolean) => {\n console.log(\"index\", index, checked);\n\n setValues((prev) => {\n let next =\n exclusive && checked ? new Array(prev.length).fill(false) : [...prev];\n next[index] = checked;\n onChange?.(next);\n return next;\n });\n },\n [exclusive, onChange],\n );\n const context = { values, register, update };\n\n return (\n <AccordionContext.Provider value={context}>\n {children}\n </AccordionContext.Provider>\n );\n}\n"],"names":["AccordionContext","createContext","Accordion","children","exclusive","onChange","values","setValues","useState","indexRef","useRef","context","register","useCallback","index","current","prev","update","checked","console","log","next","Array","length","fill","_jsx","Provider","value"],"mappings":"4IAqBaA,EAAmBC,EAC9B,MAGI,SAAUC,GAAUC,SACxBA,EAAQC,UACRA,GAAY,EAAKC,SACjBA,IAEA,MAAOC,EAAQC,GAAaC,EAAoB,IAC1CC,EAAWC,MAsBXC,EAAU,CAAEL,SAAQM,SApBTC,EAAY,KAC3B,MAAMC,EAAQL,EAASM,UAEvB,OADAR,EAAWS,GAAS,IAAIA,GAAM,IACvBF,GACN,IAgBiCG,OAdrBJ,EACb,CAACC,EAAeI,KACdC,QAAQC,IAAI,QAASN,EAAOI,GAE5BX,EAAWS,IACT,IAAIK,EACFjB,GAAac,EAAU,IAAII,MAAMN,EAAKO,QAAQC,MAAK,GAAS,IAAIR,GAGlE,OAFAK,EAAKP,GAASI,EACdb,IAAWgB,GACJA,KAGX,CAACjB,EAAWC,KAId,OACEoB,EAACzB,EAAiB0B,SAAQ,CAACC,MAAOhB,EAAOR,SACtCA,GAGP"}
1
+ {"version":3,"file":"Accordion.js","sources":["../../../src/Display/Accordion/Accordion.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\ninterface AccordionContextProps {\n values: boolean[];\n register: () => number;\n update: (index: number, checked: boolean) => void;\n}\ninterface AccordionProviderProps {\n children: ReactNode;\n exclusive?: boolean;\n onChange?: (checked: boolean[]) => void;\n}\n\nexport const AccordionContext = createContext<AccordionContextProps | null>(\n null,\n);\n\nexport function Accordion({\n children,\n exclusive = false,\n onChange,\n}: AccordionProviderProps) {\n const [values, setValues] = useState<boolean[]>([]);\n const indexRef = useRef(-1);\n\n const register = useCallback(() => {\n const index = indexRef.current++;\n setValues((prev) => [...prev, false]);\n return index;\n }, []);\n\n const update = useCallback(\n (index: number, checked: boolean) => {\n setValues((prev) => {\n let next =\n exclusive && checked ? new Array(prev.length).fill(false) : [...prev];\n next[index] = checked;\n onChange?.(next);\n return next;\n });\n },\n [exclusive, onChange],\n );\n const context = { values, register, update };\n\n return (\n <AccordionContext.Provider value={context}>\n {children}\n </AccordionContext.Provider>\n );\n}\n"],"names":["AccordionContext","createContext","Accordion","children","exclusive","onChange","values","setValues","useState","indexRef","useRef","context","register","useCallback","index","current","prev","update","checked","next","Array","length","fill","_jsx","Provider","value"],"mappings":"4IAqBaA,EAAmBC,EAC9B,MAGI,SAAUC,GAAUC,SACxBA,EAAQC,UACRA,GAAY,EAAKC,SACjBA,IAEA,MAAOC,EAAQC,GAAaC,EAAoB,IAC1CC,EAAWC,MAoBXC,EAAU,CAAEL,SAAQM,SAlBTC,EAAY,KAC3B,MAAMC,EAAQL,EAASM,UAEvB,OADAR,EAAWS,GAAS,IAAIA,GAAM,IACvBF,GACN,IAciCG,OAZrBJ,EACb,CAACC,EAAeI,KACdX,EAAWS,IACT,IAAIG,EACFf,GAAac,EAAU,IAAIE,MAAMJ,EAAKK,QAAQC,MAAK,GAAS,IAAIN,GAGlE,OAFAG,EAAKL,GAASI,EACdb,IAAWc,GACJA,KAGX,CAACf,EAAWC,KAId,OACEkB,EAACvB,EAAiBwB,SAAQ,CAACC,MAAOd,EAAOR,SACtCA,GAGP"}
@@ -1,2 +1,2 @@
1
- "use client";import{jsx as t,jsxs as o}from"react/jsx-runtime";import{useState as e,useEffect as s}from"react";import{GlassCard as i}from"../../Cards/GlassCard/GlassCard.js";import{Button as n}from"../../Inputs/Button/Button.js";import{subscribe as r,dismiss as a,addDismissInterceptor as d}from"./toast.js";import l from"./Toaster.module.css.js";function p(e){const{width:s=24,height:i=s,...n}=e;return o("svg",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",...n,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:s,height:i,children:[t("path",{d:"M18 6 6 18"}),t("path",{d:"m6 6 12 12"})]})}function u(o){const{defaultPosition:i="top right",peekGap:n=12,exitDuration:a=200,maxToastCount:p=5}=o,[u,c]=e([]),[h,f]=e(new Set);return s(()=>r(c,p),[]),s(()=>{d((t,o)=>{f(e=>{if(e.has(t))return e;const s=new Set(e).add(t);return setTimeout(()=>{o(),f(o=>{const e=new Set(o);return e.delete(t),e})},a),s})})},[a]),t("div",{className:l.root,children:u.map((o,e)=>t(m,{toast:o,defaultPosition:i,dismissing:h,peekGap:n,toasts:u,index:e},o.id))})}function m({toast:s,defaultPosition:r,dismissing:d,peekGap:u,toasts:m,index:c}){const[h,f]=(s.position??r).split(" "),[g,x]=e(!1);return console.log({toast:s}),o(i,{className:l.toast,"data-pos-y":h,"data-pos-x":f,"data-color":s.color,onMouseEnter:()=>x(!0),onMouseLeave:()=>x(!1),"data-dismissing":d.has(s.id)?"":void 0,style:{"--peek":c*u+"px",zIndex:g?m.length+1:void 0},children:[t("span",{children:s.message}),t(n,{size:"sm",square:!0,onClick:()=>a(s.id),children:t(p,{})})]},s.id)}export{u as Toaster};
1
+ "use client";import{jsx as t,jsxs as o}from"react/jsx-runtime";import{useState as e,useEffect as s}from"react";import{GlassCard as i}from"../../Cards/GlassCard/GlassCard.js";import{Button as n}from"../../Inputs/Button/Button.js";import{subscribe as r,dismiss as a,addDismissInterceptor as d}from"./toast.js";import p from"./Toaster.module.css.js";function u(e){const{width:s=24,height:i=s,...n}=e;return o("svg",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",...n,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:s,height:i,children:[t("path",{d:"M18 6 6 18"}),t("path",{d:"m6 6 12 12"})]})}function m(o){const{defaultPosition:i="top right",peekGap:n=12,exitDuration:a=200,maxToastCount:u=5}=o,[m,c]=e([]),[h,f]=e(new Set);return s(()=>r(c,u),[]),s(()=>{d((t,o)=>{f(e=>{if(e.has(t))return e;const s=new Set(e).add(t);return setTimeout(()=>{o(),f(o=>{const e=new Set(o);return e.delete(t),e})},a),s})})},[a]),t("div",{className:p.root,children:m.map((o,e)=>t(l,{toast:o,defaultPosition:i,dismissing:h,peekGap:n,toasts:m,index:e},o.id))})}function l({toast:s,defaultPosition:r,dismissing:d,peekGap:m,toasts:l,index:c}){const[h,f]=(s.position??r).split(" "),[g,x]=e(!1);return o(i,{className:p.toast,"data-pos-y":h,"data-pos-x":f,"data-color":s.color,onMouseEnter:()=>x(!0),onMouseLeave:()=>x(!1),"data-dismissing":d.has(s.id)?"":void 0,style:{"--peek":c*m+"px",zIndex:g?l.length+1:void 0},children:[t("span",{children:s.message}),t(n,{size:"sm",square:!0,onClick:()=>a(s.id),children:t(u,{})})]},s.id)}export{m as Toaster};
2
2
  //# sourceMappingURL=Toaster.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Toaster.js","sources":["../../../src/Display/Toast/Toaster.tsx"],"sourcesContent":["\"use client\";\n\nimport type { PositionStringEdge } from \"@studiocubics/types\";\nimport {\n type ComponentProps,\n useState,\n useEffect,\n type CSSProperties,\n} from \"react\";\nimport { GlassCard } from \"../../Cards/GlassCard/GlassCard\";\nimport { Button } from \"../../Inputs/Button/Button\";\nimport { type Toast, addDismissInterceptor, dismiss, subscribe } from \"./toast\";\nimport styles from \"./Toaster.module.css\";\n\nfunction CloseIcon(props: ComponentProps<\"svg\">) {\n const { width = 24, height = width, ...rest } = props;\n return (\n <svg\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...rest}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={width}\n height={height}\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\nexport interface ToasterProps {\n defaultPosition?: PositionStringEdge;\n /**\n * Gap between each toast in px\n * @default 8\n */\n peekGap?: number;\n /**\n * Duration of exit animation in ms\n * @default 200\n */\n exitDuration?: number;\n /**\n * @default 5\n */\n maxToastCount?: number;\n}\n\nexport function Toaster(props: ToasterProps) {\n const {\n defaultPosition: defaultPosition = \"top right\",\n peekGap = 12,\n exitDuration = 200,\n maxToastCount = 5,\n } = props;\n const [toasts, setToasts] = useState<Toast[]>([]);\n // Track which toast IDs are currently playing their exit animation\n const [dismissing, setDismissing] = useState<Set<string>>(new Set());\n\n useEffect(() => {\n return subscribe(setToasts, maxToastCount);\n }, []);\n\n useEffect(() => {\n // Register interceptor so all dismiss() calls (auto + manual) go through exit animation\n addDismissInterceptor((id, confirm) => {\n // No-op if already animating out\n setDismissing((prev) => {\n if (prev.has(id)) return prev;\n const next = new Set(prev).add(id);\n setTimeout(() => {\n confirm();\n setDismissing((p) => {\n const n = new Set(p);\n n.delete(id);\n return n;\n });\n }, exitDuration);\n return next;\n });\n });\n }, [exitDuration]);\n\n return (\n <div className={styles.root}>\n {toasts.map((t, i) => (\n <ToastComponent\n key={t.id}\n toast={t}\n defaultPosition={defaultPosition}\n dismissing={dismissing}\n peekGap={peekGap}\n toasts={toasts}\n index={i}\n />\n ))}\n </div>\n );\n}\nfunction ToastComponent({\n toast,\n defaultPosition,\n dismissing,\n peekGap,\n toasts,\n index,\n}: {\n toast: Toast;\n defaultPosition: PositionStringEdge;\n dismissing: Set<string>;\n peekGap: number;\n toasts: Toast[];\n index: number;\n}) {\n const [y, x] = (toast.position ?? defaultPosition).split(\" \");\n const [isHovering, setIsHovering] = useState(false);\n console.log({ toast });\n\n return (\n <GlassCard\n key={toast.id}\n className={styles.toast}\n data-pos-y={y}\n data-pos-x={x}\n data-color={toast.color}\n onMouseEnter={() => setIsHovering(true)}\n onMouseLeave={() => setIsHovering(false)}\n data-dismissing={dismissing.has(toast.id) ? \"\" : undefined}\n style={\n {\n \"--peek\": `${index * peekGap}px`,\n zIndex: isHovering ? toasts.length + 1 : undefined,\n } as CSSProperties\n }\n >\n <span>{toast.message}</span>\n {/* dismiss() goes through interceptor → exit animation → confirmDismiss */}\n <Button size=\"sm\" square onClick={() => dismiss(toast.id)}>\n <CloseIcon />\n </Button>\n </GlassCard>\n );\n}\n"],"names":["CloseIcon","props","width","height","rest","_jsxs","fill","stroke","strokeWidth","strokeLinecap","strokeLinejoin","xmlns","viewBox","children","_jsx","d","Toaster","defaultPosition","peekGap","exitDuration","maxToastCount","toasts","setToasts","useState","dismissing","setDismissing","Set","useEffect","subscribe","addDismissInterceptor","id","confirm","prev","has","next","add","setTimeout","p","n","delete","className","styles","root","map","t","i","ToastComponent","toast","index","y","x","position","split","isHovering","setIsHovering","console","log","GlassCard","color","onMouseEnter","onMouseLeave","undefined","style","zIndex","length","message","Button","size","square","onClick","dismiss"],"mappings":"2VAcA,SAASA,EAAUC,GACjB,MAAMC,MAAEA,EAAQ,GAAEC,OAAEA,EAASD,KAAUE,GAASH,EAChD,OACEI,EAAA,MAAA,CACEC,KAAK,OACLC,OAAO,eACPC,YAAY,IACZC,cAAc,QACdC,eAAe,WACXN,EACJO,MAAM,6BACNC,QAAQ,YACRV,MAAOA,EACPC,OAAQA,EAAMU,SAAA,CAEdC,UAAMC,EAAE,eACRD,EAAA,OAAA,CAAMC,EAAE,iBAGd,CAoBM,SAAUC,EAAQf,GACtB,MACEgB,gBAAiBA,EAAkB,YAAWC,QAC9CA,EAAU,GAAEC,aACZA,EAAe,IAAGC,cAClBA,EAAgB,GACdnB,GACGoB,EAAQC,GAAaC,EAAkB,KAEvCC,EAAYC,GAAiBF,EAAsB,IAAIG,KA0B9D,OAxBAC,EAAU,IACDC,EAAUN,EAAWF,GAC3B,IAEHO,EAAU,KAERE,EAAsB,CAACC,EAAIC,KAEzBN,EAAeO,IACb,GAAIA,EAAKC,IAAIH,GAAK,OAAOE,EACzB,MAAME,EAAO,IAAIR,IAAIM,GAAMG,IAAIL,GAS/B,OARAM,WAAW,KACTL,IACAN,EAAeY,IACb,MAAMC,EAAI,IAAIZ,IAAIW,GAElB,OADAC,EAAEC,OAAOT,GACFQ,KAERnB,GACIe,OAGV,CAACf,IAGFL,EAAA,MAAA,CAAK0B,UAAWC,EAAOC,KAAI7B,SACxBQ,EAAOsB,IAAI,CAACC,EAAGC,IACd/B,EAACgC,EAAc,CAEbC,MAAOH,EACP3B,gBAAiBA,EACjBO,WAAYA,EACZN,QAASA,EACTG,OAAQA,EACR2B,MAAOH,GANFD,EAAEd,MAWjB,CACA,SAASgB,GAAeC,MACtBA,EAAK9B,gBACLA,EAAeO,WACfA,EAAUN,QACVA,EAAOG,OACPA,EAAM2B,MACNA,IASA,MAAOC,EAAGC,IAAMH,EAAMI,UAAYlC,GAAiBmC,MAAM,MAClDC,EAAYC,GAAiB/B,GAAS,GAG7C,OAFAgC,QAAQC,IAAI,CAAET,UAGZ1C,EAACoD,EAAS,CAERjB,UAAWC,EAAOM,MAAK,aACXE,EAAC,aACDC,eACAH,EAAMW,MAClBC,aAAc,IAAML,GAAc,GAClCM,aAAc,IAAMN,GAAc,GAAM,kBACvB9B,EAAWS,IAAIc,EAAMjB,IAAM,QAAK+B,EACjDC,MACE,CACE,SAAad,EAAQ9B,EAAX,KACV6C,OAAQV,EAAahC,EAAO2C,OAAS,OAAIH,GACzBhD,SAAA,CAGpBC,mBAAOiC,EAAMkB,UAEbnD,EAACoD,EAAM,CAACC,KAAK,KAAKC,QAAM,EAACC,QAAS,IAAMC,EAAQvB,EAAMjB,IAAGjB,SACvDC,EAACd,EAAS,CAAA,OAlBP+C,EAAMjB,GAsBjB"}
1
+ {"version":3,"file":"Toaster.js","sources":["../../../src/Display/Toast/Toaster.tsx"],"sourcesContent":["\"use client\";\n\nimport type { PositionStringEdge } from \"@studiocubics/types\";\nimport {\n type ComponentProps,\n useState,\n useEffect,\n type CSSProperties,\n} from \"react\";\nimport { GlassCard } from \"../../Cards/GlassCard/GlassCard\";\nimport { Button } from \"../../Inputs/Button/Button\";\nimport { type Toast, addDismissInterceptor, dismiss, subscribe } from \"./toast\";\nimport styles from \"./Toaster.module.css\";\n\nfunction CloseIcon(props: ComponentProps<\"svg\">) {\n const { width = 24, height = width, ...rest } = props;\n return (\n <svg\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...rest}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={width}\n height={height}\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\nexport interface ToasterProps {\n defaultPosition?: PositionStringEdge;\n /**\n * Gap between each toast in px\n * @default 8\n */\n peekGap?: number;\n /**\n * Duration of exit animation in ms\n * @default 200\n */\n exitDuration?: number;\n /**\n * @default 5\n */\n maxToastCount?: number;\n}\n\nexport function Toaster(props: ToasterProps) {\n const {\n defaultPosition: defaultPosition = \"top right\",\n peekGap = 12,\n exitDuration = 200,\n maxToastCount = 5,\n } = props;\n const [toasts, setToasts] = useState<Toast[]>([]);\n // Track which toast IDs are currently playing their exit animation\n const [dismissing, setDismissing] = useState<Set<string>>(new Set());\n\n useEffect(() => {\n return subscribe(setToasts, maxToastCount);\n }, []);\n\n useEffect(() => {\n // Register interceptor so all dismiss() calls (auto + manual) go through exit animation\n addDismissInterceptor((id, confirm) => {\n // No-op if already animating out\n setDismissing((prev) => {\n if (prev.has(id)) return prev;\n const next = new Set(prev).add(id);\n setTimeout(() => {\n confirm();\n setDismissing((p) => {\n const n = new Set(p);\n n.delete(id);\n return n;\n });\n }, exitDuration);\n return next;\n });\n });\n }, [exitDuration]);\n\n return (\n <div className={styles.root}>\n {toasts.map((t, i) => (\n <ToastComponent\n key={t.id}\n toast={t}\n defaultPosition={defaultPosition}\n dismissing={dismissing}\n peekGap={peekGap}\n toasts={toasts}\n index={i}\n />\n ))}\n </div>\n );\n}\nfunction ToastComponent({\n toast,\n defaultPosition,\n dismissing,\n peekGap,\n toasts,\n index,\n}: {\n toast: Toast;\n defaultPosition: PositionStringEdge;\n dismissing: Set<string>;\n peekGap: number;\n toasts: Toast[];\n index: number;\n}) {\n const [y, x] = (toast.position ?? defaultPosition).split(\" \");\n const [isHovering, setIsHovering] = useState(false);\n\n return (\n <GlassCard\n key={toast.id}\n className={styles.toast}\n data-pos-y={y}\n data-pos-x={x}\n data-color={toast.color}\n onMouseEnter={() => setIsHovering(true)}\n onMouseLeave={() => setIsHovering(false)}\n data-dismissing={dismissing.has(toast.id) ? \"\" : undefined}\n style={\n {\n \"--peek\": `${index * peekGap}px`,\n zIndex: isHovering ? toasts.length + 1 : undefined,\n } as CSSProperties\n }\n >\n <span>{toast.message}</span>\n {/* dismiss() goes through interceptor → exit animation → confirmDismiss */}\n <Button size=\"sm\" square onClick={() => dismiss(toast.id)}>\n <CloseIcon />\n </Button>\n </GlassCard>\n );\n}\n"],"names":["CloseIcon","props","width","height","rest","_jsxs","fill","stroke","strokeWidth","strokeLinecap","strokeLinejoin","xmlns","viewBox","children","_jsx","d","Toaster","defaultPosition","peekGap","exitDuration","maxToastCount","toasts","setToasts","useState","dismissing","setDismissing","Set","useEffect","subscribe","addDismissInterceptor","id","confirm","prev","has","next","add","setTimeout","p","n","delete","className","styles","root","map","t","i","ToastComponent","toast","index","y","x","position","split","isHovering","setIsHovering","GlassCard","color","onMouseEnter","onMouseLeave","undefined","style","zIndex","length","message","Button","size","square","onClick","dismiss"],"mappings":"2VAcA,SAASA,EAAUC,GACjB,MAAMC,MAAEA,EAAQ,GAAEC,OAAEA,EAASD,KAAUE,GAASH,EAChD,OACEI,EAAA,MAAA,CACEC,KAAK,OACLC,OAAO,eACPC,YAAY,IACZC,cAAc,QACdC,eAAe,WACXN,EACJO,MAAM,6BACNC,QAAQ,YACRV,MAAOA,EACPC,OAAQA,EAAMU,SAAA,CAEdC,UAAMC,EAAE,eACRD,EAAA,OAAA,CAAMC,EAAE,iBAGd,CAoBM,SAAUC,EAAQf,GACtB,MACEgB,gBAAiBA,EAAkB,YAAWC,QAC9CA,EAAU,GAAEC,aACZA,EAAe,IAAGC,cAClBA,EAAgB,GACdnB,GACGoB,EAAQC,GAAaC,EAAkB,KAEvCC,EAAYC,GAAiBF,EAAsB,IAAIG,KA0B9D,OAxBAC,EAAU,IACDC,EAAUN,EAAWF,GAC3B,IAEHO,EAAU,KAERE,EAAsB,CAACC,EAAIC,KAEzBN,EAAeO,IACb,GAAIA,EAAKC,IAAIH,GAAK,OAAOE,EACzB,MAAME,EAAO,IAAIR,IAAIM,GAAMG,IAAIL,GAS/B,OARAM,WAAW,KACTL,IACAN,EAAeY,IACb,MAAMC,EAAI,IAAIZ,IAAIW,GAElB,OADAC,EAAEC,OAAOT,GACFQ,KAERnB,GACIe,OAGV,CAACf,IAGFL,EAAA,MAAA,CAAK0B,UAAWC,EAAOC,KAAI7B,SACxBQ,EAAOsB,IAAI,CAACC,EAAGC,IACd/B,EAACgC,EAAc,CAEbC,MAAOH,EACP3B,gBAAiBA,EACjBO,WAAYA,EACZN,QAASA,EACTG,OAAQA,EACR2B,MAAOH,GANFD,EAAEd,MAWjB,CACA,SAASgB,GAAeC,MACtBA,EAAK9B,gBACLA,EAAeO,WACfA,EAAUN,QACVA,EAAOG,OACPA,EAAM2B,MACNA,IASA,MAAOC,EAAGC,IAAMH,EAAMI,UAAYlC,GAAiBmC,MAAM,MAClDC,EAAYC,GAAiB/B,GAAS,GAE7C,OACElB,EAACkD,EAAS,CAERf,UAAWC,EAAOM,MAAK,aACXE,EAAC,aACDC,eACAH,EAAMS,MAClBC,aAAc,IAAMH,GAAc,GAClCI,aAAc,IAAMJ,GAAc,GAAM,kBACvB9B,EAAWS,IAAIc,EAAMjB,IAAM,QAAK6B,EACjDC,MACE,CACE,SAAaZ,EAAQ9B,EAAX,KACV2C,OAAQR,EAAahC,EAAOyC,OAAS,OAAIH,GACzB9C,SAAA,CAGpBC,mBAAOiC,EAAMgB,UAEbjD,EAACkD,EAAM,CAACC,KAAK,KAAKC,QAAM,EAACC,QAAS,IAAMC,EAAQrB,EAAMjB,IAAGjB,SACvDC,EAACd,EAAS,CAAA,OAlBP+C,EAAMjB,GAsBjB"}
@@ -1,2 +1,2 @@
1
- let n=[],t=3;const o=new Set;let e=null;function i(){o.forEach(t=>t(n))}function c(n,e){return o.add(n),t=e,()=>{o.delete(n)}}function u(n){e=n}function l(o,e){const c=crypto.randomUUID();console.log({message:o,options:e});const u={id:c,message:o,duration:2e4,...e};if(n=[...n,u],n.length>t){n.slice(0,n.length-t).forEach(n=>r(n.id))}i(),u.duration<=2e4&&setTimeout(()=>{r(c)},u.duration)}function r(n){e?e(n,()=>s(n)):s(n)}function s(t){n=n.filter(n=>n.id!==t),i()}export{u as addDismissInterceptor,s as confirmDismiss,r as dismiss,c as subscribe,l as toast};
1
+ let n=[],t=3;const e=new Set;let o=null;function i(){e.forEach(t=>t(n))}function c(n,o){return e.add(n),t=o,()=>{e.delete(n)}}function u(n){o=n}function r(e,o){const c=crypto.randomUUID(),u={id:c,message:e,duration:2e4,...o};if(n=[...n,u],n.length>t){n.slice(0,n.length-t).forEach(n=>d(n.id))}i(),u.duration<=2e4&&setTimeout(()=>{d(c)},u.duration)}function d(n){o?o(n,()=>f(n)):f(n)}function f(t){n=n.filter(n=>n.id!==t),i()}export{u as addDismissInterceptor,f as confirmDismiss,d as dismiss,c as subscribe,r as toast};
2
2
  //# sourceMappingURL=toast.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toast.js","sources":["../../../src/Display/Toast/toast.ts"],"sourcesContent":["import type { PositionStringEdge } from \"@studiocubics/types\";\n\nexport type Toast = {\n id: string;\n message: string;\n duration?: number;\n position?: PositionStringEdge;\n color?: \"primary\" | \"secondary\" | \"error\";\n};\nexport type ToastOptions = Omit<Toast, \"id\" | \"message\">;\ntype Listener = (toasts: Toast[]) => void;\n\nlet toasts: Toast[] = [];\nlet maxToastCount = 3; // adjust as needed\n\nconst listeners = new Set<Listener>();\n// Called before actually removing a toast, set by Toaster to trigger exit animation\nlet dismissInterceptor: ((id: string, confirm: () => void) => void) | null =\n null;\n\nfunction emit() {\n listeners.forEach((l) => l(toasts));\n}\n\nexport function subscribe(listener: Listener, max: number) {\n listeners.add(listener);\n maxToastCount = max;\n return () => {\n listeners.delete(listener);\n };\n}\n\n/** Registered by Toaster so it can play the exit animation before removal */\nexport function addDismissInterceptor(fn: typeof dismissInterceptor) {\n dismissInterceptor = fn;\n}\n\nexport function toast(message: string, options?: ToastOptions) {\n const id = crypto.randomUUID();\n\n console.log({ message, options });\n\n const t = {\n id,\n message,\n duration: 20000,\n ...options,\n };\n\n toasts = [...toasts, t];\n\n // Remove oldest toasts if over the limit\n if (toasts.length > maxToastCount) {\n const overflow = toasts.slice(0, toasts.length - maxToastCount);\n overflow.forEach((old) => dismiss(old.id));\n }\n\n emit();\n\n // Its a toast not a lecture!\n if (t.duration <= 20000) {\n setTimeout(() => {\n dismiss(id);\n }, t.duration);\n }\n}\n\nexport function dismiss(id: string) {\n if (dismissInterceptor) {\n // calls confirmDismiss when animation is done\n dismissInterceptor(id, () => confirmDismiss(id));\n } else {\n confirmDismiss(id);\n }\n}\n\n/** Actually removes the toast from state — called after exit animation completes */\nexport function confirmDismiss(id: string) {\n toasts = toasts.filter((t) => t.id !== id);\n emit();\n}\n"],"names":["toasts","maxToastCount","listeners","Set","dismissInterceptor","emit","forEach","l","subscribe","listener","max","add","delete","addDismissInterceptor","fn","toast","message","options","id","crypto","randomUUID","console","log","t","duration","length","slice","old","dismiss","setTimeout","confirmDismiss","filter"],"mappings":"AAYA,IAAIA,EAAkB,GAClBC,EAAgB,EAEpB,MAAMC,EAAY,IAAIC,IAEtB,IAAIC,EACF,KAEF,SAASC,IACPH,EAAUI,QAASC,GAAMA,EAAEP,GAC7B,CAEM,SAAUQ,EAAUC,EAAoBC,GAG5C,OAFAR,EAAUS,IAAIF,GACdR,EAAgBS,EACT,KACLR,EAAUU,OAAOH,GAErB,CAGM,SAAUI,EAAsBC,GACpCV,EAAqBU,CACvB,CAEM,SAAUC,EAAMC,EAAiBC,GACrC,MAAMC,EAAKC,OAAOC,aAElBC,QAAQC,IAAI,CAAEN,UAASC,YAEvB,MAAMM,EAAI,CACRL,KACAF,UACAQ,SAAU,OACPP,GAML,GAHAjB,EAAS,IAAIA,EAAQuB,GAGjBvB,EAAOyB,OAASxB,EAAe,CAChBD,EAAO0B,MAAM,EAAG1B,EAAOyB,OAASxB,GACxCK,QAASqB,GAAQC,EAAQD,EAAIT,IACxC,CAEAb,IAGIkB,EAAEC,UAAY,KAChBK,WAAW,KACTD,EAAQV,IACPK,EAAEC,SAET,CAEM,SAAUI,EAAQV,GAClBd,EAEFA,EAAmBc,EAAI,IAAMY,EAAeZ,IAE5CY,EAAeZ,EAEnB,CAGM,SAAUY,EAAeZ,GAC7BlB,EAASA,EAAO+B,OAAQR,GAAMA,EAAEL,KAAOA,GACvCb,GACF"}
1
+ {"version":3,"file":"toast.js","sources":["../../../src/Display/Toast/toast.ts"],"sourcesContent":["import type { PositionStringEdge } from \"@studiocubics/types\";\n\nexport type Toast = {\n id: string;\n message: string;\n duration?: number;\n position?: PositionStringEdge;\n color?: \"primary\" | \"secondary\" | \"error\";\n};\nexport type ToastOptions = Omit<Toast, \"id\" | \"message\">;\ntype Listener = (toasts: Toast[]) => void;\n\nlet toasts: Toast[] = [];\nlet maxToastCount = 3; // adjust as needed\n\nconst listeners = new Set<Listener>();\n// Called before actually removing a toast, set by Toaster to trigger exit animation\nlet dismissInterceptor: ((id: string, confirm: () => void) => void) | null =\n null;\n\nfunction emit() {\n listeners.forEach((l) => l(toasts));\n}\n\nexport function subscribe(listener: Listener, max: number) {\n listeners.add(listener);\n maxToastCount = max;\n return () => {\n listeners.delete(listener);\n };\n}\n\n/** Registered by Toaster so it can play the exit animation before removal */\nexport function addDismissInterceptor(fn: typeof dismissInterceptor) {\n dismissInterceptor = fn;\n}\n\nexport function toast(message: string, options?: ToastOptions) {\n const id = crypto.randomUUID();\n\n const t = {\n id,\n message,\n duration: 20000,\n ...options,\n };\n\n toasts = [...toasts, t];\n\n // Remove oldest toasts if over the limit\n if (toasts.length > maxToastCount) {\n const overflow = toasts.slice(0, toasts.length - maxToastCount);\n overflow.forEach((old) => dismiss(old.id));\n }\n\n emit();\n\n // Its a toast not a lecture!\n if (t.duration <= 20000) {\n setTimeout(() => {\n dismiss(id);\n }, t.duration);\n }\n}\n\nexport function dismiss(id: string) {\n if (dismissInterceptor) {\n // calls confirmDismiss when animation is done\n dismissInterceptor(id, () => confirmDismiss(id));\n } else {\n confirmDismiss(id);\n }\n}\n\n/** Actually removes the toast from state — called after exit animation completes */\nexport function confirmDismiss(id: string) {\n toasts = toasts.filter((t) => t.id !== id);\n emit();\n}\n"],"names":["toasts","maxToastCount","listeners","Set","dismissInterceptor","emit","forEach","l","subscribe","listener","max","add","delete","addDismissInterceptor","fn","toast","message","options","id","crypto","randomUUID","t","duration","length","slice","old","dismiss","setTimeout","confirmDismiss","filter"],"mappings":"AAYA,IAAIA,EAAkB,GAClBC,EAAgB,EAEpB,MAAMC,EAAY,IAAIC,IAEtB,IAAIC,EACF,KAEF,SAASC,IACPH,EAAUI,QAASC,GAAMA,EAAEP,GAC7B,CAEM,SAAUQ,EAAUC,EAAoBC,GAG5C,OAFAR,EAAUS,IAAIF,GACdR,EAAgBS,EACT,KACLR,EAAUU,OAAOH,GAErB,CAGM,SAAUI,EAAsBC,GACpCV,EAAqBU,CACvB,CAEM,SAAUC,EAAMC,EAAiBC,GACrC,MAAMC,EAAKC,OAAOC,aAEZC,EAAI,CACRH,KACAF,UACAM,SAAU,OACPL,GAML,GAHAjB,EAAS,IAAIA,EAAQqB,GAGjBrB,EAAOuB,OAAStB,EAAe,CAChBD,EAAOwB,MAAM,EAAGxB,EAAOuB,OAAStB,GACxCK,QAASmB,GAAQC,EAAQD,EAAIP,IACxC,CAEAb,IAGIgB,EAAEC,UAAY,KAChBK,WAAW,KACTD,EAAQR,IACPG,EAAEC,SAET,CAEM,SAAUI,EAAQR,GAClBd,EAEFA,EAAmBc,EAAI,IAAMU,EAAeV,IAE5CU,EAAeV,EAEnB,CAGM,SAAUU,EAAeV,GAC7BlB,EAASA,EAAO6B,OAAQR,GAAMA,EAAEH,KAAOA,GACvCb,GACF"}
@@ -12,6 +12,6 @@ interface CheckboxGroupProps {
12
12
  onChange?: (checked: Record<string, boolean>) => void;
13
13
  }
14
14
  export declare const CheckboxGroupContext: import("react").Context<CheckboxGroupContextProps | null>;
15
- export declare const useCheckbox: () => CheckboxGroupContextProps;
15
+ export declare const useCheckbox: () => CheckboxGroupContextProps | null;
16
16
  export declare function CheckboxProvider({ children, onChange }: CheckboxGroupProps): import("react/jsx-runtime").JSX.Element;
17
17
  export {};
@@ -1,2 +1,2 @@
1
- "use client";import{jsx as e}from"react/jsx-runtime";import{createContext as r,useContext as t,useState as n,useRef as o}from"react";const c=r(null),s=()=>{const e=t(c);if(!e)throw new Error("Components must be wrapped with <CheckboxProvider/>");return e};function i({children:r,onChange:t}){const[s,i]=n({}),[u,l]=n(0),a=o(-1),d=Object.keys(s).filter((e,r)=>Object.values(s)[r]);return e(c.Provider,{value:{values:s,selected:d,register:e=>{i(r=>({...r,[e]:!1}))},update:(e,r)=>{i(n=>{const o={...n,[e]:r};return t?.(o),o})},setAll:e=>{i(r=>{const n=Object.fromEntries(Object.keys(r).map(r=>[r,e]));return t?.(n),n})},reset:()=>{a.current=-1,i({}),l(e=>e+1)}},children:e("div",{children:r},u)})}export{c as CheckboxGroupContext,i as CheckboxProvider,s as useCheckbox};
1
+ "use client";import{jsx as e}from"react/jsx-runtime";import{createContext as r,useContext as t,useState as n,useRef as c}from"react";const s=r(null),i=()=>t(s);function l({children:r,onChange:t}){const[i,l]=n({}),[o,u]=n(0),a=c(-1),d=Object.keys(i).filter((e,r)=>Object.values(i)[r]);return e(s.Provider,{value:{values:i,selected:d,register:e=>{l(r=>({...r,[e]:!1}))},update:(e,r)=>{l(n=>{const c={...n,[e]:r};return t?.(c),c})},setAll:e=>{l(r=>{const n=Object.fromEntries(Object.keys(r).map(r=>[r,e]));return t?.(n),n})},reset:()=>{a.current=-1,l({}),u(e=>e+1)}},children:e("div",{children:r},o)})}export{s as CheckboxGroupContext,l as CheckboxProvider,i as useCheckbox};
2
2
  //# sourceMappingURL=CheckboxProvider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CheckboxProvider.js","sources":["../../../src/Inputs/Checkbox/CheckboxProvider.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n type ReactNode,\n useContext,\n useRef,\n useState,\n} from \"react\";\n\ninterface CheckboxGroupContextProps {\n values: Record<string, boolean>;\n selected: string[];\n register: (id: string) => void;\n update: (id: string, checked: boolean) => void;\n setAll: (checked: boolean) => void;\n reset: () => void;\n}\n\ninterface CheckboxGroupProps {\n children: ReactNode;\n onChange?: (checked: Record<string, boolean>) => void;\n}\n\nexport const CheckboxGroupContext =\n createContext<CheckboxGroupContextProps | null>(null);\n\nexport const useCheckbox = () => {\n const c = useContext(CheckboxGroupContext);\n if (!c)\n throw new Error(\"Components must be wrapped with <CheckboxProvider/>\");\n return c;\n};\n\nexport function CheckboxProvider({ children, onChange }: CheckboxGroupProps) {\n const [values, setValues] = useState<Record<string, boolean>>({});\n const [resetKey, setResetKey] = useState(0);\n const indexRef = useRef(-1);\n const selected = Object.keys(values).filter(\n (_, i) => Object.values(values)[i],\n );\n\n const register = (id: string) => {\n setValues((prev) => ({ ...prev, [id]: false }));\n };\n\n const update = (id: string, checked: boolean) => {\n setValues((prev) => {\n const next = { ...prev, [id]: checked };\n onChange?.(next);\n return next;\n });\n };\n\n const setAll = (checked: boolean) => {\n setValues((prev) => {\n const next = Object.fromEntries(\n Object.keys(prev).map((k) => [k, checked]),\n );\n onChange?.(next);\n return next;\n });\n };\n\n const reset = () => {\n indexRef.current = -1;\n setValues({});\n setResetKey((k) => k + 1);\n };\n return (\n <CheckboxGroupContext.Provider\n value={{ values, selected, register, update, setAll, reset }}\n >\n {/* resetKey forces all non-skipGroup checkboxes to remount and re-register */}\n <div key={resetKey}>{children}</div>\n </CheckboxGroupContext.Provider>\n );\n}\n"],"names":["CheckboxGroupContext","createContext","useCheckbox","c","useContext","Error","CheckboxProvider","children","onChange","values","setValues","useState","resetKey","setResetKey","indexRef","useRef","selected","Object","keys","filter","_","i","_jsx","Provider","value","register","id","prev","update","checked","next","setAll","fromEntries","map","k","reset","current"],"mappings":"2IAwBaA,EACXC,EAAgD,MAErCC,EAAc,KACzB,MAAMC,EAAIC,EAAWJ,GACrB,IAAKG,EACH,MAAM,IAAIE,MAAM,uDAClB,OAAOF,YAGOG,GAAiBC,SAAEA,EAAQC,SAAEA,IAC3C,MAAOC,EAAQC,GAAaC,EAAkC,CAAA,IACvDC,EAAUC,GAAeF,EAAS,GACnCG,EAAWC,MACXC,EAAWC,OAAOC,KAAKT,GAAQU,OACnC,CAACC,EAAGC,IAAMJ,OAAOR,OAAOA,GAAQY,IA8BlC,OACEC,EAACtB,EAAqBuB,SAAQ,CAC5BC,MAAO,CAAEf,SAAQO,WAAUS,SA7BbC,IAChBhB,EAAWiB,QAAeA,EAAMD,CAACA,IAAK,MA4BCE,OAzB1B,CAACF,EAAYG,KAC1BnB,EAAWiB,IACT,MAAMG,EAAO,IAAKH,EAAMD,CAACA,GAAKG,GAE9B,OADArB,IAAWsB,GACJA,KAqBsCC,OAjBjCF,IACdnB,EAAWiB,IACT,MAAMG,EAAOb,OAAOe,YAClBf,OAAOC,KAAKS,GAAMM,IAAKC,GAAM,CAACA,EAAGL,KAGnC,OADArB,IAAWsB,GACJA,KAW8CK,MAP3C,KACZrB,EAASsB,SAAU,EACnB1B,EAAU,CAAA,GACVG,EAAaqB,GAAMA,EAAI,KAIuC3B,SAG5De,EAAA,MAAA,CAAAf,SAAqBA,GAAXK,IAGhB"}
1
+ {"version":3,"file":"CheckboxProvider.js","sources":["../../../src/Inputs/Checkbox/CheckboxProvider.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n type ReactNode,\n useContext,\n useRef,\n useState,\n} from \"react\";\n\ninterface CheckboxGroupContextProps {\n values: Record<string, boolean>;\n selected: string[];\n register: (id: string) => void;\n update: (id: string, checked: boolean) => void;\n setAll: (checked: boolean) => void;\n reset: () => void;\n}\n\ninterface CheckboxGroupProps {\n children: ReactNode;\n onChange?: (checked: Record<string, boolean>) => void;\n}\n\nexport const CheckboxGroupContext =\n createContext<CheckboxGroupContextProps | null>(null);\n\nexport const useCheckbox = () => {\n const c = useContext(CheckboxGroupContext);\n return c;\n};\n\nexport function CheckboxProvider({ children, onChange }: CheckboxGroupProps) {\n const [values, setValues] = useState<Record<string, boolean>>({});\n const [resetKey, setResetKey] = useState(0);\n const indexRef = useRef(-1);\n const selected = Object.keys(values).filter(\n (_, i) => Object.values(values)[i],\n );\n\n const register = (id: string) => {\n setValues((prev) => ({ ...prev, [id]: false }));\n };\n\n const update = (id: string, checked: boolean) => {\n setValues((prev) => {\n const next = { ...prev, [id]: checked };\n onChange?.(next);\n return next;\n });\n };\n\n const setAll = (checked: boolean) => {\n setValues((prev) => {\n const next = Object.fromEntries(\n Object.keys(prev).map((k) => [k, checked]),\n );\n onChange?.(next);\n return next;\n });\n };\n\n const reset = () => {\n indexRef.current = -1;\n setValues({});\n setResetKey((k) => k + 1);\n };\n return (\n <CheckboxGroupContext.Provider\n value={{ values, selected, register, update, setAll, reset }}\n >\n {/* resetKey forces all non-skipGroup checkboxes to remount and re-register */}\n <div key={resetKey}>{children}</div>\n </CheckboxGroupContext.Provider>\n );\n}\n"],"names":["CheckboxGroupContext","createContext","useCheckbox","useContext","CheckboxProvider","children","onChange","values","setValues","useState","resetKey","setResetKey","indexRef","useRef","selected","Object","keys","filter","_","i","_jsx","Provider","value","register","id","prev","update","checked","next","setAll","fromEntries","map","k","reset","current"],"mappings":"2IAwBaA,EACXC,EAAgD,MAErCC,EAAc,IACfC,EAAWH,YAIPI,GAAiBC,SAAEA,EAAQC,SAAEA,IAC3C,MAAOC,EAAQC,GAAaC,EAAkC,CAAA,IACvDC,EAAUC,GAAeF,EAAS,GACnCG,EAAWC,MACXC,EAAWC,OAAOC,KAAKT,GAAQU,OACnC,CAACC,EAAGC,IAAMJ,OAAOR,OAAOA,GAAQY,IA8BlC,OACEC,EAACpB,EAAqBqB,SAAQ,CAC5BC,MAAO,CAAEf,SAAQO,WAAUS,SA7BbC,IAChBhB,EAAWiB,QAAeA,EAAMD,CAACA,IAAK,MA4BCE,OAzB1B,CAACF,EAAYG,KAC1BnB,EAAWiB,IACT,MAAMG,EAAO,IAAKH,EAAMD,CAACA,GAAKG,GAE9B,OADArB,IAAWsB,GACJA,KAqBsCC,OAjBjCF,IACdnB,EAAWiB,IACT,MAAMG,EAAOb,OAAOe,YAClBf,OAAOC,KAAKS,GAAMM,IAAKC,GAAM,CAACA,EAAGL,KAGnC,OADArB,IAAWsB,GACJA,KAW8CK,MAP3C,KACZrB,EAASsB,SAAU,EACnB1B,EAAU,CAAA,GACVG,EAAaqB,GAAMA,EAAI,KAIuC3B,SAG5De,EAAA,MAAA,CAAAf,SAAqBA,GAAXK,IAGhB"}
@@ -1,2 +1,2 @@
1
- import{jsx as t,jsxs as o}from"react/jsx-runtime";import{Button as r}from"../Button/Button.js";import{cn as e}from"@studiocubics/utils";import n from"./CloseButton.module.css.js";function s(r){const{width:e=24,height:n=e,...s}=r;return o("svg",{fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round",...s,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:e,height:n,children:[t("path",{d:"M18 6 6 18"}),t("path",{d:"m6 6 12 12"})]})}function i(o){const{className:i,...u}=o;return t(r,{square:!0,className:e(n.root,i),...u,children:t(s,{})})}export{i as CloseButton};
1
+ import{jsx as t,jsxs as o}from"react/jsx-runtime";import{Button as r}from"../Button/Button.js";import{cn as e}from"@studiocubics/utils";import n from"./CloseButton.module.css.js";function s(r){const{width:e=24,height:n=e,...s}=r;return o("svg",{fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",...s,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:e,height:n,children:[t("path",{d:"M18 6 6 18"}),t("path",{d:"m6 6 12 12"})]})}function i(o){const{className:i,...u}=o;return t(r,{square:!0,className:e(n.root,i),...u,children:t(s,{})})}export{i as CloseButton};
2
2
  //# sourceMappingURL=CloseButton.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CloseButton.js","sources":["../../../src/Inputs/CloseButton/CloseButton.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\";\nimport { Button, type ButtonProps } from \"../Button/Button\";\nimport { cn } from \"@studiocubics/utils\";\nimport styles from \"./CloseButton.module.css\";\n\nfunction CloseIcon(props: ComponentProps<\"svg\">) {\n const { width = 24, height = width, ...rest } = props;\n return (\n <svg\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n {...rest}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={width}\n height={height}\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\nexport function CloseButton(props: Omit<ButtonProps, \"children\">) {\n const { className, ...rest } = props;\n return (\n <Button square className={cn(styles.root, className)} {...rest}>\n <CloseIcon />\n </Button>\n );\n}\n"],"names":["CloseIcon","props","width","height","rest","_jsxs","fill","stroke","xmlns","viewBox","children","_jsx","d","CloseButton","className","Button","square","cn","styles","root"],"mappings":"mLAKA,SAASA,EAAUC,GACjB,MAAMC,MAAEA,EAAQ,GAAEC,OAAEA,EAASD,KAAUE,GAASH,EAChD,OACEI,SACEC,KAAK,OACLC,OAAO,eAAc,eACR,IAAG,iBACD,0BACC,WACZH,EACJI,MAAM,6BACNC,QAAQ,YACRP,MAAOA,EACPC,OAAQA,EAAMO,SAAA,CAEdC,EAAA,OAAA,CAAMC,EAAE,eACRD,EAAA,OAAA,CAAMC,EAAE,iBAGd,CAEM,SAAUC,EAAYZ,GAC1B,MAAMa,UAAEA,KAAcV,GAASH,EAC/B,OACEU,EAACI,EAAM,CAACC,UAAOF,UAAWG,EAAGC,EAAOC,KAAML,MAAgBV,EAAIM,SAC5DC,EAACX,EAAS,CAAA,IAGhB"}
1
+ {"version":3,"file":"CloseButton.js","sources":["../../../src/Inputs/CloseButton/CloseButton.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\";\nimport { Button, type ButtonProps } from \"../Button/Button\";\nimport { cn } from \"@studiocubics/utils\";\nimport styles from \"./CloseButton.module.css\";\n\nfunction CloseIcon(props: ComponentProps<\"svg\">) {\n const { width = 24, height = width, ...rest } = props;\n return (\n <svg\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...rest}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={width}\n height={height}\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\nexport function CloseButton(props: Omit<ButtonProps, \"children\">) {\n const { className, ...rest } = props;\n return (\n <Button square className={cn(styles.root, className)} {...rest}>\n <CloseIcon />\n </Button>\n );\n}\n"],"names":["CloseIcon","props","width","height","rest","_jsxs","fill","stroke","strokeWidth","strokeLinecap","strokeLinejoin","xmlns","viewBox","children","_jsx","d","CloseButton","className","Button","square","cn","styles","root"],"mappings":"mLAKA,SAASA,EAAUC,GACjB,MAAMC,MAAEA,EAAQ,GAAEC,OAAEA,EAASD,KAAUE,GAASH,EAChD,OACEI,EAAA,MAAA,CACEC,KAAK,OACLC,OAAO,eACPC,YAAY,IACZC,cAAc,QACdC,eAAe,WACXN,EACJO,MAAM,6BACNC,QAAQ,YACRV,MAAOA,EACPC,OAAQA,EAAMU,SAAA,CAEdC,UAAMC,EAAE,eACRD,EAAA,OAAA,CAAMC,EAAE,iBAGd,CAEM,SAAUC,EAAYf,GAC1B,MAAMgB,UAAEA,KAAcb,GAASH,EAC/B,OACEa,EAACI,EAAM,CAACC,UAAOF,UAAWG,EAAGC,EAAOC,KAAML,MAAgBb,EAAIS,SAC5DC,EAACd,EAAS,CAAA,IAGhB"}
@@ -5,15 +5,15 @@ import { type ChangeEvent, type ComponentProps, type ReactNode } from "react";
5
5
  * @group switch
6
6
  * @category inputs
7
7
  */
8
- export interface SwitchProps extends Omit<ComponentProps<"input">, "defaultValue" | "value" | "onChange" | "size"> {
8
+ export interface SwitchProps extends Omit<ComponentProps<"input">, "defaultChecked" | "checked" | "onChange" | "size"> {
9
9
  /**
10
- * Default value of the switch in boolean
10
+ * Default checked of the switch in boolean
11
11
  */
12
- defaultValue?: boolean;
12
+ defaultChecked?: boolean;
13
13
  /**
14
14
  * Value of the switch in boolean
15
15
  */
16
- value?: boolean | null;
16
+ checked?: boolean | null;
17
17
  /**
18
18
  * Event handler for when the value of the switch changes
19
19
  */
@@ -41,7 +41,7 @@ export interface SwitchProps extends Omit<ComponentProps<"input">, "defaultValue
41
41
  }
42
42
  /**
43
43
  * A switch can be used to show on/off state for form inputs, theme toggles etc.
44
- *
44
+ * //TODO add provider context
45
45
  * @group switch
46
46
  * @category inputs
47
47
  */
@@ -1,2 +1,2 @@
1
- "use client";import{jsxs as e,jsx as t}from"react/jsx-runtime";import{useRef as r,useState as c,useEffect as n,useCallback as o}from"react";import a from"./Switch.module.css.js";import{cssSafeString as s,cn as u,mergeRefs as i}from"@studiocubics/utils";function l(l){const{value:d,defaultValue:m,type:h="checkbox",onChange:p,className:v,ref:b,label:f,"aria-label":k,icon:E,disabled:N,slotProps:L={},color:g,size:w="md",htmlSize:z,...C}=l,X=r(null),x=r(null),S=void 0!==d,[W,j]=c(m??!1),y=S?d??!1:W,M=r(!1),T=r(!1),D=r(0),F=r(y),P=l.id??s(f);n(()=>{F.current=y},[y]);const V=o(e=>{if(S||j(e),X.current&&p){const t=X.current;t.checked=e;const r=new Event("change",{bubbles:!0});t.dispatchEvent(r)}},[S,p]),q=o(e=>{N||(M.current=!0,T.current=!1,D.current=e)},[N]),A=o(e=>{if(!M.current||N)return;const t=e-D.current;if(Math.abs(t)>10){T.current=!0;const e=t>0;e!==F.current&&V(e)}},[N,V]),B=o(()=>{M.current=!1},[]);return n(()=>{const e=e=>A(e.clientX),t=e=>A(e.touches[0].clientX);return document.addEventListener("mousemove",e),document.addEventListener("mouseup",B),document.addEventListener("touchmove",t),document.addEventListener("touchend",B),()=>{document.removeEventListener("mousemove",e),document.removeEventListener("mouseup",B),document.removeEventListener("touchmove",t),document.removeEventListener("touchend",B)}},[A,B]),e("div",{...L.root,"data-color":g,"data-size":w,className:u(L.root?.className,v,a.root,N?a.disabled:""),children:[e("div",{...L.inputWrapper,className:u(a.inputWrapper,L.inputWrapper?.className),children:[t("input",{...C,id:P,size:z,type:h,ref:i(b,X),className:a.input,role:"switch","aria-checked":y,"aria-label":k??f,checked:S?y:void 0,defaultChecked:S?void 0:m,disabled:N,onChange:e=>{const t=e.currentTarget.checked;S||j(t),p&&p(e,t)}}),t("span",{className:u(a.track,y?a.checked:""),onClick:()=>{T.current?T.current=!1:X.current?.click()},"aria-hidden":"true",children:t("span",{ref:x,className:a.thumb,onMouseDown:e=>q(e.clientX),onTouchStart:e=>q(e.touches[0].clientX),children:E})})]}),f&&t("label",{...L.label,htmlFor:P,className:u(L.label?.className,a.label),children:f})]})}export{l as Switch};
1
+ "use client";import{jsxs as e,jsx as t}from"react/jsx-runtime";import{useRef as r,useState as c,useCallback as n,useEffect as o}from"react";import a from"./Switch.module.css.js";import{cssSafeString as s,cn as u,mergeRefs as i}from"@studiocubics/utils";function l(l){const{checked:d,defaultChecked:m,type:h="checkbox",onChange:p,className:v,ref:b,label:f,"aria-label":k,icon:N,disabled:E,slotProps:L={},color:g,size:C="md",htmlSize:w,...z}=l,X=r(null),x=r(null),S=void 0!==d,[T,W]=c(m??!1),j=S?d??!1:T,y=r(!1),M=r(!1),D=r(0),F=r(j),P=l.id??s(f),q=n(e=>{if(!E&&(S||W(e),X.current&&p)){const t={...new Event("change",{bubbles:!0}),target:X.current,currentTarget:X.current};X.current.checked=e,p(t,e)}},[S,p,E]),A=n(e=>{E||(y.current=!0,M.current=!1,D.current=e)},[E]),B=n(e=>{if(!y.current||E)return;const t=e-D.current;if(Math.abs(t)>10){M.current=!0;const e=t>0;e!==F.current&&q(e)}},[E,q]),G=n(()=>{y.current=!1},[]);return o(()=>{const e=e=>B(e.clientX),t=e=>B(e.touches[0].clientX);return document.addEventListener("mousemove",e),document.addEventListener("mouseup",G),document.addEventListener("touchmove",t),document.addEventListener("touchend",G),()=>{document.removeEventListener("mousemove",e),document.removeEventListener("mouseup",G),document.removeEventListener("touchmove",t),document.removeEventListener("touchend",G)}},[B,G]),o(()=>{S||W(m??!1)},[m,S]),o(()=>{F.current=j},[j]),e("div",{...L.root,"data-color":g,"data-size":C,className:u(L.root?.className,v,a.root,E?a.disabled:""),children:[e("div",{...L.inputWrapper,className:u(a.inputWrapper,L.inputWrapper?.className),children:[t("input",{...z,id:P,size:w,type:h,ref:i(b,X),className:a.input,role:"switch","aria-checked":j,"aria-label":k??f,checked:S?j:void 0,defaultChecked:S?void 0:m,disabled:E,onChange:e=>{const t=e.currentTarget.checked;S||W(t),p&&p(e,t)}}),t("span",{className:u(a.track,j?a.checked:""),onClick:()=>{M.current?M.current=!1:X.current?.click()},"aria-hidden":"true",children:t("span",{ref:x,className:a.thumb,onMouseDown:e=>A(e.clientX),onTouchStart:e=>A(e.touches[0].clientX),children:N})})]}),f&&t("label",{...L.label,htmlFor:P,className:u(L.label?.className,a.label),children:f})]})}export{l as Switch};
2
2
  //# sourceMappingURL=Switch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.js","sources":["../../../src/Inputs/Switch/Switch.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type ChangeEvent,\n type ComponentProps,\n type ReactNode,\n useEffect,\n useRef,\n useState,\n useCallback,\n} from \"react\";\nimport styles from \"./Switch.module.css\";\nimport { cn, cssSafeString, mergeRefs } from \"@studiocubics/utils\";\n\n/**\n * Props for the Switch component\n *\n * @group switch\n * @category inputs\n */\nexport interface SwitchProps\n extends Omit<\n ComponentProps<\"input\">,\n \"defaultValue\" | \"value\" | \"onChange\" | \"size\"\n > {\n /**\n * Default value of the switch in boolean\n */\n defaultValue?: boolean;\n /**\n * Value of the switch in boolean\n */\n value?: boolean | null;\n /**\n * Event handler for when the value of the switch changes\n */\n onChange?: (e: ChangeEvent<HTMLInputElement>, checked: boolean) => void;\n /**\n * Label for the switch\n */\n label?: string;\n /**\n * Icon to render in the thumb of the switch\n */\n icon?: ReactNode;\n /**\n * Switch slots props\n */\n slotProps?: {\n root?: ComponentProps<\"div\">;\n inputWrapper?: ComponentProps<\"div\">;\n label?: ComponentProps<\"label\">;\n track?: ComponentProps<\"span\">;\n };\n color?: \"primary\" | \"secondary\" | \"error\";\n size?: \"sm\" | \"md\" | \"lg\";\n htmlSize?: ComponentProps<\"input\">[\"size\"];\n}\n\n/**\n * A switch can be used to show on/off state for form inputs, theme toggles etc.\n *\n * @group switch\n * @category inputs\n */\nexport function Switch(props: SwitchProps) {\n const {\n value,\n defaultValue,\n type = \"checkbox\",\n onChange,\n className,\n ref,\n label,\n \"aria-label\": ariaLabel,\n icon,\n disabled,\n slotProps = {},\n color,\n size = \"md\",\n htmlSize,\n ...rest\n } = props;\n\n const inputRef = useRef<HTMLInputElement>(null);\n const thumbRef = useRef<HTMLSpanElement>(null);\n\n const isControlled = value !== undefined;\n const [internalChecked, setInternalChecked] = useState<boolean>(\n defaultValue ?? false,\n );\n const checked = isControlled ? (value ?? false) : internalChecked;\n\n const isDragging = useRef(false);\n const didDrag = useRef(false);\n const dragStartX = useRef(0);\n\n const checkedRef = useRef(checked);\n const id = props.id ?? cssSafeString(label);\n\n useEffect(() => {\n checkedRef.current = checked;\n }, [checked]);\n\n const triggerChange = useCallback(\n (newChecked: boolean) => {\n if (!isControlled) setInternalChecked(newChecked);\n if (inputRef.current && onChange) {\n const nativeInput = inputRef.current;\n nativeInput.checked = newChecked;\n const nativeEvent = new Event(\"change\", { bubbles: true });\n nativeInput.dispatchEvent(nativeEvent);\n }\n },\n [isControlled, onChange],\n );\n\n const handleDragStart = useCallback(\n (clientX: number) => {\n if (disabled) return;\n isDragging.current = true;\n didDrag.current = false;\n dragStartX.current = clientX;\n },\n [disabled],\n );\n\n const handleDragMove = useCallback(\n (clientX: number) => {\n if (!isDragging.current || disabled) return;\n\n const delta = clientX - dragStartX.current;\n const threshold = 10; // Minimum drag distance to trigger change\n\n if (Math.abs(delta) > threshold) {\n didDrag.current = true;\n const newChecked = delta > 0;\n if (newChecked !== checkedRef.current) {\n triggerChange(newChecked);\n }\n }\n },\n [disabled, triggerChange],\n );\n\n const handleDragEnd = useCallback(() => {\n isDragging.current = false;\n // didDrag.current is intentionally NOT reset here;\n // it stays true until the subsequent click event reads and clears it\n }, []);\n\n useEffect(() => {\n const handleMouseMove = (e: MouseEvent) => handleDragMove(e.clientX);\n const handleTouchMove = (e: TouchEvent) =>\n handleDragMove(e.touches[0].clientX);\n\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseup\", handleDragEnd);\n document.addEventListener(\"touchmove\", handleTouchMove);\n document.addEventListener(\"touchend\", handleDragEnd);\n\n return () => {\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseup\", handleDragEnd);\n document.removeEventListener(\"touchmove\", handleTouchMove);\n document.removeEventListener(\"touchend\", handleDragEnd);\n };\n }, [handleDragMove, handleDragEnd]);\n\n return (\n <div\n // TODO rename to container\n {...slotProps.root}\n data-color={color}\n data-size={size}\n className={cn(\n slotProps.root?.className,\n className,\n styles.root,\n disabled ? styles.disabled : \"\",\n )}\n >\n <div\n {...slotProps.inputWrapper}\n className={cn(styles.inputWrapper, slotProps.inputWrapper?.className)}\n >\n <input\n {...rest}\n id={id}\n size={htmlSize}\n type={type}\n ref={mergeRefs(ref, inputRef)}\n className={styles.input}\n role=\"switch\"\n aria-checked={checked}\n aria-label={ariaLabel ?? label}\n checked={isControlled ? checked : undefined}\n defaultChecked={!isControlled ? defaultValue : undefined}\n disabled={disabled}\n onChange={(e) => {\n const c = e.currentTarget.checked;\n if (!isControlled) setInternalChecked(c);\n if (onChange) onChange(e, c);\n }}\n />\n <span\n className={cn(styles.track, checked ? styles.checked : \"\")}\n onClick={() => {\n if (didDrag.current) {\n didDrag.current = false;\n return;\n }\n inputRef.current?.click();\n }}\n aria-hidden=\"true\"\n >\n <span\n ref={thumbRef}\n className={styles.thumb}\n onMouseDown={(e) => handleDragStart(e.clientX)}\n onTouchStart={(e) => handleDragStart(e.touches[0].clientX)}\n >\n {icon}\n </span>\n </span>\n </div>\n {label && (\n <label\n {...slotProps.label}\n htmlFor={id}\n className={cn(slotProps.label?.className, styles.label)}\n >\n {label}\n </label>\n )}\n </div>\n );\n}\n"],"names":["Switch","props","value","defaultValue","type","onChange","className","ref","label","ariaLabel","icon","disabled","slotProps","color","size","htmlSize","rest","inputRef","useRef","thumbRef","isControlled","undefined","internalChecked","setInternalChecked","useState","checked","isDragging","didDrag","dragStartX","checkedRef","id","cssSafeString","useEffect","current","triggerChange","useCallback","newChecked","nativeInput","nativeEvent","Event","bubbles","dispatchEvent","handleDragStart","clientX","handleDragMove","delta","Math","abs","handleDragEnd","handleMouseMove","e","handleTouchMove","touches","document","addEventListener","removeEventListener","_jsxs","root","cn","styles","children","inputWrapper","_jsx","mergeRefs","input","role","defaultChecked","c","currentTarget","track","onClick","click","thumb","onMouseDown","onTouchStart","htmlFor"],"mappings":"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"}
1
+ {"version":3,"file":"Switch.js","sources":["../../../src/Inputs/Switch/Switch.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type ChangeEvent,\n type ComponentProps,\n type ReactNode,\n useEffect,\n useRef,\n useState,\n useCallback,\n} from \"react\";\nimport styles from \"./Switch.module.css\";\nimport { cn, cssSafeString, mergeRefs } from \"@studiocubics/utils\";\n\n/**\n * Props for the Switch component\n *\n * @group switch\n * @category inputs\n */\nexport interface SwitchProps\n extends Omit<\n ComponentProps<\"input\">,\n \"defaultChecked\" | \"checked\" | \"onChange\" | \"size\"\n > {\n /**\n * Default checked of the switch in boolean\n */\n defaultChecked?: boolean;\n /**\n * Value of the switch in boolean\n */\n checked?: boolean | null;\n /**\n * Event handler for when the value of the switch changes\n */\n onChange?: (e: ChangeEvent<HTMLInputElement>, checked: boolean) => void;\n /**\n * Label for the switch\n */\n label?: string;\n /**\n * Icon to render in the thumb of the switch\n */\n icon?: ReactNode;\n /**\n * Switch slots props\n */\n slotProps?: {\n root?: ComponentProps<\"div\">;\n inputWrapper?: ComponentProps<\"div\">;\n label?: ComponentProps<\"label\">;\n track?: ComponentProps<\"span\">;\n };\n color?: \"primary\" | \"secondary\" | \"error\";\n size?: \"sm\" | \"md\" | \"lg\";\n htmlSize?: ComponentProps<\"input\">[\"size\"];\n}\n\n/**\n * A switch can be used to show on/off state for form inputs, theme toggles etc.\n * //TODO add provider context\n * @group switch\n * @category inputs\n */\nexport function Switch(props: SwitchProps) {\n const {\n checked,\n defaultChecked,\n type = \"checkbox\",\n onChange,\n className,\n ref,\n label,\n \"aria-label\": ariaLabel,\n icon,\n disabled,\n slotProps = {},\n color,\n size = \"md\",\n htmlSize,\n ...rest\n } = props;\n\n const inputRef = useRef<HTMLInputElement>(null);\n const thumbRef = useRef<HTMLSpanElement>(null);\n\n const isControlled = checked !== undefined;\n const [internalChecked, setInternalChecked] = useState<boolean>(\n defaultChecked ?? false,\n );\n const isOn = isControlled ? (checked ?? false) : internalChecked;\n\n const isDragging = useRef(false);\n const didDrag = useRef(false);\n const dragStartX = useRef(0);\n\n const checkedRef = useRef(isOn);\n const id = props.id ?? cssSafeString(label);\n\n const triggerChange = useCallback(\n (newChecked: boolean) => {\n if (disabled) return;\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n if (inputRef.current && onChange) {\n const event = {\n ...new Event(\"change\", { bubbles: true }),\n target: inputRef.current,\n currentTarget: inputRef.current,\n } as unknown as ChangeEvent<HTMLInputElement>;\n // keep DOM in sync\n inputRef.current.checked = newChecked;\n onChange(event, newChecked);\n }\n },\n [isControlled, onChange, disabled],\n );\n\n const handleDragStart = useCallback(\n (clientX: number) => {\n if (disabled) return;\n isDragging.current = true;\n didDrag.current = false;\n dragStartX.current = clientX;\n },\n [disabled],\n );\n\n const handleDragMove = useCallback(\n (clientX: number) => {\n if (!isDragging.current || disabled) return;\n\n const delta = clientX - dragStartX.current;\n const threshold = 10; // Minimum drag distance to trigger change\n\n if (Math.abs(delta) > threshold) {\n didDrag.current = true;\n const newChecked = delta > 0;\n if (newChecked !== checkedRef.current) {\n triggerChange(newChecked);\n }\n }\n },\n [disabled, triggerChange],\n );\n\n const handleDragEnd = useCallback(() => {\n isDragging.current = false;\n // didDrag.current is intentionally NOT reset here;\n // it stays true until the subsequent click event reads and clears it\n }, []);\n\n useEffect(() => {\n const handleMouseMove = (e: MouseEvent) => handleDragMove(e.clientX);\n const handleTouchMove = (e: TouchEvent) =>\n handleDragMove(e.touches[0].clientX);\n\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseup\", handleDragEnd);\n document.addEventListener(\"touchmove\", handleTouchMove);\n document.addEventListener(\"touchend\", handleDragEnd);\n\n return () => {\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseup\", handleDragEnd);\n document.removeEventListener(\"touchmove\", handleTouchMove);\n document.removeEventListener(\"touchend\", handleDragEnd);\n };\n }, [handleDragMove, handleDragEnd]);\n\n useEffect(() => {\n if (!isControlled) {\n setInternalChecked(defaultChecked ?? false);\n }\n }, [defaultChecked, isControlled]);\n\n useEffect(() => {\n checkedRef.current = isOn;\n }, [isOn]);\n\n return (\n <div\n // TODO rename to container\n {...slotProps.root}\n data-color={color}\n data-size={size}\n className={cn(\n slotProps.root?.className,\n className,\n styles.root,\n disabled ? styles.disabled : \"\",\n )}\n >\n <div\n {...slotProps.inputWrapper}\n className={cn(styles.inputWrapper, slotProps.inputWrapper?.className)}\n >\n <input\n {...rest}\n id={id}\n size={htmlSize}\n type={type}\n ref={mergeRefs(ref, inputRef)}\n className={styles.input}\n role=\"switch\"\n aria-checked={isOn}\n aria-label={ariaLabel ?? label}\n checked={isControlled ? isOn : undefined}\n defaultChecked={!isControlled ? defaultChecked : undefined}\n disabled={disabled}\n onChange={(e) => {\n const c = e.currentTarget.checked;\n if (!isControlled) setInternalChecked(c);\n if (onChange) onChange(e, c);\n }}\n />\n <span\n className={cn(styles.track, isOn ? styles.checked : \"\")}\n onClick={() => {\n if (didDrag.current) {\n didDrag.current = false;\n return;\n }\n inputRef.current?.click();\n }}\n aria-hidden=\"true\"\n >\n <span\n ref={thumbRef}\n className={styles.thumb}\n onMouseDown={(e) => handleDragStart(e.clientX)}\n onTouchStart={(e) => handleDragStart(e.touches[0].clientX)}\n >\n {icon}\n </span>\n </span>\n </div>\n {label && (\n <label\n {...slotProps.label}\n htmlFor={id}\n className={cn(slotProps.label?.className, styles.label)}\n >\n {label}\n </label>\n )}\n </div>\n );\n}\n"],"names":["Switch","props","checked","defaultChecked","type","onChange","className","ref","label","ariaLabel","icon","disabled","slotProps","color","size","htmlSize","rest","inputRef","useRef","thumbRef","isControlled","undefined","internalChecked","setInternalChecked","useState","isOn","isDragging","didDrag","dragStartX","checkedRef","id","cssSafeString","triggerChange","useCallback","newChecked","current","event","Event","bubbles","target","currentTarget","handleDragStart","clientX","handleDragMove","delta","Math","abs","handleDragEnd","useEffect","handleMouseMove","e","handleTouchMove","touches","document","addEventListener","removeEventListener","_jsxs","root","cn","styles","children","inputWrapper","_jsx","mergeRefs","input","role","c","track","onClick","click","thumb","onMouseDown","onTouchStart","htmlFor"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{jsxs as o,Fragment as t,jsx as r}from"react/jsx-runtime";import{useDisclosure as e}from"@studiocubics/hooks";import{Button as i}from"../../Inputs/Button/Button.js";import{Dialog as n}from"../Dialog/Dialog.js";import{cn as s}from"@studiocubics/utils";import l from"./Drawer.module.css.js";const h=t=>o("svg",{width:"24",height:"24",stroke:"currentColor",...t,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round",children:[r("rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}),r("path",{d:"M9 3v18"}),r("path",{d:"m16 15-3-3 3-3"})]}),d=t=>o("svg",{width:"24",height:"24",stroke:"currentColor",...t,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round",children:[r("rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}),r("path",{d:"M15 3v18"}),r("path",{d:"m8 9 3 3-3 3"})]});function c(c){const{side:m="right",slotProps:p,children:u,className:w,...a}=c,{open:g,handleOpen:f,handleClose:k}=e();return o(t,{children:[r(i,{onClick:f,children:r("left"==m?d:h,{})}),r(n,{open:g,onClose:k,className:s(w,l.drawer),...a,children:u})]})}export{c as Drawer};
1
+ import{jsxs as o,Fragment as t,jsx as r}from"react/jsx-runtime";import{useDisclosure as e}from"@studiocubics/hooks";import{Button as i}from"../../Inputs/Button/Button.js";import{Dialog as n}from"../Dialog/Dialog.js";import{cn as s}from"@studiocubics/utils";import h from"./Drawer.module.css.js";const d=t=>o("svg",{width:"24",height:"24",stroke:"currentColor",...t,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[r("rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}),r("path",{d:"M9 3v18"}),r("path",{d:"m16 15-3-3 3-3"})]}),l=t=>o("svg",{width:"24",height:"24",stroke:"currentColor",...t,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",fill:"none",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[r("rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}),r("path",{d:"M15 3v18"}),r("path",{d:"m8 9 3 3-3 3"})]});function c(c){const{side:m="right",slotProps:p,children:u,className:a,...w}=c,{open:g,handleOpen:f,handleClose:k}=e();return o(t,{children:[r(i,{onClick:f,children:r("left"==m?l:d,{})}),r(n,{open:g,onClose:k,className:s(a,h.drawer),...w,children:u})]})}export{c as Drawer};
2
2
  //# sourceMappingURL=Drawer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Drawer.js","sources":["../../../src/Layout/Drawer/Drawer.tsx"],"sourcesContent":["import { useDisclosure } from \"@studiocubics/hooks\";\nimport { Button, type ButtonProps } from \"../../Inputs/Button/Button\";\nimport { Dialog, type DialogProps } from \"../../Layout/Dialog/Dialog\";\nimport type { ComponentProps } from \"react\";\nimport { cn } from \"@studiocubics/utils\";\nimport styles from \"./Drawer.module.css\";\n\nexport interface DrawerProps extends Omit<DialogProps, \"open\" | \"onClose\"> {\n /**\n * @default \"right\"\n */\n side?: \"right\" | \"left\";\n\n slotProps?: {\n button?: ButtonProps;\n };\n}\n\nconst PanelLeft = (props: ComponentProps<\"svg\">) => {\n return (\n <svg\n width=\"24\"\n height=\"24\"\n stroke=\"currentColor\"\n {...props}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M9 3v18\" />\n <path d=\"m16 15-3-3 3-3\" />\n </svg>\n );\n};\nconst PanelRight = (props: ComponentProps<\"svg\">) => {\n return (\n <svg\n width=\"24\"\n height=\"24\"\n stroke=\"currentColor\"\n {...props}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M15 3v18\" />\n <path d=\"m8 9 3 3-3 3\" />\n </svg>\n );\n};\n\n/**\n * Opens a drawer from the side of the screen\n */\nexport function Drawer(props: DrawerProps) {\n const { side = \"right\", slotProps, children, className, ...rest } = props;\n const { open, handleOpen, handleClose } = useDisclosure();\n\n return (\n <>\n <Button onClick={handleOpen}>\n {side == \"left\" ? <PanelRight /> : <PanelLeft />}\n </Button>\n <Dialog\n open={open}\n onClose={handleClose}\n className={cn(className, styles.drawer)}\n {...rest}\n >\n {children}\n </Dialog>\n </>\n );\n}\n"],"names":["PanelLeft","props","_jsxs","width","height","stroke","xmlns","viewBox","fill","children","_jsx","x","y","rx","d","PanelRight","Drawer","side","slotProps","className","rest","open","handleOpen","handleClose","useDisclosure","_Fragment","Button","onClick","Dialog","onClose","cn","styles","drawer"],"mappings":"uSAkBA,MAAMA,EAAaC,GAEfC,EAAA,MAAA,CACEC,MAAM,KACNC,OAAO,KACPC,OAAO,kBACHJ,EACJK,MAAM,6BACNC,QAAQ,YACRC,KAAK,OAAM,eACE,IAAG,iBACD,0BACC,QAAOC,SAAA,CAEvBC,EAAA,OAAA,CAAMP,MAAM,KAAKC,OAAO,KAAKO,EAAE,IAAIC,EAAE,IAAIC,GAAG,MAC5CH,EAAA,OAAA,CAAMI,EAAE,YACRJ,EAAA,OAAA,CAAMI,EAAE,sBAIRC,EAAcd,GAEhBC,EAAA,MAAA,CACEC,MAAM,KACNC,OAAO,KACPC,OAAO,kBACHJ,EACJK,MAAM,6BACNC,QAAQ,YACRC,KAAK,OAAM,eACE,IAAG,iBACD,0BACC,QAAOC,SAAA,CAEvBC,EAAA,OAAA,CAAMP,MAAM,KAAKC,OAAO,KAAKO,EAAE,IAAIC,EAAE,IAAIC,GAAG,MAC5CH,EAAA,OAAA,CAAMI,EAAE,aACRJ,EAAA,OAAA,CAAMI,EAAE,oBAQR,SAAUE,EAAOf,GACrB,MAAMgB,KAAEA,EAAO,QAAOC,UAAEA,EAAST,SAAEA,EAAQU,UAAEA,KAAcC,GAASnB,GAC9DoB,KAAEA,EAAIC,WAAEA,EAAUC,YAAEA,GAAgBC,IAE1C,OACEtB,EAAAuB,EAAA,CAAAhB,SAAA,CACEC,EAACgB,EAAM,CAACC,QAASL,EAAUb,SACPC,EAAT,QAARO,EAAkBF,EAAiBf,EAAP,CAAA,KAE/BU,EAACkB,EAAM,CACLP,KAAMA,EACNQ,QAASN,EACTJ,UAAWW,EAAGX,EAAWY,EAAOC,WAC5BZ,EAAIX,SAEPA,MAIT"}
1
+ {"version":3,"file":"Drawer.js","sources":["../../../src/Layout/Drawer/Drawer.tsx"],"sourcesContent":["import { useDisclosure } from \"@studiocubics/hooks\";\nimport { Button, type ButtonProps } from \"../../Inputs/Button/Button\";\nimport { Dialog, type DialogProps } from \"../../Layout/Dialog/Dialog\";\nimport type { ComponentProps } from \"react\";\nimport { cn } from \"@studiocubics/utils\";\nimport styles from \"./Drawer.module.css\";\n\nexport interface DrawerProps extends Omit<DialogProps, \"open\" | \"onClose\"> {\n /**\n * @default \"right\"\n */\n side?: \"right\" | \"left\";\n\n slotProps?: {\n button?: ButtonProps;\n };\n}\n\nconst PanelLeft = (props: ComponentProps<\"svg\">) => {\n return (\n <svg\n width=\"24\"\n height=\"24\"\n stroke=\"currentColor\"\n {...props}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M9 3v18\" />\n <path d=\"m16 15-3-3 3-3\" />\n </svg>\n );\n};\nconst PanelRight = (props: ComponentProps<\"svg\">) => {\n return (\n <svg\n width=\"24\"\n height=\"24\"\n stroke=\"currentColor\"\n {...props}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" />\n <path d=\"M15 3v18\" />\n <path d=\"m8 9 3 3-3 3\" />\n </svg>\n );\n};\n\n/**\n * Opens a drawer from the side of the screen\n */\nexport function Drawer(props: DrawerProps) {\n const { side = \"right\", slotProps, children, className, ...rest } = props;\n const { open, handleOpen, handleClose } = useDisclosure();\n\n return (\n <>\n <Button onClick={handleOpen}>\n {side == \"left\" ? <PanelRight /> : <PanelLeft />}\n </Button>\n <Dialog\n open={open}\n onClose={handleClose}\n className={cn(className, styles.drawer)}\n {...rest}\n >\n {children}\n </Dialog>\n </>\n );\n}\n"],"names":["PanelLeft","props","_jsxs","width","height","stroke","xmlns","viewBox","fill","strokeWidth","strokeLinecap","strokeLinejoin","_jsx","x","y","rx","d","PanelRight","Drawer","side","slotProps","children","className","rest","open","handleOpen","handleClose","useDisclosure","_Fragment","Button","onClick","Dialog","onClose","cn","styles","drawer"],"mappings":"uSAkBA,MAAMA,EAAaC,GAEfC,EAAA,MAAA,CACEC,MAAM,KACNC,OAAO,KACPC,OAAO,kBACHJ,EACJK,MAAM,6BACNC,QAAQ,YACRC,KAAK,OACLC,YAAY,IACZC,cAAc,QACdC,eAAe,kBAEfC,EAAA,OAAA,CAAMT,MAAM,KAAKC,OAAO,KAAKS,EAAE,IAAIC,EAAE,IAAIC,GAAG,MAC5CH,EAAA,OAAA,CAAMI,EAAE,YACRJ,EAAA,OAAA,CAAMI,EAAE,sBAIRC,EAAchB,GAEhBC,EAAA,MAAA,CACEC,MAAM,KACNC,OAAO,KACPC,OAAO,kBACHJ,EACJK,MAAM,6BACNC,QAAQ,YACRC,KAAK,OACLC,YAAY,IACZC,cAAc,QACdC,eAAe,kBAEfC,EAAA,OAAA,CAAMT,MAAM,KAAKC,OAAO,KAAKS,EAAE,IAAIC,EAAE,IAAIC,GAAG,MAC5CH,EAAA,OAAA,CAAMI,EAAE,aACRJ,EAAA,OAAA,CAAMI,EAAE,oBAQR,SAAUE,EAAOjB,GACrB,MAAMkB,KAAEA,EAAO,QAAOC,UAAEA,EAASC,SAAEA,EAAQC,UAAEA,KAAcC,GAAStB,GAC9DuB,KAAEA,EAAIC,WAAEA,EAAUC,YAAEA,GAAgBC,IAE1C,OACEzB,EAAA0B,EAAA,CAAAP,SAAA,CACET,EAACiB,EAAM,CAACC,QAASL,EAAUJ,SACPT,EAAT,QAARO,EAAkBF,EAAiBjB,EAAP,CAAA,KAE/BY,EAACmB,EAAM,CACLP,KAAMA,EACNQ,QAASN,EACTJ,UAAWW,EAAGX,EAAWY,EAAOC,WAC5BZ,EAAIF,SAEPA,MAIT"}
@@ -1,2 +1,2 @@
1
- function s({activeCrumb:s,crumbs:n,siblingCount:t=0,boundaryCount:l=1}){const o=Array.from(n),e=n.length;if(e<=2*l+2*t+2)return o;const i=Math.min(l,e);console.log("crumbs",o);const u=o.slice(0,i+1),c=o.slice(e-1-i,o.length),h=Math.max(Math.min(s-t,e-l-2*t-1),l+2),r=Math.min(Math.max(s+t,l+2*t+2),c.length>0?e-1-c.length:e-1);console.log("siblingsStart",h),console.log("siblingsEnd",r);const a=[];a.push(...u),h>l+2?a.push("ellipsis"):l+1<e-l&&a.push(n[l+1]);for(let s=h;s<=r;s++)a.push(n[s]);r<e-1-l?a.push("ellipsis"):e-l>l&&a.push(n[e-l]);const g=c.filter(s=>!a.includes(s));return console.log("endPagesFiltered",g),a.push(...g),a}export{s as useBreadcrumbs};
1
+ function t({activeCrumb:t,crumbs:n,siblingCount:s=0,boundaryCount:h=1}){const i=Array.from(n),u=n.length;if(u<=2*h+2*s+2)return i;const e=Math.min(h,u),l=i.slice(0,e+1),r=i.slice(u-1-e,i.length),a=Math.max(Math.min(t-s,u-h-2*s-1),h+2),o=Math.min(Math.max(t+s,h+2*s+2),r.length>0?u-1-r.length:u-1),p=[];p.push(...l),a>h+2?p.push("ellipsis"):h+1<u-h&&p.push(n[h+1]);for(let t=a;t<=o;t++)p.push(n[t]);o<u-1-h?p.push("ellipsis"):u-h>h&&p.push(n[u-h]);const c=r.filter(t=>!p.includes(t));return p.push(...c),p}export{t as useBreadcrumbs};
2
2
  //# sourceMappingURL=useBreadcrumbs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useBreadcrumbs.js","sources":["../../../src/Navigation/Breadcrumbs/useBreadcrumbs.tsx"],"sourcesContent":["import type { ReactElement } from \"react\";\n\nexport function useBreadcrumbs({\n activeCrumb,\n crumbs,\n siblingCount = 0,\n boundaryCount = 1,\n}: {\n activeCrumb: number;\n crumbs: ReactElement[];\n siblingCount?: number;\n boundaryCount?: number;\n}) {\n const crumbsClone = Array.from(crumbs);\n const count = crumbs.length;\n if (count <= boundaryCount * 2 + siblingCount * 2 + 2) {\n // If total items fit without ellipsis, just return all crumbs\n return crumbsClone;\n }\n const resolvedBoundaryCount = Math.min(boundaryCount, count);\n\n console.log(\"crumbs\", crumbsClone);\n\n const startPages = crumbsClone.slice(0, resolvedBoundaryCount + 1);\n const endPages = crumbsClone.slice(\n count - 1 - resolvedBoundaryCount,\n crumbsClone.length,\n );\n\n const siblingsStart = Math.max(\n Math.min(\n activeCrumb - siblingCount,\n count - boundaryCount - siblingCount * 2 - 1,\n ),\n boundaryCount + 2,\n );\n const siblingsEnd = Math.min(\n Math.max(activeCrumb + siblingCount, boundaryCount + siblingCount * 2 + 2),\n endPages.length > 0 ? count - 1 - endPages.length : count - 1,\n );\n\n console.log(\"siblingsStart\", siblingsStart);\n console.log(\"siblingsEnd\", siblingsEnd);\n\n const itemList: (ReactElement | \"ellipsis\")[] = [];\n\n // Start pages\n itemList.push(...startPages);\n\n // Ellipsis after start pages\n if (siblingsStart > boundaryCount + 2) {\n itemList.push(\"ellipsis\");\n } else if (boundaryCount + 1 < count - boundaryCount) {\n itemList.push(crumbs[boundaryCount + 1]);\n }\n // Middle pages\n for (let i = siblingsStart; i <= siblingsEnd; i++) {\n itemList.push(crumbs[i]);\n }\n\n // Ellipsis before end pages\n if (siblingsEnd < count - 1 - boundaryCount) {\n itemList.push(\"ellipsis\");\n } else if (count - boundaryCount > boundaryCount) {\n itemList.push(crumbs[count - boundaryCount]);\n }\n\n const endPagesFiltered = endPages.filter((p) => !itemList.includes(p));\n console.log(\"endPagesFiltered\", endPagesFiltered);\n\n itemList.push(...endPagesFiltered);\n\n return itemList;\n}\n"],"names":["useBreadcrumbs","activeCrumb","crumbs","siblingCount","boundaryCount","crumbsClone","Array","from","count","length","resolvedBoundaryCount","Math","min","console","log","startPages","slice","endPages","siblingsStart","max","siblingsEnd","itemList","push","i","endPagesFiltered","filter","p","includes"],"mappings":"AAEM,SAAUA,GAAeC,YAC7BA,EAAWC,OACXA,EAAMC,aACNA,EAAe,EAACC,cAChBA,EAAgB,IAOhB,MAAMC,EAAcC,MAAMC,KAAKL,GACzBM,EAAQN,EAAOO,OACrB,GAAID,GAAyB,EAAhBJ,EAAmC,EAAfD,EAAmB,EAElD,OAAOE,EAET,MAAMK,EAAwBC,KAAKC,IAAIR,EAAeI,GAEtDK,QAAQC,IAAI,SAAUT,GAEtB,MAAMU,EAAaV,EAAYW,MAAM,EAAGN,EAAwB,GAC1DO,EAAWZ,EAAYW,MAC3BR,EAAQ,EAAIE,EACZL,EAAYI,QAGRS,EAAgBP,KAAKQ,IACzBR,KAAKC,IACHX,EAAcE,EACdK,EAAQJ,EAA+B,EAAfD,EAAmB,GAE7CC,EAAgB,GAEZgB,EAAcT,KAAKC,IACvBD,KAAKQ,IAAIlB,EAAcE,EAAcC,EAA+B,EAAfD,EAAmB,GACxEc,EAASR,OAAS,EAAID,EAAQ,EAAIS,EAASR,OAASD,EAAQ,GAG9DK,QAAQC,IAAI,gBAAiBI,GAC7BL,QAAQC,IAAI,cAAeM,GAE3B,MAAMC,EAA0C,GAGhDA,EAASC,QAAQP,GAGbG,EAAgBd,EAAgB,EAClCiB,EAASC,KAAK,YACLlB,EAAgB,EAAII,EAAQJ,GACrCiB,EAASC,KAAKpB,EAAOE,EAAgB,IAGvC,IAAK,IAAImB,EAAIL,EAAeK,GAAKH,EAAaG,IAC5CF,EAASC,KAAKpB,EAAOqB,IAInBH,EAAcZ,EAAQ,EAAIJ,EAC5BiB,EAASC,KAAK,YACLd,EAAQJ,EAAgBA,GACjCiB,EAASC,KAAKpB,EAAOM,EAAQJ,IAG/B,MAAMoB,EAAmBP,EAASQ,OAAQC,IAAOL,EAASM,SAASD,IAKnE,OAJAb,QAAQC,IAAI,mBAAoBU,GAEhCH,EAASC,QAAQE,GAEVH,CACT"}
1
+ {"version":3,"file":"useBreadcrumbs.js","sources":["../../../src/Navigation/Breadcrumbs/useBreadcrumbs.tsx"],"sourcesContent":["import type { ReactElement } from \"react\";\n\nexport function useBreadcrumbs({\n activeCrumb,\n crumbs,\n siblingCount = 0,\n boundaryCount = 1,\n}: {\n activeCrumb: number;\n crumbs: ReactElement[];\n siblingCount?: number;\n boundaryCount?: number;\n}) {\n const crumbsClone = Array.from(crumbs);\n const count = crumbs.length;\n if (count <= boundaryCount * 2 + siblingCount * 2 + 2) {\n // If total items fit without ellipsis, just return all crumbs\n return crumbsClone;\n }\n const resolvedBoundaryCount = Math.min(boundaryCount, count);\n\n const startPages = crumbsClone.slice(0, resolvedBoundaryCount + 1);\n const endPages = crumbsClone.slice(\n count - 1 - resolvedBoundaryCount,\n crumbsClone.length,\n );\n\n const siblingsStart = Math.max(\n Math.min(\n activeCrumb - siblingCount,\n count - boundaryCount - siblingCount * 2 - 1,\n ),\n boundaryCount + 2,\n );\n const siblingsEnd = Math.min(\n Math.max(activeCrumb + siblingCount, boundaryCount + siblingCount * 2 + 2),\n endPages.length > 0 ? count - 1 - endPages.length : count - 1,\n );\n\n const itemList: (ReactElement | \"ellipsis\")[] = [];\n\n // Start pages\n itemList.push(...startPages);\n\n // Ellipsis after start pages\n if (siblingsStart > boundaryCount + 2) {\n itemList.push(\"ellipsis\");\n } else if (boundaryCount + 1 < count - boundaryCount) {\n itemList.push(crumbs[boundaryCount + 1]);\n }\n // Middle pages\n for (let i = siblingsStart; i <= siblingsEnd; i++) {\n itemList.push(crumbs[i]);\n }\n\n // Ellipsis before end pages\n if (siblingsEnd < count - 1 - boundaryCount) {\n itemList.push(\"ellipsis\");\n } else if (count - boundaryCount > boundaryCount) {\n itemList.push(crumbs[count - boundaryCount]);\n }\n\n const endPagesFiltered = endPages.filter((p) => !itemList.includes(p));\n\n itemList.push(...endPagesFiltered);\n\n return itemList;\n}\n"],"names":["useBreadcrumbs","activeCrumb","crumbs","siblingCount","boundaryCount","crumbsClone","Array","from","count","length","resolvedBoundaryCount","Math","min","startPages","slice","endPages","siblingsStart","max","siblingsEnd","itemList","push","i","endPagesFiltered","filter","p","includes"],"mappings":"AAEM,SAAUA,GAAeC,YAC7BA,EAAWC,OACXA,EAAMC,aACNA,EAAe,EAACC,cAChBA,EAAgB,IAOhB,MAAMC,EAAcC,MAAMC,KAAKL,GACzBM,EAAQN,EAAOO,OACrB,GAAID,GAAyB,EAAhBJ,EAAmC,EAAfD,EAAmB,EAElD,OAAOE,EAET,MAAMK,EAAwBC,KAAKC,IAAIR,EAAeI,GAEhDK,EAAaR,EAAYS,MAAM,EAAGJ,EAAwB,GAC1DK,EAAWV,EAAYS,MAC3BN,EAAQ,EAAIE,EACZL,EAAYI,QAGRO,EAAgBL,KAAKM,IACzBN,KAAKC,IACHX,EAAcE,EACdK,EAAQJ,EAA+B,EAAfD,EAAmB,GAE7CC,EAAgB,GAEZc,EAAcP,KAAKC,IACvBD,KAAKM,IAAIhB,EAAcE,EAAcC,EAA+B,EAAfD,EAAmB,GACxEY,EAASN,OAAS,EAAID,EAAQ,EAAIO,EAASN,OAASD,EAAQ,GAGxDW,EAA0C,GAGhDA,EAASC,QAAQP,GAGbG,EAAgBZ,EAAgB,EAClCe,EAASC,KAAK,YACLhB,EAAgB,EAAII,EAAQJ,GACrCe,EAASC,KAAKlB,EAAOE,EAAgB,IAGvC,IAAK,IAAIiB,EAAIL,EAAeK,GAAKH,EAAaG,IAC5CF,EAASC,KAAKlB,EAAOmB,IAInBH,EAAcV,EAAQ,EAAIJ,EAC5Be,EAASC,KAAK,YACLZ,EAAQJ,EAAgBA,GACjCe,EAASC,KAAKlB,EAAOM,EAAQJ,IAG/B,MAAMkB,EAAmBP,EAASQ,OAAQC,IAAOL,EAASM,SAASD,IAInE,OAFAL,EAASC,QAAQE,GAEVH,CACT"}
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "access": "public"
6
6
  },
7
7
  "private": false,
8
- "version": "0.0.21",
8
+ "version": "0.0.23",
9
9
  "keywords": [
10
10
  "@studiocubics",
11
11
  "cubics",
@@ -34,9 +34,9 @@
34
34
  "react-dom": ">= 19"
35
35
  },
36
36
  "dependencies": {
37
- "@studiocubics/hooks": "^0.0.21",
38
- "@studiocubics/types": "^0.0.21",
39
- "@studiocubics/utils": "^0.0.21"
37
+ "@studiocubics/hooks": "^0.0.23",
38
+ "@studiocubics/types": "^0.0.23",
39
+ "@studiocubics/utils": "^0.0.23"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@eslint/js": "^9.39.1",