@spark-ui/components 17.13.1 → 17.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accordion/Accordion.d.ts +7 -1
- package/dist/accordion/index.js +1 -1
- package/dist/accordion/index.js.map +1 -1
- package/dist/accordion/index.mjs +20 -17
- package/dist/accordion/index.mjs.map +1 -1
- package/dist/badge/BadgeItem.styles.d.ts +1 -1
- package/dist/button/Button.styles.d.ts +1 -1
- package/dist/card/Backdrop.d.ts +1 -1
- package/dist/card/Card.styles.d.ts +1 -1
- package/dist/card/Content.styles.d.ts +1 -1
- package/dist/card/Type.d.ts +1 -1
- package/dist/checkbox/CheckboxInput.styles.d.ts +1 -1
- package/dist/chip/Chip.styles.d.ts +1 -1
- package/dist/icon/Icon.styles.d.ts +1 -1
- package/dist/menu/MenuItemStyles.d.ts +1 -1
- package/dist/popover/PopoverContent.styles.d.ts +1 -1
- package/dist/radio-group/RadioIndicator.styles.d.ts +1 -1
- package/dist/radio-group/RadioInput.styles.d.ts +1 -1
- package/dist/scrolling-list/ScrollingListNextButton.d.ts +1 -1
- package/dist/scrolling-list/ScrollingListPrevButton.d.ts +1 -1
- package/dist/scrolling-list/index.js +1 -1
- package/dist/scrolling-list/index.js.map +1 -1
- package/dist/scrolling-list/index.mjs +14 -14
- package/dist/scrolling-list/index.mjs.map +1 -1
- package/dist/slider/SliderThumb.styles.d.ts +1 -1
- package/dist/slider/SliderTrack.styles.d.ts +1 -1
- package/dist/spinner/Spinner.styles.d.ts +1 -1
- package/dist/switch/SwitchInput.styles.d.ts +1 -1
- package/dist/tag/Tag.styles.d.ts +1 -1
- package/dist/toast/Toast.styles.d.ts +1 -1
- package/package.json +5 -5
|
@@ -16,6 +16,11 @@ export interface AccordionProps extends ExtentedBaseUIInterface {
|
|
|
16
16
|
*/
|
|
17
17
|
multiple?: boolean;
|
|
18
18
|
design?: 'filled' | 'outlined';
|
|
19
|
+
/**
|
|
20
|
+
* Change the color scheme of the accordion
|
|
21
|
+
* @default surface
|
|
22
|
+
*/
|
|
23
|
+
intent?: 'surface' | 'support';
|
|
19
24
|
ref?: Ref<HTMLDivElement>;
|
|
20
25
|
/**
|
|
21
26
|
* The controlled value (always an array of strings)
|
|
@@ -30,11 +35,12 @@ export interface AccordionProps extends ExtentedBaseUIInterface {
|
|
|
30
35
|
*/
|
|
31
36
|
onValueChange?: (value: string[]) => void;
|
|
32
37
|
}
|
|
33
|
-
export declare function Accordion({ asChild, children, design, hiddenUntilFound, multiple, className, ref, value, defaultValue, onValueChange, ...props }: AccordionProps): import("react/jsx-runtime").JSX.Element;
|
|
38
|
+
export declare function Accordion({ asChild, children, design, intent, hiddenUntilFound, multiple, className, ref, value, defaultValue, onValueChange, ...props }: AccordionProps): import("react/jsx-runtime").JSX.Element;
|
|
34
39
|
export declare namespace Accordion {
|
|
35
40
|
var displayName: string;
|
|
36
41
|
}
|
|
37
42
|
export declare const useAccordionContext: () => {
|
|
38
43
|
design: "filled" | "outlined";
|
|
44
|
+
intent: "surface" | "support";
|
|
39
45
|
};
|
|
40
46
|
export {};
|
package/dist/accordion/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../chunk-C91j1N6u.js`);const e=require(`../slot/index.js`),t=require(`../icon-CRPcdgYp.js`);let n=require(`@base-ui/react/accordion`),r=require(`class-variance-authority`),i=require(`react`),a=require(`react/jsx-runtime`),o=require(`@spark-ui/icons/ArrowHorizontalDown`);function s(t,n){let r=t?e.Slot:n;return t?({...e})=>(0,a.jsx)(r,{...e}):void 0}var c=(0,i.createContext)(null);function l({asChild:e=!1,children:t,design:i=`outlined`,hiddenUntilFound:
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../chunk-C91j1N6u.js`);const e=require(`../slot/index.js`),t=require(`../icon-CRPcdgYp.js`);let n=require(`@base-ui/react/accordion`),r=require(`class-variance-authority`),i=require(`react`),a=require(`react/jsx-runtime`),o=require(`@spark-ui/icons/ArrowHorizontalDown`);function s(t,n){let r=t?e.Slot:n;return t?({...e})=>(0,a.jsx)(r,{...e}):void 0}var c=(0,i.createContext)(null);function l({asChild:e=!1,children:t,design:i=`outlined`,intent:o=`surface`,hiddenUntilFound:l=!0,multiple:u=!1,className:d,ref:f,value:p,defaultValue:m,onValueChange:h,...g}){let _=s(e,`div`),v=h?e=>{h(Array.isArray(e)?e:[e])}:void 0;return(0,a.jsx)(c,{value:{design:i,intent:o},children:(0,a.jsx)(n.Accordion.Root,{"data-spark-component":`accordion`,ref:f,multiple:u,hiddenUntilFound:l,className:(0,r.cx)(`bg-surface h-fit rounded-lg`,d),render:_,value:p,defaultValue:m,onValueChange:v,...g,children:t})})}l.displayName=`Accordion`;var u=()=>{let e=(0,i.useContext)(c);if(!e)throw Error(`useAccordionContext must be used within a Accordion provider`);return e},d=({asChild:e=!1,className:t,children:i,ref:o,...c})=>{let l=u(),d=s(e,`div`);return(0,a.jsx)(n.Accordion.Item,{ref:o,"data-spark-component":`accordion-item`,render:d,className:(0,r.cx)(`relative first:rounded-t-lg last:rounded-b-lg`,`not-last:border-b-0`,{"border-sm border-outline":l.design===`outlined`},t),...c,children:i})};d.displayName=`Accordion.Item`;var f=({asChild:e=!1,className:t,children:i,ref:o,...c})=>{let l=s(e,`div`);return(0,a.jsx)(n.Accordion.Panel,{ref:o,"data-spark-component":`accordion-item-content`,className:(0,r.cx)(`[&>:first-child]:p-lg overflow-hidden`,`h-[var(--accordion-panel-height)] transition-all duration-200 data-[ending-style]:h-0 data-[starting-style]:h-0`,`text-body-1 text-on-surface`,t),render:l,...c,children:i})};f.displayName=`Accordion.ItemContent`;var p=({asChild:t=!1,children:n,className:i,ref:o})=>(0,a.jsx)(t?e.Slot:`h3`,{ref:o,"data-spark-component":`accordion-item-header`,className:(0,r.cx)(`rounded-[inherit]`,i),children:n});p.displayName=`Accordion.ItemHeader`;var m=({asChild:e=!1,children:i,className:c,ref:l,...d})=>{let f=s(e,`button`),{intent:p}=u();return(0,a.jsxs)(n.Accordion.Trigger,{ref:l,"data-spark-component":`accordion-item-trigger`,render:f,className:(0,r.cx)(`group`,`gap-lg min-h-sz-48 relative flex items-center justify-between`,`px-lg py-md text-headline-2 data-panel-open:rounded-b-0 w-full rounded-[inherit] text-left`,`focus-visible:u-outline focus-visible:z-raised focus-visible:outline-hidden`,`data-disabled:opacity-dim-3 cursor-pointer data-disabled:cursor-not-allowed`,p===`surface`&&`bg-surface text-on-surface hover:enabled:bg-surface-hovered focus:bg-surface-hovered`,p===`support`&&`bg-support-container text-on-support-container hover:enabled:bg-support-container-hovered focus:bg-support-container-hovered`,c),...d,children:[(0,a.jsx)(`div`,{className:`gap-lg flex grow items-center`,children:i}),(0,a.jsx)(t.t,{intent:`neutral`,className:(0,r.cx)(`shrink-0 rotate-0 duration-100 ease-in motion-reduce:transition-none`,`group-data-panel-open:rotate-180`),size:`sm`,children:(0,a.jsx)(o.ArrowHorizontalDown,{})})]})};m.displayName=`Accordion.ItemTrigger`;var h=Object.assign(l,{Item:d,ItemHeader:p,ItemTrigger:m,ItemContent:f});h.displayName=`Accordion`,d.displayName=`Item`,p.displayName=`ItemHeader`,m.displayName=`Accordion.Trigger`,f.displayName=`Accordion.Content`,exports.Accordion=h;
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/accordion/useRenderSlot.tsx","../../src/accordion/Accordion.tsx","../../src/accordion/AccordionItem.tsx","../../src/accordion/AccordionItemContent.tsx","../../src/accordion/AccordionItemHeader.tsx","../../src/accordion/AccordionItemTrigger.tsx","../../src/accordion/index.ts"],"sourcesContent":["import { Slot } from '../slot'\n\nexport function useRenderSlot(asChild: boolean, defaultTag: string) {\n const Component = asChild ? Slot : defaultTag\n\n return asChild ? ({ ...props }) => <Component {...props} /> : undefined\n}\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { cx } from 'class-variance-authority'\nimport { ComponentProps, createContext, Ref, useContext } from 'react'\n\nimport { useRenderSlot } from './useRenderSlot'\n\ntype BaseAccordionRootProps = ComponentProps<typeof BaseAccordion.Root<string | string[]>>\n\ntype ExtentedBaseUIInterface = Omit<\n BaseAccordionRootProps,\n 'multiple' | 'render' | 'value' | 'defaultValue' | 'onValueChange'\n>\n\nexport interface AccordionProps extends ExtentedBaseUIInterface {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n /**\n * Whether the accordion items are disabled\n */\n disabled?: boolean\n /**\n * Whether multiple items can be open at the same time.\n */\n multiple?: boolean\n design?: 'filled' | 'outlined'\n ref?: Ref<HTMLDivElement>\n /**\n * The controlled value (always an array of strings)\n */\n value?: string[]\n /**\n * The default value (always an array of strings)\n */\n defaultValue?: string[]\n /**\n * Callback when the value changes (always receives an array of strings)\n */\n onValueChange?: (value: string[]) => void\n}\n\nconst AccordionContext = createContext<{\n design: 'filled' | 'outlined'\n} | null>(null)\n\nexport function Accordion({\n asChild = false,\n children,\n design = 'outlined',\n hiddenUntilFound = true,\n multiple = false,\n className,\n ref,\n value,\n defaultValue,\n onValueChange,\n ...props\n}: AccordionProps) {\n const renderSlot = useRenderSlot(asChild, 'div')\n\n // Wrap the onValueChange to always provide string[]\n const handleValueChange = onValueChange\n ? (newValue: string | string[]) => {\n // Base UI returns string when multiple=false, string[] when multiple=true\n // We normalize to always return string[]\n const normalizedValue = Array.isArray(newValue) ? newValue : [newValue]\n onValueChange(normalizedValue)\n }\n : undefined\n\n return (\n <AccordionContext value={{ design }}>\n <BaseAccordion.Root\n data-spark-component=\"accordion\"\n ref={ref}\n multiple={multiple}\n hiddenUntilFound={hiddenUntilFound}\n className={cx('bg-surface h-fit rounded-lg', className)}\n render={renderSlot}\n value={value as any}\n defaultValue={defaultValue as any}\n onValueChange={handleValueChange as any}\n {...props}\n >\n {children}\n </BaseAccordion.Root>\n </AccordionContext>\n )\n}\n\nAccordion.displayName = 'Accordion'\n\nexport const useAccordionContext = () => {\n const context = useContext(AccordionContext)\n\n if (!context) {\n throw Error('useAccordionContext must be used within a Accordion provider')\n }\n\n return context\n}\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { useAccordionContext } from './Accordion'\nimport { useRenderSlot } from './useRenderSlot'\n\ntype ExtentedZagInterface = Omit<ComponentProps<typeof BaseAccordion.Item>, 'render'>\n\nexport interface AccordionItemProps extends ExtentedZagInterface {\n asChild?: boolean\n ref?: Ref<HTMLDivElement>\n}\n\n/**\n * Groups an accordion header with the corresponding panel. Renders a <div> element.\n */\nexport const Item = ({\n asChild = false,\n className,\n children,\n ref,\n ...props\n}: AccordionItemProps) => {\n const accordion = useAccordionContext()\n\n const renderSlot = useRenderSlot(asChild, 'div')\n\n return (\n <BaseAccordion.Item\n ref={ref}\n data-spark-component=\"accordion-item\"\n render={renderSlot}\n className={cx(\n 'relative first:rounded-t-lg last:rounded-b-lg',\n 'not-last:border-b-0',\n { 'border-sm border-outline': accordion.design === 'outlined' },\n className\n )}\n {...props}\n >\n {children}\n </BaseAccordion.Item>\n )\n}\n\nItem.displayName = 'Accordion.Item'\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { useRenderSlot } from './useRenderSlot'\n\ntype ExtentedZagInterface = Omit<ComponentProps<typeof BaseAccordion.Panel>, 'render'>\n\nexport interface AccordionItemContentProps extends ExtentedZagInterface {\n asChild?: boolean\n ref?: Ref<HTMLDivElement>\n}\n\nexport const ItemContent = ({\n asChild = false,\n className,\n children,\n ref,\n ...props\n}: AccordionItemContentProps) => {\n const renderSlot = useRenderSlot(asChild, 'div')\n\n return (\n <BaseAccordion.Panel\n ref={ref}\n data-spark-component=\"accordion-item-content\"\n className={cx(\n '[&>:first-child]:p-lg overflow-hidden',\n 'h-[var(--accordion-panel-height)] transition-all duration-200 data-[ending-style]:h-0 data-[starting-style]:h-0',\n 'text-body-1 text-on-surface',\n className\n )}\n render={renderSlot}\n {...props}\n >\n {children}\n </BaseAccordion.Panel>\n )\n}\n\nItemContent.displayName = 'Accordion.ItemContent'\n","import { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { Slot } from '../slot'\n\nexport interface AccordionItemHeaderProps extends ComponentProps<'h3'> {\n asChild?: boolean\n ref?: Ref<HTMLHeadingElement>\n}\n\nexport const ItemHeader = ({\n asChild = false,\n children,\n className,\n ref,\n}: AccordionItemHeaderProps) => {\n const Component = asChild ? Slot : 'h3'\n\n return (\n <Component\n ref={ref}\n data-spark-component=\"accordion-item-header\"\n className={cx('rounded-[inherit]', className)}\n >\n {children}\n </Component>\n )\n}\n\nItemHeader.displayName = 'Accordion.ItemHeader'\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { ArrowHorizontalDown } from '@spark-ui/icons/ArrowHorizontalDown'\nimport { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { Icon } from '../icon'\nimport { useRenderSlot } from './useRenderSlot'\n\ntype ExtentedZagInterface = Omit<ComponentProps<typeof BaseAccordion.Trigger>, 'render'>\n\nexport interface AccordionItemTriggerProps extends ExtentedZagInterface {\n asChild?: boolean\n ref?: Ref<HTMLButtonElement>\n}\n\nexport const ItemTrigger = ({\n asChild = false,\n children,\n className,\n ref,\n ...props\n}: AccordionItemTriggerProps) => {\n const renderSlot = useRenderSlot(asChild, 'button')\n\n return (\n <BaseAccordion.Trigger\n ref={ref}\n data-spark-component=\"accordion-item-trigger\"\n render={renderSlot}\n className={cx(\n 'group',\n 'gap-lg min-h-sz-48 relative flex items-center justify-between',\n 'px-lg py-md text-headline-2 text-on-surface data-[panel-open]:rounded-b-0 w-full rounded-[inherit] text-left',\n 'hover:enabled:bg-surface-hovered focus:bg-surface-hovered',\n 'focus-visible:u-outline focus-visible:z-raised focus-visible:outline-hidden',\n 'disabled:opacity-dim-3 cursor-pointer disabled:cursor-not-allowed',\n className\n )}\n {...props}\n >\n <div className=\"gap-lg flex grow items-center\">{children}</div>\n <Icon\n intent=\"neutral\"\n className={cx(\n 'shrink-0 rotate-0 duration-100 ease-in motion-reduce:transition-none',\n 'group-data-[panel-open]:rotate-180'\n )}\n size=\"sm\"\n >\n <ArrowHorizontalDown />\n </Icon>\n </BaseAccordion.Trigger>\n )\n}\n\nItemTrigger.displayName = 'Accordion.ItemTrigger'\n","import { Accordion as Root } from './Accordion'\nimport { Item } from './AccordionItem'\nimport { ItemContent } from './AccordionItemContent'\nimport { ItemHeader } from './AccordionItemHeader'\nimport { ItemTrigger } from './AccordionItemTrigger'\n\n/**\n * A vertically stacked set of expandable sections that allow users to show and hide content.\n */\nexport const Accordion: typeof Root & {\n Item: typeof Item\n ItemHeader: typeof ItemHeader\n ItemTrigger: typeof ItemTrigger\n ItemContent: typeof ItemContent\n} = Object.assign(Root, {\n Item,\n ItemHeader,\n ItemTrigger,\n ItemContent,\n})\n\nAccordion.displayName = 'Accordion'\nItem.displayName = 'Item'\nItemHeader.displayName = 'ItemHeader'\nItemTrigger.displayName = 'Accordion.Trigger'\nItemContent.displayName = 'Accordion.Content'\n\nexport { type AccordionProps } from './Accordion'\nexport { type AccordionItemHeaderProps } from './AccordionItemHeader'\nexport { type AccordionItemContentProps } from './AccordionItemContent'\nexport { type AccordionItemTriggerProps } from './AccordionItemTrigger'\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/accordion/useRenderSlot.tsx","../../src/accordion/Accordion.tsx","../../src/accordion/AccordionItem.tsx","../../src/accordion/AccordionItemContent.tsx","../../src/accordion/AccordionItemHeader.tsx","../../src/accordion/AccordionItemTrigger.tsx","../../src/accordion/index.ts"],"sourcesContent":["import { Slot } from '../slot'\n\nexport function useRenderSlot(asChild: boolean, defaultTag: string) {\n const Component = asChild ? Slot : defaultTag\n\n return asChild ? ({ ...props }) => <Component {...props} /> : undefined\n}\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { cx } from 'class-variance-authority'\nimport { ComponentProps, createContext, Ref, useContext } from 'react'\n\nimport { useRenderSlot } from './useRenderSlot'\n\ntype BaseAccordionRootProps = ComponentProps<typeof BaseAccordion.Root<string | string[]>>\n\ntype ExtentedBaseUIInterface = Omit<\n BaseAccordionRootProps,\n 'multiple' | 'render' | 'value' | 'defaultValue' | 'onValueChange'\n>\n\nexport interface AccordionProps extends ExtentedBaseUIInterface {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n /**\n * Whether the accordion items are disabled\n */\n disabled?: boolean\n /**\n * Whether multiple items can be open at the same time.\n */\n multiple?: boolean\n design?: 'filled' | 'outlined'\n /**\n * Change the color scheme of the accordion\n * @default surface\n */\n intent?: 'surface' | 'support'\n ref?: Ref<HTMLDivElement>\n /**\n * The controlled value (always an array of strings)\n */\n value?: string[]\n /**\n * The default value (always an array of strings)\n */\n defaultValue?: string[]\n /**\n * Callback when the value changes (always receives an array of strings)\n */\n onValueChange?: (value: string[]) => void\n}\n\nconst AccordionContext = createContext<{\n design: 'filled' | 'outlined'\n intent: 'surface' | 'support'\n} | null>(null)\n\nexport function Accordion({\n asChild = false,\n children,\n design = 'outlined',\n intent = 'surface',\n hiddenUntilFound = true,\n multiple = false,\n className,\n ref,\n value,\n defaultValue,\n onValueChange,\n ...props\n}: AccordionProps) {\n const renderSlot = useRenderSlot(asChild, 'div')\n\n // Wrap the onValueChange to always provide string[]\n const handleValueChange = onValueChange\n ? (newValue: string | string[]) => {\n // Base UI returns string when multiple=false, string[] when multiple=true\n // We normalize to always return string[]\n const normalizedValue = Array.isArray(newValue) ? newValue : [newValue]\n onValueChange(normalizedValue)\n }\n : undefined\n\n return (\n <AccordionContext value={{ design, intent }}>\n <BaseAccordion.Root\n data-spark-component=\"accordion\"\n ref={ref}\n multiple={multiple}\n hiddenUntilFound={hiddenUntilFound}\n className={cx('bg-surface h-fit rounded-lg', className)}\n render={renderSlot}\n value={value as any}\n defaultValue={defaultValue as any}\n onValueChange={handleValueChange as any}\n {...props}\n >\n {children}\n </BaseAccordion.Root>\n </AccordionContext>\n )\n}\n\nAccordion.displayName = 'Accordion'\n\nexport const useAccordionContext = () => {\n const context = useContext(AccordionContext)\n\n if (!context) {\n throw Error('useAccordionContext must be used within a Accordion provider')\n }\n\n return context\n}\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { useAccordionContext } from './Accordion'\nimport { useRenderSlot } from './useRenderSlot'\n\ntype ExtentedZagInterface = Omit<ComponentProps<typeof BaseAccordion.Item>, 'render'>\n\nexport interface AccordionItemProps extends ExtentedZagInterface {\n asChild?: boolean\n ref?: Ref<HTMLDivElement>\n}\n\n/**\n * Groups an accordion header with the corresponding panel. Renders a <div> element.\n */\nexport const Item = ({\n asChild = false,\n className,\n children,\n ref,\n ...props\n}: AccordionItemProps) => {\n const accordion = useAccordionContext()\n\n const renderSlot = useRenderSlot(asChild, 'div')\n\n return (\n <BaseAccordion.Item\n ref={ref}\n data-spark-component=\"accordion-item\"\n render={renderSlot}\n className={cx(\n 'relative first:rounded-t-lg last:rounded-b-lg',\n 'not-last:border-b-0',\n { 'border-sm border-outline': accordion.design === 'outlined' },\n className\n )}\n {...props}\n >\n {children}\n </BaseAccordion.Item>\n )\n}\n\nItem.displayName = 'Accordion.Item'\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { useRenderSlot } from './useRenderSlot'\n\ntype ExtentedZagInterface = Omit<ComponentProps<typeof BaseAccordion.Panel>, 'render'>\n\nexport interface AccordionItemContentProps extends ExtentedZagInterface {\n asChild?: boolean\n ref?: Ref<HTMLDivElement>\n}\n\nexport const ItemContent = ({\n asChild = false,\n className,\n children,\n ref,\n ...props\n}: AccordionItemContentProps) => {\n const renderSlot = useRenderSlot(asChild, 'div')\n\n return (\n <BaseAccordion.Panel\n ref={ref}\n data-spark-component=\"accordion-item-content\"\n className={cx(\n '[&>:first-child]:p-lg overflow-hidden',\n 'h-[var(--accordion-panel-height)] transition-all duration-200 data-[ending-style]:h-0 data-[starting-style]:h-0',\n 'text-body-1 text-on-surface',\n className\n )}\n render={renderSlot}\n {...props}\n >\n {children}\n </BaseAccordion.Panel>\n )\n}\n\nItemContent.displayName = 'Accordion.ItemContent'\n","import { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { Slot } from '../slot'\n\nexport interface AccordionItemHeaderProps extends ComponentProps<'h3'> {\n asChild?: boolean\n ref?: Ref<HTMLHeadingElement>\n}\n\nexport const ItemHeader = ({\n asChild = false,\n children,\n className,\n ref,\n}: AccordionItemHeaderProps) => {\n const Component = asChild ? Slot : 'h3'\n\n return (\n <Component\n ref={ref}\n data-spark-component=\"accordion-item-header\"\n className={cx('rounded-[inherit]', className)}\n >\n {children}\n </Component>\n )\n}\n\nItemHeader.displayName = 'Accordion.ItemHeader'\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { ArrowHorizontalDown } from '@spark-ui/icons/ArrowHorizontalDown'\nimport { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { Icon } from '../icon'\nimport { useAccordionContext } from './Accordion'\nimport { useRenderSlot } from './useRenderSlot'\n\ntype ExtentedZagInterface = Omit<ComponentProps<typeof BaseAccordion.Trigger>, 'render'>\n\nexport interface AccordionItemTriggerProps extends ExtentedZagInterface {\n asChild?: boolean\n ref?: Ref<HTMLButtonElement>\n}\n\nexport const ItemTrigger = ({\n asChild = false,\n children,\n className,\n ref,\n ...props\n}: AccordionItemTriggerProps) => {\n const renderSlot = useRenderSlot(asChild, 'button')\n const { intent } = useAccordionContext()\n\n return (\n <BaseAccordion.Trigger\n ref={ref}\n data-spark-component=\"accordion-item-trigger\"\n render={renderSlot}\n className={cx(\n 'group',\n 'gap-lg min-h-sz-48 relative flex items-center justify-between',\n 'px-lg py-md text-headline-2 data-panel-open:rounded-b-0 w-full rounded-[inherit] text-left',\n 'focus-visible:u-outline focus-visible:z-raised focus-visible:outline-hidden',\n 'data-disabled:opacity-dim-3 cursor-pointer data-disabled:cursor-not-allowed',\n intent === 'surface' &&\n 'bg-surface text-on-surface hover:enabled:bg-surface-hovered focus:bg-surface-hovered',\n intent === 'support' &&\n 'bg-support-container text-on-support-container hover:enabled:bg-support-container-hovered focus:bg-support-container-hovered',\n className\n )}\n {...props}\n >\n <div className=\"gap-lg flex grow items-center\">{children}</div>\n <Icon\n intent=\"neutral\"\n className={cx(\n 'shrink-0 rotate-0 duration-100 ease-in motion-reduce:transition-none',\n 'group-data-panel-open:rotate-180'\n )}\n size=\"sm\"\n >\n <ArrowHorizontalDown />\n </Icon>\n </BaseAccordion.Trigger>\n )\n}\n\nItemTrigger.displayName = 'Accordion.ItemTrigger'\n","import { Accordion as Root } from './Accordion'\nimport { Item } from './AccordionItem'\nimport { ItemContent } from './AccordionItemContent'\nimport { ItemHeader } from './AccordionItemHeader'\nimport { ItemTrigger } from './AccordionItemTrigger'\n\n/**\n * A vertically stacked set of expandable sections that allow users to show and hide content.\n */\nexport const Accordion: typeof Root & {\n Item: typeof Item\n ItemHeader: typeof ItemHeader\n ItemTrigger: typeof ItemTrigger\n ItemContent: typeof ItemContent\n} = Object.assign(Root, {\n Item,\n ItemHeader,\n ItemTrigger,\n ItemContent,\n})\n\nAccordion.displayName = 'Accordion'\nItem.displayName = 'Item'\nItemHeader.displayName = 'ItemHeader'\nItemTrigger.displayName = 'Accordion.Trigger'\nItemContent.displayName = 'Accordion.Content'\n\nexport { type AccordionProps } from './Accordion'\nexport { type AccordionItemHeaderProps } from './AccordionItemHeader'\nexport { type AccordionItemContentProps } from './AccordionItemContent'\nexport { type AccordionItemTriggerProps } from './AccordionItemTrigger'\n"],"mappings":"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"}
|
package/dist/accordion/index.mjs
CHANGED
|
@@ -13,23 +13,26 @@ function l(t, n) {
|
|
|
13
13
|
//#endregion
|
|
14
14
|
//#region src/accordion/Accordion.tsx
|
|
15
15
|
var u = i(null);
|
|
16
|
-
function d({ asChild: e = !1, children: t, design: i = "outlined",
|
|
17
|
-
let
|
|
18
|
-
|
|
16
|
+
function d({ asChild: e = !1, children: t, design: i = "outlined", intent: a = "surface", hiddenUntilFound: s = !0, multiple: c = !1, className: d, ref: f, value: p, defaultValue: m, onValueChange: h, ...g }) {
|
|
17
|
+
let _ = l(e, "div"), v = h ? (e) => {
|
|
18
|
+
h(Array.isArray(e) ? e : [e]);
|
|
19
19
|
} : void 0;
|
|
20
20
|
return /* @__PURE__ */ o(u, {
|
|
21
|
-
value: {
|
|
21
|
+
value: {
|
|
22
|
+
design: i,
|
|
23
|
+
intent: a
|
|
24
|
+
},
|
|
22
25
|
children: /* @__PURE__ */ o(n.Root, {
|
|
23
26
|
"data-spark-component": "accordion",
|
|
24
|
-
ref:
|
|
25
|
-
multiple:
|
|
26
|
-
hiddenUntilFound:
|
|
27
|
-
className: r("bg-surface h-fit rounded-lg",
|
|
28
|
-
render:
|
|
29
|
-
value:
|
|
30
|
-
defaultValue:
|
|
31
|
-
onValueChange:
|
|
32
|
-
...
|
|
27
|
+
ref: f,
|
|
28
|
+
multiple: c,
|
|
29
|
+
hiddenUntilFound: s,
|
|
30
|
+
className: r("bg-surface h-fit rounded-lg", d),
|
|
31
|
+
render: _,
|
|
32
|
+
value: p,
|
|
33
|
+
defaultValue: m,
|
|
34
|
+
onValueChange: v,
|
|
35
|
+
...g,
|
|
33
36
|
children: t
|
|
34
37
|
})
|
|
35
38
|
});
|
|
@@ -77,19 +80,19 @@ h.displayName = "Accordion.ItemHeader";
|
|
|
77
80
|
//#endregion
|
|
78
81
|
//#region src/accordion/AccordionItemTrigger.tsx
|
|
79
82
|
var g = ({ asChild: e = !1, children: i, className: a, ref: u, ...d }) => {
|
|
80
|
-
let
|
|
83
|
+
let p = l(e, "button"), { intent: m } = f();
|
|
81
84
|
return /* @__PURE__ */ s(n.Trigger, {
|
|
82
85
|
ref: u,
|
|
83
86
|
"data-spark-component": "accordion-item-trigger",
|
|
84
|
-
render:
|
|
85
|
-
className: r("group", "gap-lg min-h-sz-48 relative flex items-center justify-between", "px-lg py-md text-headline-2
|
|
87
|
+
render: p,
|
|
88
|
+
className: r("group", "gap-lg min-h-sz-48 relative flex items-center justify-between", "px-lg py-md text-headline-2 data-panel-open:rounded-b-0 w-full rounded-[inherit] text-left", "focus-visible:u-outline focus-visible:z-raised focus-visible:outline-hidden", "data-disabled:opacity-dim-3 cursor-pointer data-disabled:cursor-not-allowed", m === "surface" && "bg-surface text-on-surface hover:enabled:bg-surface-hovered focus:bg-surface-hovered", m === "support" && "bg-support-container text-on-support-container hover:enabled:bg-support-container-hovered focus:bg-support-container-hovered", a),
|
|
86
89
|
...d,
|
|
87
90
|
children: [/* @__PURE__ */ o("div", {
|
|
88
91
|
className: "gap-lg flex grow items-center",
|
|
89
92
|
children: i
|
|
90
93
|
}), /* @__PURE__ */ o(t, {
|
|
91
94
|
intent: "neutral",
|
|
92
|
-
className: r("shrink-0 rotate-0 duration-100 ease-in motion-reduce:transition-none", "group-data-
|
|
95
|
+
className: r("shrink-0 rotate-0 duration-100 ease-in motion-reduce:transition-none", "group-data-panel-open:rotate-180"),
|
|
93
96
|
size: "sm",
|
|
94
97
|
children: /* @__PURE__ */ o(c, {})
|
|
95
98
|
})]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/accordion/useRenderSlot.tsx","../../src/accordion/Accordion.tsx","../../src/accordion/AccordionItem.tsx","../../src/accordion/AccordionItemContent.tsx","../../src/accordion/AccordionItemHeader.tsx","../../src/accordion/AccordionItemTrigger.tsx","../../src/accordion/index.ts"],"sourcesContent":["import { Slot } from '../slot'\n\nexport function useRenderSlot(asChild: boolean, defaultTag: string) {\n const Component = asChild ? Slot : defaultTag\n\n return asChild ? ({ ...props }) => <Component {...props} /> : undefined\n}\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { cx } from 'class-variance-authority'\nimport { ComponentProps, createContext, Ref, useContext } from 'react'\n\nimport { useRenderSlot } from './useRenderSlot'\n\ntype BaseAccordionRootProps = ComponentProps<typeof BaseAccordion.Root<string | string[]>>\n\ntype ExtentedBaseUIInterface = Omit<\n BaseAccordionRootProps,\n 'multiple' | 'render' | 'value' | 'defaultValue' | 'onValueChange'\n>\n\nexport interface AccordionProps extends ExtentedBaseUIInterface {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n /**\n * Whether the accordion items are disabled\n */\n disabled?: boolean\n /**\n * Whether multiple items can be open at the same time.\n */\n multiple?: boolean\n design?: 'filled' | 'outlined'\n ref?: Ref<HTMLDivElement>\n /**\n * The controlled value (always an array of strings)\n */\n value?: string[]\n /**\n * The default value (always an array of strings)\n */\n defaultValue?: string[]\n /**\n * Callback when the value changes (always receives an array of strings)\n */\n onValueChange?: (value: string[]) => void\n}\n\nconst AccordionContext = createContext<{\n design: 'filled' | 'outlined'\n} | null>(null)\n\nexport function Accordion({\n asChild = false,\n children,\n design = 'outlined',\n hiddenUntilFound = true,\n multiple = false,\n className,\n ref,\n value,\n defaultValue,\n onValueChange,\n ...props\n}: AccordionProps) {\n const renderSlot = useRenderSlot(asChild, 'div')\n\n // Wrap the onValueChange to always provide string[]\n const handleValueChange = onValueChange\n ? (newValue: string | string[]) => {\n // Base UI returns string when multiple=false, string[] when multiple=true\n // We normalize to always return string[]\n const normalizedValue = Array.isArray(newValue) ? newValue : [newValue]\n onValueChange(normalizedValue)\n }\n : undefined\n\n return (\n <AccordionContext value={{ design }}>\n <BaseAccordion.Root\n data-spark-component=\"accordion\"\n ref={ref}\n multiple={multiple}\n hiddenUntilFound={hiddenUntilFound}\n className={cx('bg-surface h-fit rounded-lg', className)}\n render={renderSlot}\n value={value as any}\n defaultValue={defaultValue as any}\n onValueChange={handleValueChange as any}\n {...props}\n >\n {children}\n </BaseAccordion.Root>\n </AccordionContext>\n )\n}\n\nAccordion.displayName = 'Accordion'\n\nexport const useAccordionContext = () => {\n const context = useContext(AccordionContext)\n\n if (!context) {\n throw Error('useAccordionContext must be used within a Accordion provider')\n }\n\n return context\n}\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { useAccordionContext } from './Accordion'\nimport { useRenderSlot } from './useRenderSlot'\n\ntype ExtentedZagInterface = Omit<ComponentProps<typeof BaseAccordion.Item>, 'render'>\n\nexport interface AccordionItemProps extends ExtentedZagInterface {\n asChild?: boolean\n ref?: Ref<HTMLDivElement>\n}\n\n/**\n * Groups an accordion header with the corresponding panel. Renders a <div> element.\n */\nexport const Item = ({\n asChild = false,\n className,\n children,\n ref,\n ...props\n}: AccordionItemProps) => {\n const accordion = useAccordionContext()\n\n const renderSlot = useRenderSlot(asChild, 'div')\n\n return (\n <BaseAccordion.Item\n ref={ref}\n data-spark-component=\"accordion-item\"\n render={renderSlot}\n className={cx(\n 'relative first:rounded-t-lg last:rounded-b-lg',\n 'not-last:border-b-0',\n { 'border-sm border-outline': accordion.design === 'outlined' },\n className\n )}\n {...props}\n >\n {children}\n </BaseAccordion.Item>\n )\n}\n\nItem.displayName = 'Accordion.Item'\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { useRenderSlot } from './useRenderSlot'\n\ntype ExtentedZagInterface = Omit<ComponentProps<typeof BaseAccordion.Panel>, 'render'>\n\nexport interface AccordionItemContentProps extends ExtentedZagInterface {\n asChild?: boolean\n ref?: Ref<HTMLDivElement>\n}\n\nexport const ItemContent = ({\n asChild = false,\n className,\n children,\n ref,\n ...props\n}: AccordionItemContentProps) => {\n const renderSlot = useRenderSlot(asChild, 'div')\n\n return (\n <BaseAccordion.Panel\n ref={ref}\n data-spark-component=\"accordion-item-content\"\n className={cx(\n '[&>:first-child]:p-lg overflow-hidden',\n 'h-[var(--accordion-panel-height)] transition-all duration-200 data-[ending-style]:h-0 data-[starting-style]:h-0',\n 'text-body-1 text-on-surface',\n className\n )}\n render={renderSlot}\n {...props}\n >\n {children}\n </BaseAccordion.Panel>\n )\n}\n\nItemContent.displayName = 'Accordion.ItemContent'\n","import { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { Slot } from '../slot'\n\nexport interface AccordionItemHeaderProps extends ComponentProps<'h3'> {\n asChild?: boolean\n ref?: Ref<HTMLHeadingElement>\n}\n\nexport const ItemHeader = ({\n asChild = false,\n children,\n className,\n ref,\n}: AccordionItemHeaderProps) => {\n const Component = asChild ? Slot : 'h3'\n\n return (\n <Component\n ref={ref}\n data-spark-component=\"accordion-item-header\"\n className={cx('rounded-[inherit]', className)}\n >\n {children}\n </Component>\n )\n}\n\nItemHeader.displayName = 'Accordion.ItemHeader'\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { ArrowHorizontalDown } from '@spark-ui/icons/ArrowHorizontalDown'\nimport { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { Icon } from '../icon'\nimport { useRenderSlot } from './useRenderSlot'\n\ntype ExtentedZagInterface = Omit<ComponentProps<typeof BaseAccordion.Trigger>, 'render'>\n\nexport interface AccordionItemTriggerProps extends ExtentedZagInterface {\n asChild?: boolean\n ref?: Ref<HTMLButtonElement>\n}\n\nexport const ItemTrigger = ({\n asChild = false,\n children,\n className,\n ref,\n ...props\n}: AccordionItemTriggerProps) => {\n const renderSlot = useRenderSlot(asChild, 'button')\n\n return (\n <BaseAccordion.Trigger\n ref={ref}\n data-spark-component=\"accordion-item-trigger\"\n render={renderSlot}\n className={cx(\n 'group',\n 'gap-lg min-h-sz-48 relative flex items-center justify-between',\n 'px-lg py-md text-headline-2 text-on-surface data-[panel-open]:rounded-b-0 w-full rounded-[inherit] text-left',\n 'hover:enabled:bg-surface-hovered focus:bg-surface-hovered',\n 'focus-visible:u-outline focus-visible:z-raised focus-visible:outline-hidden',\n 'disabled:opacity-dim-3 cursor-pointer disabled:cursor-not-allowed',\n className\n )}\n {...props}\n >\n <div className=\"gap-lg flex grow items-center\">{children}</div>\n <Icon\n intent=\"neutral\"\n className={cx(\n 'shrink-0 rotate-0 duration-100 ease-in motion-reduce:transition-none',\n 'group-data-[panel-open]:rotate-180'\n )}\n size=\"sm\"\n >\n <ArrowHorizontalDown />\n </Icon>\n </BaseAccordion.Trigger>\n )\n}\n\nItemTrigger.displayName = 'Accordion.ItemTrigger'\n","import { Accordion as Root } from './Accordion'\nimport { Item } from './AccordionItem'\nimport { ItemContent } from './AccordionItemContent'\nimport { ItemHeader } from './AccordionItemHeader'\nimport { ItemTrigger } from './AccordionItemTrigger'\n\n/**\n * A vertically stacked set of expandable sections that allow users to show and hide content.\n */\nexport const Accordion: typeof Root & {\n Item: typeof Item\n ItemHeader: typeof ItemHeader\n ItemTrigger: typeof ItemTrigger\n ItemContent: typeof ItemContent\n} = Object.assign(Root, {\n Item,\n ItemHeader,\n ItemTrigger,\n ItemContent,\n})\n\nAccordion.displayName = 'Accordion'\nItem.displayName = 'Item'\nItemHeader.displayName = 'ItemHeader'\nItemTrigger.displayName = 'Accordion.Trigger'\nItemContent.displayName = 'Accordion.Content'\n\nexport { type AccordionProps } from './Accordion'\nexport { type AccordionItemHeaderProps } from './AccordionItemHeader'\nexport { type AccordionItemContentProps } from './AccordionItemContent'\nexport { type AccordionItemTriggerProps } from './AccordionItemTrigger'\n"],"mappings":";;;;;;;;AAEA,SAAgB,EAAc,GAAkB,GAAoB;CAClE,IAAM,IAAY,IAAU,IAAO;AAEnC,QAAO,KAAW,EAAE,GAAG,QAAY,kBAAC,GAAD,EAAW,GAAI,GAAS,CAAA,GAAG,KAAA;;;;ACqChE,IAAM,IAAmB,EAEf,KAAK;AAEf,SAAgB,EAAU,EACxB,aAAU,IACV,aACA,YAAS,YACT,sBAAmB,IACnB,cAAW,IACX,cACA,QACA,UACA,iBACA,kBACA,GAAG,KACc;CACjB,IAAM,IAAa,EAAc,GAAS,MAAM,EAG1C,IAAoB,KACrB,MAAgC;AAI/B,IADwB,MAAM,QAAQ,EAAS,GAAG,IAAW,CAAC,EAAS,CACzC;KAEhC,KAAA;AAEJ,QACE,kBAAC,GAAD;EAAkB,OAAO,EAAE,WAAQ;YACjC,kBAAC,EAAc,MAAf;GACE,wBAAqB;GAChB;GACK;GACQ;GAClB,WAAW,EAAG,+BAA+B,EAAU;GACvD,QAAQ;GACD;GACO;GACd,eAAe;GACf,GAAI;GAEH;GACkB,CAAA;EACJ,CAAA;;AAIvB,EAAU,cAAc;AAExB,IAAa,UAA4B;CACvC,IAAM,IAAU,EAAW,EAAiB;AAE5C,KAAI,CAAC,EACH,OAAM,MAAM,+DAA+D;AAG7E,QAAO;GCnFI,KAAQ,EACnB,aAAU,IACV,cACA,aACA,QACA,GAAG,QACqB;CACxB,IAAM,IAAY,GAAqB,EAEjC,IAAa,EAAc,GAAS,MAAM;AAEhD,QACE,kBAAC,EAAc,MAAf;EACO;EACL,wBAAqB;EACrB,QAAQ;EACR,WAAW,EACT,iDACA,uBACA,EAAE,4BAA4B,EAAU,WAAW,YAAY,EAC/D,EACD;EACD,GAAI;EAEH;EACkB,CAAA;;AAIzB,EAAK,cAAc;;;ACjCnB,IAAa,KAAe,EAC1B,aAAU,IACV,cACA,aACA,QACA,GAAG,QAC4B;CAC/B,IAAM,IAAa,EAAc,GAAS,MAAM;AAEhD,QACE,kBAAC,EAAc,OAAf;EACO;EACL,wBAAqB;EACrB,WAAW,EACT,yCACA,mHACA,+BACA,EACD;EACD,QAAQ;EACR,GAAI;EAEH;EACmB,CAAA;;AAI1B,EAAY,cAAc;;;AC9B1B,IAAa,KAAc,EACzB,aAAU,IACV,aACA,cACA,aAKE,kBAHgB,IAAU,IAAO,MAGjC;CACO;CACL,wBAAqB;CACrB,WAAW,EAAG,qBAAqB,EAAU;CAE5C;CACS,CAAA;AAIhB,EAAW,cAAc;;;ACdzB,IAAa,KAAe,EAC1B,aAAU,IACV,aACA,cACA,QACA,GAAG,QAC4B;CAC/B,IAAM,IAAa,EAAc,GAAS,SAAS;AAEnD,QACE,kBAAC,EAAc,SAAf;EACO;EACL,wBAAqB;EACrB,QAAQ;EACR,WAAW,EACT,SACA,iEACA,gHACA,6DACA,+EACA,qEACA,EACD;EACD,GAAI;YAbN,CAeE,kBAAC,OAAD;GAAK,WAAU;GAAiC;GAAe,CAAA,EAC/D,kBAAC,GAAD;GACE,QAAO;GACP,WAAW,EACT,wEACA,qCACD;GACD,MAAK;aAEL,kBAAC,GAAD,EAAuB,CAAA;GAClB,CAAA,CACe;;;AAI5B,EAAY,cAAc;;;AC9C1B,IAAa,IAKT,OAAO,OAAO,GAAM;CACtB;CACA;CACA;CACA;CACD,CAAC;AAEF,EAAU,cAAc,aACxB,EAAK,cAAc,QACnB,EAAW,cAAc,cACzB,EAAY,cAAc,qBAC1B,EAAY,cAAc"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/accordion/useRenderSlot.tsx","../../src/accordion/Accordion.tsx","../../src/accordion/AccordionItem.tsx","../../src/accordion/AccordionItemContent.tsx","../../src/accordion/AccordionItemHeader.tsx","../../src/accordion/AccordionItemTrigger.tsx","../../src/accordion/index.ts"],"sourcesContent":["import { Slot } from '../slot'\n\nexport function useRenderSlot(asChild: boolean, defaultTag: string) {\n const Component = asChild ? Slot : defaultTag\n\n return asChild ? ({ ...props }) => <Component {...props} /> : undefined\n}\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { cx } from 'class-variance-authority'\nimport { ComponentProps, createContext, Ref, useContext } from 'react'\n\nimport { useRenderSlot } from './useRenderSlot'\n\ntype BaseAccordionRootProps = ComponentProps<typeof BaseAccordion.Root<string | string[]>>\n\ntype ExtentedBaseUIInterface = Omit<\n BaseAccordionRootProps,\n 'multiple' | 'render' | 'value' | 'defaultValue' | 'onValueChange'\n>\n\nexport interface AccordionProps extends ExtentedBaseUIInterface {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n /**\n * Whether the accordion items are disabled\n */\n disabled?: boolean\n /**\n * Whether multiple items can be open at the same time.\n */\n multiple?: boolean\n design?: 'filled' | 'outlined'\n /**\n * Change the color scheme of the accordion\n * @default surface\n */\n intent?: 'surface' | 'support'\n ref?: Ref<HTMLDivElement>\n /**\n * The controlled value (always an array of strings)\n */\n value?: string[]\n /**\n * The default value (always an array of strings)\n */\n defaultValue?: string[]\n /**\n * Callback when the value changes (always receives an array of strings)\n */\n onValueChange?: (value: string[]) => void\n}\n\nconst AccordionContext = createContext<{\n design: 'filled' | 'outlined'\n intent: 'surface' | 'support'\n} | null>(null)\n\nexport function Accordion({\n asChild = false,\n children,\n design = 'outlined',\n intent = 'surface',\n hiddenUntilFound = true,\n multiple = false,\n className,\n ref,\n value,\n defaultValue,\n onValueChange,\n ...props\n}: AccordionProps) {\n const renderSlot = useRenderSlot(asChild, 'div')\n\n // Wrap the onValueChange to always provide string[]\n const handleValueChange = onValueChange\n ? (newValue: string | string[]) => {\n // Base UI returns string when multiple=false, string[] when multiple=true\n // We normalize to always return string[]\n const normalizedValue = Array.isArray(newValue) ? newValue : [newValue]\n onValueChange(normalizedValue)\n }\n : undefined\n\n return (\n <AccordionContext value={{ design, intent }}>\n <BaseAccordion.Root\n data-spark-component=\"accordion\"\n ref={ref}\n multiple={multiple}\n hiddenUntilFound={hiddenUntilFound}\n className={cx('bg-surface h-fit rounded-lg', className)}\n render={renderSlot}\n value={value as any}\n defaultValue={defaultValue as any}\n onValueChange={handleValueChange as any}\n {...props}\n >\n {children}\n </BaseAccordion.Root>\n </AccordionContext>\n )\n}\n\nAccordion.displayName = 'Accordion'\n\nexport const useAccordionContext = () => {\n const context = useContext(AccordionContext)\n\n if (!context) {\n throw Error('useAccordionContext must be used within a Accordion provider')\n }\n\n return context\n}\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { useAccordionContext } from './Accordion'\nimport { useRenderSlot } from './useRenderSlot'\n\ntype ExtentedZagInterface = Omit<ComponentProps<typeof BaseAccordion.Item>, 'render'>\n\nexport interface AccordionItemProps extends ExtentedZagInterface {\n asChild?: boolean\n ref?: Ref<HTMLDivElement>\n}\n\n/**\n * Groups an accordion header with the corresponding panel. Renders a <div> element.\n */\nexport const Item = ({\n asChild = false,\n className,\n children,\n ref,\n ...props\n}: AccordionItemProps) => {\n const accordion = useAccordionContext()\n\n const renderSlot = useRenderSlot(asChild, 'div')\n\n return (\n <BaseAccordion.Item\n ref={ref}\n data-spark-component=\"accordion-item\"\n render={renderSlot}\n className={cx(\n 'relative first:rounded-t-lg last:rounded-b-lg',\n 'not-last:border-b-0',\n { 'border-sm border-outline': accordion.design === 'outlined' },\n className\n )}\n {...props}\n >\n {children}\n </BaseAccordion.Item>\n )\n}\n\nItem.displayName = 'Accordion.Item'\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { useRenderSlot } from './useRenderSlot'\n\ntype ExtentedZagInterface = Omit<ComponentProps<typeof BaseAccordion.Panel>, 'render'>\n\nexport interface AccordionItemContentProps extends ExtentedZagInterface {\n asChild?: boolean\n ref?: Ref<HTMLDivElement>\n}\n\nexport const ItemContent = ({\n asChild = false,\n className,\n children,\n ref,\n ...props\n}: AccordionItemContentProps) => {\n const renderSlot = useRenderSlot(asChild, 'div')\n\n return (\n <BaseAccordion.Panel\n ref={ref}\n data-spark-component=\"accordion-item-content\"\n className={cx(\n '[&>:first-child]:p-lg overflow-hidden',\n 'h-[var(--accordion-panel-height)] transition-all duration-200 data-[ending-style]:h-0 data-[starting-style]:h-0',\n 'text-body-1 text-on-surface',\n className\n )}\n render={renderSlot}\n {...props}\n >\n {children}\n </BaseAccordion.Panel>\n )\n}\n\nItemContent.displayName = 'Accordion.ItemContent'\n","import { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { Slot } from '../slot'\n\nexport interface AccordionItemHeaderProps extends ComponentProps<'h3'> {\n asChild?: boolean\n ref?: Ref<HTMLHeadingElement>\n}\n\nexport const ItemHeader = ({\n asChild = false,\n children,\n className,\n ref,\n}: AccordionItemHeaderProps) => {\n const Component = asChild ? Slot : 'h3'\n\n return (\n <Component\n ref={ref}\n data-spark-component=\"accordion-item-header\"\n className={cx('rounded-[inherit]', className)}\n >\n {children}\n </Component>\n )\n}\n\nItemHeader.displayName = 'Accordion.ItemHeader'\n","import { Accordion as BaseAccordion } from '@base-ui/react/accordion'\nimport { ArrowHorizontalDown } from '@spark-ui/icons/ArrowHorizontalDown'\nimport { cx } from 'class-variance-authority'\nimport { type ComponentProps, Ref } from 'react'\n\nimport { Icon } from '../icon'\nimport { useAccordionContext } from './Accordion'\nimport { useRenderSlot } from './useRenderSlot'\n\ntype ExtentedZagInterface = Omit<ComponentProps<typeof BaseAccordion.Trigger>, 'render'>\n\nexport interface AccordionItemTriggerProps extends ExtentedZagInterface {\n asChild?: boolean\n ref?: Ref<HTMLButtonElement>\n}\n\nexport const ItemTrigger = ({\n asChild = false,\n children,\n className,\n ref,\n ...props\n}: AccordionItemTriggerProps) => {\n const renderSlot = useRenderSlot(asChild, 'button')\n const { intent } = useAccordionContext()\n\n return (\n <BaseAccordion.Trigger\n ref={ref}\n data-spark-component=\"accordion-item-trigger\"\n render={renderSlot}\n className={cx(\n 'group',\n 'gap-lg min-h-sz-48 relative flex items-center justify-between',\n 'px-lg py-md text-headline-2 data-panel-open:rounded-b-0 w-full rounded-[inherit] text-left',\n 'focus-visible:u-outline focus-visible:z-raised focus-visible:outline-hidden',\n 'data-disabled:opacity-dim-3 cursor-pointer data-disabled:cursor-not-allowed',\n intent === 'surface' &&\n 'bg-surface text-on-surface hover:enabled:bg-surface-hovered focus:bg-surface-hovered',\n intent === 'support' &&\n 'bg-support-container text-on-support-container hover:enabled:bg-support-container-hovered focus:bg-support-container-hovered',\n className\n )}\n {...props}\n >\n <div className=\"gap-lg flex grow items-center\">{children}</div>\n <Icon\n intent=\"neutral\"\n className={cx(\n 'shrink-0 rotate-0 duration-100 ease-in motion-reduce:transition-none',\n 'group-data-panel-open:rotate-180'\n )}\n size=\"sm\"\n >\n <ArrowHorizontalDown />\n </Icon>\n </BaseAccordion.Trigger>\n )\n}\n\nItemTrigger.displayName = 'Accordion.ItemTrigger'\n","import { Accordion as Root } from './Accordion'\nimport { Item } from './AccordionItem'\nimport { ItemContent } from './AccordionItemContent'\nimport { ItemHeader } from './AccordionItemHeader'\nimport { ItemTrigger } from './AccordionItemTrigger'\n\n/**\n * A vertically stacked set of expandable sections that allow users to show and hide content.\n */\nexport const Accordion: typeof Root & {\n Item: typeof Item\n ItemHeader: typeof ItemHeader\n ItemTrigger: typeof ItemTrigger\n ItemContent: typeof ItemContent\n} = Object.assign(Root, {\n Item,\n ItemHeader,\n ItemTrigger,\n ItemContent,\n})\n\nAccordion.displayName = 'Accordion'\nItem.displayName = 'Item'\nItemHeader.displayName = 'ItemHeader'\nItemTrigger.displayName = 'Accordion.Trigger'\nItemContent.displayName = 'Accordion.Content'\n\nexport { type AccordionProps } from './Accordion'\nexport { type AccordionItemHeaderProps } from './AccordionItemHeader'\nexport { type AccordionItemContentProps } from './AccordionItemContent'\nexport { type AccordionItemTriggerProps } from './AccordionItemTrigger'\n"],"mappings":";;;;;;;;AAEA,SAAgB,EAAc,GAAkB,GAAoB;CAClE,IAAM,IAAY,IAAU,IAAO;AAEnC,QAAO,KAAW,EAAE,GAAG,QAAY,kBAAC,GAAD,EAAW,GAAI,GAAS,CAAA,GAAG,KAAA;;;;AC0ChE,IAAM,IAAmB,EAGf,KAAK;AAEf,SAAgB,EAAU,EACxB,aAAU,IACV,aACA,YAAS,YACT,YAAS,WACT,sBAAmB,IACnB,cAAW,IACX,cACA,QACA,UACA,iBACA,kBACA,GAAG,KACc;CACjB,IAAM,IAAa,EAAc,GAAS,MAAM,EAG1C,IAAoB,KACrB,MAAgC;AAI/B,IADwB,MAAM,QAAQ,EAAS,GAAG,IAAW,CAAC,EAAS,CACzC;KAEhC,KAAA;AAEJ,QACE,kBAAC,GAAD;EAAkB,OAAO;GAAE;GAAQ;GAAQ;YACzC,kBAAC,EAAc,MAAf;GACE,wBAAqB;GAChB;GACK;GACQ;GAClB,WAAW,EAAG,+BAA+B,EAAU;GACvD,QAAQ;GACD;GACO;GACd,eAAe;GACf,GAAI;GAEH;GACkB,CAAA;EACJ,CAAA;;AAIvB,EAAU,cAAc;AAExB,IAAa,UAA4B;CACvC,IAAM,IAAU,EAAW,EAAiB;AAE5C,KAAI,CAAC,EACH,OAAM,MAAM,+DAA+D;AAG7E,QAAO;GC1FI,KAAQ,EACnB,aAAU,IACV,cACA,aACA,QACA,GAAG,QACqB;CACxB,IAAM,IAAY,GAAqB,EAEjC,IAAa,EAAc,GAAS,MAAM;AAEhD,QACE,kBAAC,EAAc,MAAf;EACO;EACL,wBAAqB;EACrB,QAAQ;EACR,WAAW,EACT,iDACA,uBACA,EAAE,4BAA4B,EAAU,WAAW,YAAY,EAC/D,EACD;EACD,GAAI;EAEH;EACkB,CAAA;;AAIzB,EAAK,cAAc;;;ACjCnB,IAAa,KAAe,EAC1B,aAAU,IACV,cACA,aACA,QACA,GAAG,QAC4B;CAC/B,IAAM,IAAa,EAAc,GAAS,MAAM;AAEhD,QACE,kBAAC,EAAc,OAAf;EACO;EACL,wBAAqB;EACrB,WAAW,EACT,yCACA,mHACA,+BACA,EACD;EACD,QAAQ;EACR,GAAI;EAEH;EACmB,CAAA;;AAI1B,EAAY,cAAc;;;AC9B1B,IAAa,KAAc,EACzB,aAAU,IACV,aACA,cACA,aAKE,kBAHgB,IAAU,IAAO,MAGjC;CACO;CACL,wBAAqB;CACrB,WAAW,EAAG,qBAAqB,EAAU;CAE5C;CACS,CAAA;AAIhB,EAAW,cAAc;;;ACbzB,IAAa,KAAe,EAC1B,aAAU,IACV,aACA,cACA,QACA,GAAG,QAC4B;CAC/B,IAAM,IAAa,EAAc,GAAS,SAAS,EAC7C,EAAE,cAAW,GAAqB;AAExC,QACE,kBAAC,EAAc,SAAf;EACO;EACL,wBAAqB;EACrB,QAAQ;EACR,WAAW,EACT,SACA,iEACA,8FACA,+EACA,+EACA,MAAW,aACT,wFACF,MAAW,aACT,gIACF,EACD;EACD,GAAI;YAhBN,CAkBE,kBAAC,OAAD;GAAK,WAAU;GAAiC;GAAe,CAAA,EAC/D,kBAAC,GAAD;GACE,QAAO;GACP,WAAW,EACT,wEACA,mCACD;GACD,MAAK;aAEL,kBAAC,GAAD,EAAuB,CAAA;GAClB,CAAA,CACe;;;AAI5B,EAAY,cAAc;;;ACnD1B,IAAa,IAKT,OAAO,OAAO,GAAM;CACtB;CACA;CACA;CACA;CACD,CAAC;AAEF,EAAU,cAAc,aACxB,EAAK,cAAc,QACnB,EAAW,cAAc,cACzB,EAAY,cAAc,qBAC1B,EAAY,cAAc"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const styles: (props?: ({
|
|
3
|
-
intent?: "main" | "alert" | "support" | "accent" | "success" | "info" | "neutral" | "danger" |
|
|
3
|
+
intent?: "main" | "alert" | "surface" | "support" | "accent" | "success" | "info" | "neutral" | "danger" | null | undefined;
|
|
4
4
|
size?: "sm" | "md" | null | undefined;
|
|
5
5
|
type?: "relative" | "standalone" | null | undefined;
|
|
6
6
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
@@ -2,7 +2,7 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
2
2
|
export declare const buttonStyles: (props?: ({
|
|
3
3
|
design?: "filled" | "outlined" | "ghost" | "tinted" | "contrast" | null | undefined;
|
|
4
4
|
underline?: boolean | null | undefined;
|
|
5
|
-
intent?: "main" | "alert" | "support" | "accent" | "success" | "info" | "neutral" | "danger" | "
|
|
5
|
+
intent?: "main" | "alert" | "surface" | "support" | "accent" | "success" | "info" | "neutral" | "danger" | "surfaceInverse" | null | undefined;
|
|
6
6
|
size?: "sm" | "md" | "lg" | null | undefined;
|
|
7
7
|
shape?: "square" | "rounded" | "pill" | null | undefined;
|
|
8
8
|
disabled?: boolean | null | undefined;
|
package/dist/card/Backdrop.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const backdropStyles: (props?: ({
|
|
3
3
|
animation?: "none" | "pulse" | null | undefined;
|
|
4
|
-
intent?: "main" | "alert" | "support" | "accent" | "success" | "info" | "neutral" | "danger" | "
|
|
4
|
+
intent?: "main" | "alert" | "surface" | "support" | "accent" | "success" | "info" | "neutral" | "danger" | "surfaceInverse" | null | undefined;
|
|
5
5
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
6
6
|
export type BackdropStylesProps = VariantProps<typeof backdropStyles>;
|
|
7
7
|
interface BackdropProps extends BackdropStylesProps {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const cardStyles: (props?: ({
|
|
3
3
|
design?: "outlined" | "tinted" | null | undefined;
|
|
4
|
-
intent?: "main" | "alert" | "support" | "accent" | "success" | "info" | "neutral" | "danger" |
|
|
4
|
+
intent?: "main" | "alert" | "surface" | "support" | "accent" | "success" | "info" | "neutral" | "danger" | null | undefined;
|
|
5
5
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
6
6
|
export type CardStylesProps = VariantProps<typeof cardStyles>;
|
|
@@ -3,6 +3,6 @@ export declare const contentStyles: (props?: ({
|
|
|
3
3
|
inset?: boolean | null | undefined;
|
|
4
4
|
design?: "outlined" | "tinted" | null | undefined;
|
|
5
5
|
hasType?: boolean | null | undefined;
|
|
6
|
-
intent?: "main" | "alert" | "support" | "accent" | "success" | "info" | "neutral" | "danger" |
|
|
6
|
+
intent?: "main" | "alert" | "surface" | "support" | "accent" | "success" | "info" | "neutral" | "danger" | null | undefined;
|
|
7
7
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
8
8
|
export type ContentStylesProps = VariantProps<typeof contentStyles>;
|
package/dist/card/Type.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
import { ComponentProps, ReactNode } from 'react';
|
|
3
3
|
export declare const typeStyles: (props?: ({
|
|
4
|
-
intent?: "main" | "alert" | "support" | "accent" | "success" | "info" | "neutral" | "danger" |
|
|
4
|
+
intent?: "main" | "alert" | "surface" | "support" | "accent" | "success" | "info" | "neutral" | "danger" | null | undefined;
|
|
5
5
|
design?: "outlined" | "tinted" | null | undefined;
|
|
6
6
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
7
7
|
type TypeStylesProps = VariantProps<typeof typeStyles>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const checkboxInputStyles: (props?: ({
|
|
3
|
-
intent?: "main" | "alert" | "
|
|
3
|
+
intent?: "main" | "alert" | "support" | "error" | "accent" | "success" | "info" | "neutral" | null | undefined;
|
|
4
4
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
5
5
|
export type CheckboxInputStylesProps = VariantProps<typeof checkboxInputStyles>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const chipStyles: (props?: ({
|
|
3
3
|
design?: "outlined" | "dashed" | "tinted" | null | undefined;
|
|
4
|
-
intent?: "main" | "alert" | "support" | "accent" | "success" | "info" | "neutral" | "danger" |
|
|
4
|
+
intent?: "main" | "alert" | "surface" | "support" | "accent" | "success" | "info" | "neutral" | "danger" | null | undefined;
|
|
5
5
|
disabled?: boolean | null | undefined;
|
|
6
6
|
hasClearButton?: boolean | null | undefined;
|
|
7
7
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const iconStyles: (props?: ({
|
|
3
|
-
intent?: "main" | "current" | "alert" | "
|
|
3
|
+
intent?: "main" | "current" | "alert" | "support" | "error" | "accent" | "success" | "info" | "neutral" | null | undefined;
|
|
4
4
|
size?: "current" | "sm" | "md" | "lg" | "xl" | null | undefined;
|
|
5
5
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
6
6
|
export type IconVariantsProps = VariantProps<typeof iconStyles>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const menuItemStyles: (props?: ({
|
|
3
|
-
intent?: "main" | "alert" | "support" | "accent" | "success" | "info" | "neutral" | "danger" |
|
|
3
|
+
intent?: "main" | "alert" | "surface" | "support" | "accent" | "success" | "info" | "neutral" | "danger" | null | undefined;
|
|
4
4
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
5
5
|
export type MenuItemStylesProps = VariantProps<typeof menuItemStyles>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const styles: (props?: ({
|
|
3
|
-
intent?: "main" | "alert" | "support" | "accent" | "success" | "info" | "neutral" | "danger" |
|
|
3
|
+
intent?: "main" | "alert" | "surface" | "support" | "accent" | "success" | "info" | "neutral" | "danger" | null | undefined;
|
|
4
4
|
matchTriggerWidth?: boolean | null | undefined;
|
|
5
5
|
enforceBoundaries?: boolean | null | undefined;
|
|
6
6
|
inset?: boolean | null | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const radioIndicatorStyles: (props?: ({
|
|
3
|
-
intent?: "main" | "alert" | "
|
|
3
|
+
intent?: "main" | "alert" | "support" | "error" | "accent" | "success" | "info" | "neutral" | null | undefined;
|
|
4
4
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
5
5
|
export type RadioIndicatorStylesProps = VariantProps<typeof radioIndicatorStyles>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const radioInputVariants: (props?: ({
|
|
3
|
-
intent?: "main" | "alert" | "
|
|
3
|
+
intent?: "main" | "alert" | "support" | "error" | "accent" | "success" | "info" | "neutral" | null | undefined;
|
|
4
4
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
5
5
|
export type RadioInputVariantsProps = VariantProps<typeof radioInputVariants>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IconButtonProps } from '../icon-button';
|
|
2
2
|
/** A button to scroll to the next page of items. Renders a <button> element. */
|
|
3
3
|
export declare const ScrollingListNextButton: {
|
|
4
|
-
({ "aria-label": ariaLabel, ...rest }: IconButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
({ "aria-label": ariaLabel, onClick, ...rest }: IconButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
displayName: string;
|
|
6
6
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IconButtonProps } from '../icon-button';
|
|
2
2
|
/** A button to scroll to the previous page of items. Renders a <button> element. */
|
|
3
3
|
export declare const ScrollingListPrevButton: {
|
|
4
|
-
({ "aria-label": ariaLabel, ...rest }: IconButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
({ "aria-label": ariaLabel, onClick, ...rest }: IconButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
displayName: string;
|
|
6
6
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../chunk-C91j1N6u.js`);const e=require(`../slot/index.js`),t=require(`../icon-CRPcdgYp.js`),n=require(`../button-Tv2N8_24.js`),r=require(`../icon-button-CTe0v0g7.js`);let i=require(`class-variance-authority`),a=require(`react`),o=require(`react/jsx-runtime`),s=require(`@spark-ui/hooks/use-scroll-overflow`),c=require(`@spark-ui/icons/ArrowVerticalRight`),l=require(`@spark-ui/icons/ArrowVerticalLeft`),u=require(`react-snap-carousel`);var d=(0,a.createContext)(null),f=({snapType:e=`none`,snapStop:t=`normal`,scrollBehavior:n=`smooth`,loop:r=!1,gap:c=16,withFade:l=!1,scrollPadding:f=0,children:p,className:m,...h})=>{let g=(0,a.useRef)(null),_=(0,a.useRef)(null),v=(0,u.useSnapCarousel)(),{overflow:y,refresh:b}=(0,s.useScrollOverflow)(g,{precisionTreshold:1}),{activePageIndex:x,pages:S,refresh:C}=v,w=S[x],T=w?[w[0]+1,w[w.length-1]+1]:[0,0],E=(0,a.useCallback)(()=>{C&&g.current&&setTimeout(()=>{C()},0)},[C]);(0,a.useEffect)(()=>{E()},[p,E]),(0,a.useLayoutEffect)(()=>{g.current&&requestAnimationFrame(()=>{b()})},[p,b]);let D=()=>{_.current?.focus()};return(0,o.jsxs)(d,{value:{...v,snapType:e,snapStop:t,skipKeyboardNavigation:D,scrollBehavior:n,visibleItemsRange:T,loop:r,gap:c,withFade:l,scrollPadding:f,scrollAreaRef:g,overflow:y},children:[(0,o.jsx)(`div`,{"data-spark-component":`scrolling-list`,className:(0,i.cx)(`gap-lg group/scrolling-list relative flex flex-col default:w-full`,m),...h,children:p}),(0,o.jsx)(`span`,{ref:_,className:`size-0 overflow-hidden`,tabIndex:-1})]})};f.displayName=`ScrollingList`;var p=({children:e,visibility:t=`always`,className:n,...r})=>(0,o.jsx)(`div`,{"data-spark-component":`scrolling-list-controls`,className:(0,i.cx)(`default:px-md pointer-events-none absolute inset-0 flex flex-row items-center justify-between overflow-hidden`,n),style:{"--scrolling-list-controls-opacity":t===`hover`?`0`:`1`},"data-orientation":`horizontal`,...r,children:e});p.displayName=`ScrollingList.Controls`;function m(e,t){let[n,r]=(0,a.useState)(!1);return(0,a.useEffect)(()=>{let n=e=>{r(!0);let n=e.target,i=t.current;if(n&&i){let e=n.getBoundingClientRect(),t=i.getBoundingClientRect();e.left>=t.left&&e.right<=t.right&&e.top>=t.top&&e.bottom<=t.bottom||n.scrollIntoView({behavior:`smooth`,inline:`center`,block:`nearest`})}},i=t=>{e.current&&!e.current.contains(t.relatedTarget)&&r(!1)},a=e.current;return a&&(a.addEventListener(`focusin`,n),a.addEventListener(`focusout`,i)),()=>{a&&(a.removeEventListener(`focusin`,n),a.removeEventListener(`focusout`,i))}},[e,t]),n}var h=({asChild:t=!1,children:n,index:r=0,className:s=``,...c})=>{let l=(0,a.useContext)(d),u=(0,a.useRef)(null),f=l.snapPointIndexes.has(r);return m(u,l.scrollAreaRef),(0,o.jsx)(t?e.Slot:`div`,{"data-spark-component":`scrolling-list-item`,role:`listitem`,ref:u,className:(0,i.cx)(`default:w-auto default:shrink-0`,{"snap-start":f,"snap-normal":f&&l.snapStop===`normal`,"snap-always":f&&l.snapStop===`always`},s),...c,children:n})};h.displayName=`ScrollingList.Item`;function g(...e){return t=>{e.forEach(e=>{typeof e==`function`?e(t):e&&typeof e==`object`&&`current`in e&&(e.current=t)})}}var _=({children:e,ref:t,className:n=``,...r})=>{let s=(0,a.useContext)(d),c={mandatory:`x mandatory`,proximity:`x proximity`,none:`none`},l=e=>{!s.loop&&!s.hasPrevPage||(e.preventDefault(),s.goTo(s.hasPrevPage?s.activePageIndex-1:s.pages.length-1,{behavior:s.scrollBehavior}))},u=e=>{!s.loop&&!s.hasNextPage||(e.preventDefault(),s.goTo(s.hasNextPage?s.activePageIndex+1:0,{behavior:s.scrollBehavior}))},f=e=>{e.key===`ArrowLeft`&&l(e),e.key===`ArrowRight`&&u(e)},p={scrollSnapType:c[s.snapType],scrollPaddingInline:`var(--scrolling-list-px)`,"--scrolling-list-px":`${s.scrollPadding}px`,"--scrolling-list-gap":`${s.gap}px`,...s.withFade&&{maskImage:`linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1) 44px, rgba(0, 0, 0, 1) calc(100% - 44px), rgba(0, 0, 0, 0))`,maskSize:`calc(100% + ${s.overflow.left?`0px`:`44px`} + ${s.overflow.right?`0px`:`44px`}) 100%`,maskPosition:`${s.overflow.left?`0px`:`-44px`} 0`}};return(0,o.jsx)(`div`,{"data-spark-component":`scrolling-list-items`,id:`scrolling-list-items`,role:`list`,className:(0,i.cx)(`relative transition-all duration-300`,`u-no-scrollbar overflow-x-auto scroll-smooth`,`w-full gap-(--scrolling-list-gap) default:flex default:flex-row`,`focus-visible:u-outline`,n),ref:g(s.scrollAreaRef,s.scrollRef,t),style:p,onKeyDown:f,...r,children:a.Children.map(e,(e,t)=>(0,a.isValidElement)(e)?(0,a.cloneElement)(e,{index:t}):e)})};_.displayName=`ScrollingList.Items`;var v=({"aria-label":e,...
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../chunk-C91j1N6u.js`);const e=require(`../slot/index.js`),t=require(`../icon-CRPcdgYp.js`),n=require(`../button-Tv2N8_24.js`),r=require(`../icon-button-CTe0v0g7.js`);let i=require(`class-variance-authority`),a=require(`react`),o=require(`react/jsx-runtime`),s=require(`@spark-ui/hooks/use-scroll-overflow`),c=require(`@spark-ui/icons/ArrowVerticalRight`),l=require(`@spark-ui/icons/ArrowVerticalLeft`),u=require(`react-snap-carousel`);var d=(0,a.createContext)(null),f=({snapType:e=`none`,snapStop:t=`normal`,scrollBehavior:n=`smooth`,loop:r=!1,gap:c=16,withFade:l=!1,scrollPadding:f=0,children:p,className:m,...h})=>{let g=(0,a.useRef)(null),_=(0,a.useRef)(null),v=(0,u.useSnapCarousel)(),{overflow:y,refresh:b}=(0,s.useScrollOverflow)(g,{precisionTreshold:1}),{activePageIndex:x,pages:S,refresh:C}=v,w=S[x],T=w?[w[0]+1,w[w.length-1]+1]:[0,0],E=(0,a.useCallback)(()=>{C&&g.current&&setTimeout(()=>{C()},0)},[C]);(0,a.useEffect)(()=>{E()},[p,E]),(0,a.useLayoutEffect)(()=>{g.current&&requestAnimationFrame(()=>{b()})},[p,b]);let D=()=>{_.current?.focus()};return(0,o.jsxs)(d,{value:{...v,snapType:e,snapStop:t,skipKeyboardNavigation:D,scrollBehavior:n,visibleItemsRange:T,loop:r,gap:c,withFade:l,scrollPadding:f,scrollAreaRef:g,overflow:y},children:[(0,o.jsx)(`div`,{"data-spark-component":`scrolling-list`,className:(0,i.cx)(`gap-lg group/scrolling-list relative flex flex-col default:w-full`,m),...h,children:p}),(0,o.jsx)(`span`,{ref:_,className:`size-0 overflow-hidden`,tabIndex:-1})]})};f.displayName=`ScrollingList`;var p=({children:e,visibility:t=`always`,className:n,...r})=>(0,o.jsx)(`div`,{"data-spark-component":`scrolling-list-controls`,className:(0,i.cx)(`default:px-md pointer-events-none absolute inset-0 flex flex-row items-center justify-between overflow-hidden`,n),style:{"--scrolling-list-controls-opacity":t===`hover`?`0`:`1`},"data-orientation":`horizontal`,...r,children:e});p.displayName=`ScrollingList.Controls`;function m(e,t){let[n,r]=(0,a.useState)(!1);return(0,a.useEffect)(()=>{let n=e=>{r(!0);let n=e.target,i=t.current;if(n&&i){let e=n.getBoundingClientRect(),t=i.getBoundingClientRect();e.left>=t.left&&e.right<=t.right&&e.top>=t.top&&e.bottom<=t.bottom||n.scrollIntoView({behavior:`smooth`,inline:`center`,block:`nearest`})}},i=t=>{e.current&&!e.current.contains(t.relatedTarget)&&r(!1)},a=e.current;return a&&(a.addEventListener(`focusin`,n),a.addEventListener(`focusout`,i)),()=>{a&&(a.removeEventListener(`focusin`,n),a.removeEventListener(`focusout`,i))}},[e,t]),n}var h=({asChild:t=!1,children:n,index:r=0,className:s=``,...c})=>{let l=(0,a.useContext)(d),u=(0,a.useRef)(null),f=l.snapPointIndexes.has(r);return m(u,l.scrollAreaRef),(0,o.jsx)(t?e.Slot:`div`,{"data-spark-component":`scrolling-list-item`,role:`listitem`,ref:u,className:(0,i.cx)(`default:w-auto default:shrink-0`,{"snap-start":f,"snap-normal":f&&l.snapStop===`normal`,"snap-always":f&&l.snapStop===`always`},s),...c,children:n})};h.displayName=`ScrollingList.Item`;function g(...e){return t=>{e.forEach(e=>{typeof e==`function`?e(t):e&&typeof e==`object`&&`current`in e&&(e.current=t)})}}var _=({children:e,ref:t,className:n=``,...r})=>{let s=(0,a.useContext)(d),c={mandatory:`x mandatory`,proximity:`x proximity`,none:`none`},l=e=>{!s.loop&&!s.hasPrevPage||(e.preventDefault(),s.goTo(s.hasPrevPage?s.activePageIndex-1:s.pages.length-1,{behavior:s.scrollBehavior}))},u=e=>{!s.loop&&!s.hasNextPage||(e.preventDefault(),s.goTo(s.hasNextPage?s.activePageIndex+1:0,{behavior:s.scrollBehavior}))},f=e=>{e.key===`ArrowLeft`&&l(e),e.key===`ArrowRight`&&u(e)},p={scrollSnapType:c[s.snapType],scrollPaddingInline:`var(--scrolling-list-px)`,"--scrolling-list-px":`${s.scrollPadding}px`,"--scrolling-list-gap":`${s.gap}px`,...s.withFade&&{maskImage:`linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1) 44px, rgba(0, 0, 0, 1) calc(100% - 44px), rgba(0, 0, 0, 0))`,maskSize:`calc(100% + ${s.overflow.left?`0px`:`44px`} + ${s.overflow.right?`0px`:`44px`}) 100%`,maskPosition:`${s.overflow.left?`0px`:`-44px`} 0`}};return(0,o.jsx)(`div`,{"data-spark-component":`scrolling-list-items`,id:`scrolling-list-items`,role:`list`,className:(0,i.cx)(`relative transition-all duration-300`,`u-no-scrollbar overflow-x-auto scroll-smooth`,`w-full gap-(--scrolling-list-gap) default:flex default:flex-row`,`focus-visible:u-outline`,n),ref:g(s.scrollAreaRef,s.scrollRef,t),style:p,onKeyDown:f,...r,children:a.Children.map(e,(e,t)=>(0,a.isValidElement)(e)?(0,a.cloneElement)(e,{index:t}):e)})};_.displayName=`ScrollingList.Items`;var v=({"aria-label":e,onClick:n,...s})=>{let l=(0,a.useContext)(d),u=e=>{l.hasNextPage?l.next({behavior:l.scrollBehavior}):l.goTo(0,{behavior:l.scrollBehavior}),n?.(e)},f=!(l.overflow.left||l.overflow.right)||!l.loop&&!l.overflow.right;return(0,o.jsx)(r.t,{"data-spark-component":`scrolling-list-next-button`,size:`sm`,intent:`surface`,design:`filled`,className:(0,i.cx)(`pointer-events-auto opacity-(--scrolling-list-controls-opacity) shadow-sm disabled:invisible`,`group-hover/scrolling-list:opacity-none focus-visible:opacity-none`),onClick:u,disabled:f,"aria-label":e,"aria-controls":`scrolling-list-items`,...s,children:(0,o.jsx)(t.t,{children:(0,o.jsx)(c.ArrowVerticalRight,{})})})};v.displayName=`ScrollingList.NextButton`;var y=({"aria-label":e,onClick:n,...s})=>{let c=(0,a.useContext)(d),u=e=>{c.activePageIndex===0&&(c.scrollAreaRef.current?.scrollLeft||0)>0?c.goTo(0,{behavior:c.scrollBehavior}):c.hasPrevPage?c.prev({behavior:c.scrollBehavior}):c.goTo(c.pages.length-1,{behavior:c.scrollBehavior}),n?.(e)},f=!(c.overflow.left||c.overflow.right)||!c.loop&&!c.overflow.left;return(0,o.jsx)(r.t,{"data-spark-component":`scrolling-list-prev-button`,size:`sm`,intent:`surface`,design:`filled`,className:(0,i.cx)(`pointer-events-auto opacity-(--scrolling-list-controls-opacity) shadow-sm disabled:invisible`,`group-hover/scrolling-list:opacity-none focus-visible:opacity-none`),onClick:u,disabled:f,"aria-label":e,"aria-controls":`scrolling-list-items`,...s,children:(0,o.jsx)(t.t,{children:(0,o.jsx)(l.ArrowVerticalLeft,{})})})};y.displayName=`ScrollingList.PrevButton`;var b=({children:e,...t})=>{let r=(0,a.useContext)(d);return(0,o.jsx)(n.t,{type:`button`,design:`tinted`,intent:`surface`,tabIndex:0,className:(0,i.cx)(`z-raised absolute top-1/2 left-0 -translate-y-1/2`,`not-focus-visible:pointer-events-none not-focus-visible:size-0 not-focus-visible:opacity-0`),onClick:r.skipKeyboardNavigation,...t,children:e})};b.displayName=`ScrollingList.SkipButton`;var x=Object.assign(f,{Controls:p,NextButton:v,PrevButton:y,Item:h,Items:_,SkipButton:b});x.displayName=`ScrollingList`,exports.ScrollingList=x;
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/scrolling-list/ScrollingList.tsx","../../src/scrolling-list/ScrollingListControls.tsx","../../src/scrolling-list/useFocusWithinScroll.tsx","../../src/scrolling-list/ScrollingListItem.tsx","../../src/scrolling-list/ScrollingListItems.tsx","../../src/scrolling-list/ScrollingListNextButton.tsx","../../src/scrolling-list/ScrollingListPrevButton.tsx","../../src/scrolling-list/ScrollingListSkipButton.tsx","../../src/scrolling-list/index.ts"],"sourcesContent":["import { ScrollOverflow, useScrollOverflow } from '@spark-ui/hooks/use-scroll-overflow'\nimport { cx } from 'class-variance-authority'\nimport {\n ComponentPropsWithRef,\n createContext,\n ReactNode,\n RefObject,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n} from 'react'\nimport { SnapCarouselResult, useSnapCarousel } from 'react-snap-carousel'\n\ntype SnapType = 'mandatory' | 'proximity' | 'none'\ntype ScrollBehavior = 'smooth' | 'instant'\ntype SnapStop = 'normal' | 'always'\n\ninterface Props extends ComponentPropsWithRef<'div'> {\n /**\n * CSS scroll snap behavior.\n * - `mandatory` to force snapping on each \"page\".\n * - `proximity` to force snapping only when scroll position is near the edge of a \"page\". Behavior can change depending on each browser.\n * - `none` to disabled scroll snapping.\n */\n snapType?: SnapType\n /**\n * Defines whether or not the scroll container is allowed to \"pass over\" possible snap positions.\n */\n snapStop?: SnapStop\n scrollBehavior?: ScrollBehavior\n /**\n * Add a fade effect to indicate content overflow.\n */\n withFade?: boolean\n children?: ReactNode\n /**\n * When `true`, allow previous and next buttons to be used when reaching the edges of the list.\n */\n loop?: boolean\n /**\n * Space (in pixels) between items.\n */\n gap?: number\n /**\n * Offset (in pixels) of the left of the optimal viewing region of the list.\n */\n scrollPadding?: number\n className?: string\n}\n\ninterface ScrollingListContextState extends SnapCarouselResult {\n snapType: SnapType\n snapStop: SnapStop\n scrollBehavior: ScrollBehavior\n visibleItemsRange: readonly [number, number]\n loop: boolean\n gap: number\n withFade: boolean\n scrollPadding: number\n scrollAreaRef: RefObject<HTMLDivElement | null>\n overflow: ScrollOverflow\n skipKeyboardNavigation: () => void\n}\n\nexport const ScrollingListContext = createContext<ScrollingListContextState>(\n null as unknown as ScrollingListContextState\n)\n\nexport const ScrollingList = ({\n snapType = 'none',\n snapStop = 'normal',\n scrollBehavior = 'smooth',\n loop = false,\n gap = 16,\n withFade = false,\n scrollPadding = 0,\n children,\n className,\n ...rest\n}: Props) => {\n const scrollAreaRef = useRef<HTMLDivElement>(null)\n const skipAnchorRef = useRef<HTMLButtonElement>(null)\n\n const snapCarouselAPI = useSnapCarousel()\n\n const { overflow, refresh: refreshOverflow } = useScrollOverflow(scrollAreaRef, {\n precisionTreshold: 1,\n })\n\n const { activePageIndex, pages, refresh } = snapCarouselAPI\n\n const visibleItems = pages[activePageIndex] as number[]\n\n const visibleItemsRange = visibleItems\n ? ([visibleItems[0]! + 1, visibleItems[visibleItems.length - 1]! + 1] as const)\n : ([0, 0] as const)\n\n // Force refresh of the carousel API when children change\n const forceRefresh = useCallback(() => {\n if (refresh && scrollAreaRef.current) {\n // Small delay to ensure DOM is updated\n setTimeout(() => {\n refresh()\n }, 0)\n }\n }, [refresh])\n\n useEffect(() => {\n forceRefresh()\n }, [children, forceRefresh])\n\n useLayoutEffect(() => {\n if (scrollAreaRef.current) {\n // Use requestAnimationFrame to ensure proper timing with the render cycle\n // This prevents race conditions that occur when the console is closed\n requestAnimationFrame(() => {\n refreshOverflow()\n })\n }\n }, [children, refreshOverflow])\n\n const skipKeyboardNavigation = () => {\n skipAnchorRef.current?.focus()\n }\n\n const ctxValue: ScrollingListContextState = {\n ...snapCarouselAPI,\n snapType,\n snapStop,\n skipKeyboardNavigation,\n scrollBehavior,\n visibleItemsRange,\n loop,\n gap,\n withFade,\n scrollPadding,\n scrollAreaRef,\n overflow,\n }\n\n return (\n <ScrollingListContext value={ctxValue}>\n <div\n data-spark-component=\"scrolling-list\"\n className={cx(\n 'gap-lg group/scrolling-list relative flex flex-col default:w-full',\n className\n )}\n {...rest}\n >\n {children}\n </div>\n <span ref={skipAnchorRef} className=\"size-0 overflow-hidden\" tabIndex={-1} />\n </ScrollingListContext>\n )\n}\n\nScrollingList.displayName = 'ScrollingList'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, CSSProperties, ReactNode } from 'react'\n\ninterface ScrollingListControls extends ComponentPropsWithoutRef<'div'> {\n /**\n * Visibility behavior of the control buttons:\n * - `always`: buttons are always visible.\n * - `hover`: buttons only appear on hover.\n *\n * a11y: `hover` is dangerous for accessibility as it disabled controls for touch screen users.\n * When using it, you must provide an alternative control outside of the list to replace them.\n */\n visibility?: 'hover' | 'always'\n children: ReactNode\n}\n\n/** Container for navigation controls (previous/next buttons) of the scrolling list. Renders a <div> element. */\nexport const ScrollingListControls = ({\n children,\n visibility = 'always',\n className,\n ...rest\n}: ScrollingListControls) => {\n return (\n <div\n data-spark-component=\"scrolling-list-controls\"\n className={cx(\n 'default:px-md pointer-events-none absolute inset-0 flex flex-row items-center justify-between overflow-hidden',\n className\n )}\n style={\n {\n '--scrolling-list-controls-opacity': visibility === 'hover' ? '0' : '1',\n } as CSSProperties\n }\n data-orientation=\"horizontal\"\n {...rest}\n >\n {children}\n </div>\n )\n}\n\nScrollingListControls.displayName = 'ScrollingList.Controls'\n","import { RefObject, useEffect, useState } from 'react'\n\nexport function useFocusWithinScroll<T extends HTMLElement | null>(\n ref: RefObject<T>, // The container to detect focus within\n scrollRef: RefObject<HTMLDivElement | null> // The scrollable container\n) {\n const [isFocusWithin, setIsFocusWithin] = useState(false)\n\n useEffect(() => {\n const handleFocusIn = (event: FocusEvent) => {\n setIsFocusWithin(true)\n\n const focusedElement = event.target as HTMLElement\n const scrollContainer = scrollRef.current\n\n if (focusedElement && scrollContainer) {\n const focusRect = focusedElement.getBoundingClientRect()\n const scrollRect = scrollContainer.getBoundingClientRect()\n\n // Check if the focused element is fully visible inside the scroll container\n const isFullyVisible =\n focusRect.left >= scrollRect.left &&\n focusRect.right <= scrollRect.right &&\n focusRect.top >= scrollRect.top &&\n focusRect.bottom <= scrollRect.bottom\n\n if (!isFullyVisible) {\n focusedElement.scrollIntoView({ behavior: 'smooth', inline: 'center', block: 'nearest' })\n }\n }\n }\n\n const handleFocusOut = (event: FocusEvent) => {\n if (ref.current && !ref.current.contains(event.relatedTarget as Node)) {\n setIsFocusWithin(false)\n }\n }\n\n const node = ref.current\n if (node) {\n node.addEventListener('focusin', handleFocusIn)\n node.addEventListener('focusout', handleFocusOut)\n }\n\n return () => {\n if (node) {\n node.removeEventListener('focusin', handleFocusIn)\n node.removeEventListener('focusout', handleFocusOut)\n }\n }\n }, [ref, scrollRef])\n\n return isFocusWithin\n}\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, ReactNode, useContext, useRef } from 'react'\n\nimport { Slot } from '../slot'\nimport { ScrollingListContext } from './ScrollingList'\nimport { useFocusWithinScroll } from './useFocusWithinScroll'\n\nexport interface ScrollingListItemProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n children?: ReactNode\n /**\n * DO NOT USE. This prop is automatically managed by the parent ScrollingList.ListItems\n */\n index?: number\n className?: string\n}\n\n/** A single item in the scrolling list. Renders a <div> element. */\nexport const ScrollingListItem = ({\n asChild = false,\n children,\n index = 0,\n className = '',\n ...rest\n}: ScrollingListItemProps) => {\n const ctx = useContext(ScrollingListContext)\n const itemRef = useRef<HTMLDivElement>(null)\n\n const isSnapPoint = ctx.snapPointIndexes.has(index)\n\n useFocusWithinScroll(itemRef, ctx.scrollAreaRef)\n\n const Component = asChild ? Slot : 'div'\n\n return (\n <Component\n data-spark-component=\"scrolling-list-item\"\n role=\"listitem\"\n ref={itemRef}\n className={cx(\n 'default:w-auto default:shrink-0',\n {\n 'snap-start': isSnapPoint,\n 'snap-normal': isSnapPoint && ctx.snapStop === 'normal',\n 'snap-always': isSnapPoint && ctx.snapStop === 'always',\n },\n className\n )}\n {...rest}\n >\n {children}\n </Component>\n )\n}\n\nScrollingListItem.displayName = 'ScrollingList.Item'\n","import { cx } from 'class-variance-authority'\nimport {\n Children,\n cloneElement,\n ComponentPropsWithRef,\n CSSProperties,\n isValidElement,\n KeyboardEvent,\n ReactNode,\n Ref,\n RefObject,\n useContext,\n} from 'react'\n\nimport { ScrollingListContext } from './ScrollingList'\nimport { ScrollingListItemProps } from './ScrollingListItem'\n\ninterface Props extends ComponentPropsWithRef<'div'> {\n children?: ReactNode\n className?: string\n}\n\nexport function mergeRefs<T>(...refs: (Ref<T> | undefined | null)[]): Ref<T> {\n return (value: T | null) => {\n refs.forEach(ref => {\n if (typeof ref === 'function') {\n ref(value)\n } else if (ref && typeof ref === 'object' && 'current' in ref) {\n ;(ref as RefObject<T | null>).current = value\n }\n })\n }\n}\n\n/** The scrollable container for the list items. Renders a <div> element. */\nexport const ScrollingListItems = ({ children, ref, className = '', ...rest }: Props) => {\n const ctx = useContext(ScrollingListContext)\n\n const snapConfig = {\n mandatory: 'x mandatory',\n proximity: 'x proximity',\n none: 'none',\n }\n\n const handleLeftArrow = (event: KeyboardEvent<HTMLDivElement>) => {\n if (!ctx.loop && !ctx.hasPrevPage) return\n\n event.preventDefault()\n ctx.goTo(ctx.hasPrevPage ? ctx.activePageIndex - 1 : ctx.pages.length - 1, {\n behavior: ctx.scrollBehavior,\n })\n }\n\n const handleRightArrow = (event: KeyboardEvent<HTMLDivElement>) => {\n if (!ctx.loop && !ctx.hasNextPage) return\n\n event.preventDefault()\n ctx.goTo(ctx.hasNextPage ? ctx.activePageIndex + 1 : 0, { behavior: ctx.scrollBehavior })\n }\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'ArrowLeft') {\n handleLeftArrow(event)\n }\n\n if (event.key === 'ArrowRight') {\n handleRightArrow(event)\n }\n }\n\n interface CustomCSSProperties extends CSSProperties {\n '--scrolling-list-gap'?: string\n '--scrolling-list-px'?: string\n }\n\n const inlineStyles: CustomCSSProperties = {\n scrollSnapType: snapConfig[ctx.snapType],\n scrollPaddingInline: 'var(--scrolling-list-px)',\n '--scrolling-list-px': `${ctx.scrollPadding}px`,\n '--scrolling-list-gap': `${ctx.gap}px`,\n ...(ctx.withFade && {\n maskImage:\n 'linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1) 44px, rgba(0, 0, 0, 1) calc(100% - 44px), rgba(0, 0, 0, 0))',\n maskSize: `calc(100% + ${ctx.overflow.left ? '0px' : '44px'} + ${ctx.overflow.right ? '0px' : '44px'}) 100%`,\n maskPosition: `${ctx.overflow.left ? '0px' : '-44px'} 0`,\n }),\n }\n\n return (\n <div\n data-spark-component=\"scrolling-list-items\"\n id=\"scrolling-list-items\"\n role=\"list\"\n className={cx(\n 'relative transition-all duration-300',\n 'u-no-scrollbar overflow-x-auto scroll-smooth',\n 'w-full gap-(--scrolling-list-gap) default:flex default:flex-row',\n 'focus-visible:u-outline',\n className\n )}\n ref={mergeRefs<HTMLDivElement>(ctx.scrollAreaRef, ctx.scrollRef, ref)}\n style={inlineStyles}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {Children.map(children, (child, index) =>\n isValidElement<ScrollingListItemProps>(child) ? cloneElement(child, { index }) : child\n )}\n </div>\n )\n}\n\nScrollingListItems.displayName = 'ScrollingList.Items'\n","import { ArrowVerticalRight } from '@spark-ui/icons/ArrowVerticalRight'\nimport { cx } from 'class-variance-authority'\nimport { useContext } from 'react'\n\nimport { Icon } from '../icon'\nimport { IconButton, IconButtonProps } from '../icon-button'\nimport { ScrollingListContext } from './ScrollingList'\n\n/** A button to scroll to the next page of items. Renders a <button> element. */\nexport const ScrollingListNextButton = ({ 'aria-label': ariaLabel, ...rest }: IconButtonProps) => {\n const ctx = useContext(ScrollingListContext)\n\n const handleNextPage = () => {\n if (ctx.hasNextPage) {\n ctx.next({ behavior: ctx.scrollBehavior })\n } else {\n ctx.goTo(0, { behavior: ctx.scrollBehavior })\n }\n }\n\n const listHasOverflow = ctx.overflow.left || ctx.overflow.right\n const isDisabled = !listHasOverflow || (!ctx.loop && !ctx.overflow.right)\n\n return (\n <IconButton\n data-spark-component=\"scrolling-list-next-button\"\n size=\"sm\"\n intent=\"surface\"\n design=\"filled\"\n className={cx(\n 'pointer-events-auto opacity-(--scrolling-list-controls-opacity) shadow-sm disabled:invisible',\n 'group-hover/scrolling-list:opacity-none focus-visible:opacity-none'\n )}\n onClick={handleNextPage}\n disabled={isDisabled}\n aria-label={ariaLabel}\n aria-controls=\"scrolling-list-items\"\n {...rest}\n >\n <Icon>\n <ArrowVerticalRight />\n </Icon>\n </IconButton>\n )\n}\n\nScrollingListNextButton.displayName = 'ScrollingList.NextButton'\n","import { ArrowVerticalLeft } from '@spark-ui/icons/ArrowVerticalLeft'\nimport { cx } from 'class-variance-authority'\nimport { useContext } from 'react'\n\nimport { Icon } from '../icon'\nimport { IconButton, IconButtonProps } from '../icon-button'\nimport { ScrollingListContext } from './ScrollingList'\n\n/** A button to scroll to the previous page of items. Renders a <button> element. */\nexport const ScrollingListPrevButton = ({\n 'aria-label': ariaLabel,\n\n ...rest\n}: IconButtonProps) => {\n const ctx = useContext(ScrollingListContext)\n\n const handlePrevPage = () => {\n const shouldSnapFirstPage =\n ctx.activePageIndex === 0 && (ctx.scrollAreaRef.current?.scrollLeft || 0) > 0\n\n if (shouldSnapFirstPage) {\n ctx.goTo(0, { behavior: ctx.scrollBehavior })\n } else if (ctx.hasPrevPage) {\n ctx.prev({ behavior: ctx.scrollBehavior })\n } else {\n ctx.goTo(ctx.pages.length - 1, { behavior: ctx.scrollBehavior })\n }\n }\n\n const listHasOverflow = ctx.overflow.left || ctx.overflow.right\n const isDisabled = !listHasOverflow || (!ctx.loop && !ctx.overflow.left)\n\n return (\n <IconButton\n data-spark-component=\"scrolling-list-prev-button\"\n size=\"sm\"\n intent=\"surface\"\n design=\"filled\"\n className={cx(\n 'pointer-events-auto opacity-(--scrolling-list-controls-opacity) shadow-sm disabled:invisible',\n 'group-hover/scrolling-list:opacity-none focus-visible:opacity-none'\n )}\n onClick={handlePrevPage}\n disabled={isDisabled}\n aria-label={ariaLabel}\n aria-controls=\"scrolling-list-items\"\n {...rest}\n >\n <Icon>\n <ArrowVerticalLeft />\n </Icon>\n </IconButton>\n )\n}\n\nScrollingListPrevButton.displayName = 'ScrollingList.PrevButton'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, useContext } from 'react'\n\nimport { Button } from '../button'\nimport { ScrollingListContext } from './ScrollingList'\n\ninterface Props extends ComponentPropsWithoutRef<'button'> {\n children: string\n}\n\n/** A button to skip keyboard navigation, improving accessibility. Renders a <button> element. */\nexport const ScrollingListSkipButton = ({ children, ...rest }: Props) => {\n const ctx = useContext(ScrollingListContext)\n\n return (\n <Button\n type=\"button\"\n design=\"tinted\"\n intent=\"surface\"\n tabIndex={0}\n className={cx(\n 'z-raised absolute top-1/2 left-0 -translate-y-1/2',\n 'not-focus-visible:pointer-events-none not-focus-visible:size-0 not-focus-visible:opacity-0'\n )}\n onClick={ctx.skipKeyboardNavigation}\n {...rest}\n >\n {children}\n </Button>\n )\n}\n\nScrollingListSkipButton.displayName = 'ScrollingList.SkipButton'\n","import { ScrollingList as Root } from './ScrollingList'\nimport { ScrollingListControls as Controls } from './ScrollingListControls'\nimport { ScrollingListItem as Item } from './ScrollingListItem'\nimport { ScrollingListItems as Items } from './ScrollingListItems'\nimport { ScrollingListNextButton as NextButton } from './ScrollingListNextButton'\nimport { ScrollingListPrevButton as PrevButton } from './ScrollingListPrevButton'\nimport { ScrollingListSkipButton as SkipButton } from './ScrollingListSkipButton'\n\n/**\n * A horizontal scrollable list component with optional snap points and navigation controls.\n */\nexport const ScrollingList: typeof Root & {\n Controls: typeof Controls\n NextButton: typeof NextButton\n PrevButton: typeof PrevButton\n Item: typeof Item\n Items: typeof Items\n SkipButton: typeof SkipButton\n} = Object.assign(Root, {\n Controls,\n NextButton,\n PrevButton,\n Item,\n Items,\n SkipButton,\n})\n\nScrollingList.displayName = 'ScrollingList'\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/scrolling-list/ScrollingList.tsx","../../src/scrolling-list/ScrollingListControls.tsx","../../src/scrolling-list/useFocusWithinScroll.tsx","../../src/scrolling-list/ScrollingListItem.tsx","../../src/scrolling-list/ScrollingListItems.tsx","../../src/scrolling-list/ScrollingListNextButton.tsx","../../src/scrolling-list/ScrollingListPrevButton.tsx","../../src/scrolling-list/ScrollingListSkipButton.tsx","../../src/scrolling-list/index.ts"],"sourcesContent":["import { ScrollOverflow, useScrollOverflow } from '@spark-ui/hooks/use-scroll-overflow'\nimport { cx } from 'class-variance-authority'\nimport {\n ComponentPropsWithRef,\n createContext,\n ReactNode,\n RefObject,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n} from 'react'\nimport { SnapCarouselResult, useSnapCarousel } from 'react-snap-carousel'\n\ntype SnapType = 'mandatory' | 'proximity' | 'none'\ntype ScrollBehavior = 'smooth' | 'instant'\ntype SnapStop = 'normal' | 'always'\n\ninterface Props extends ComponentPropsWithRef<'div'> {\n /**\n * CSS scroll snap behavior.\n * - `mandatory` to force snapping on each \"page\".\n * - `proximity` to force snapping only when scroll position is near the edge of a \"page\". Behavior can change depending on each browser.\n * - `none` to disabled scroll snapping.\n */\n snapType?: SnapType\n /**\n * Defines whether or not the scroll container is allowed to \"pass over\" possible snap positions.\n */\n snapStop?: SnapStop\n scrollBehavior?: ScrollBehavior\n /**\n * Add a fade effect to indicate content overflow.\n */\n withFade?: boolean\n children?: ReactNode\n /**\n * When `true`, allow previous and next buttons to be used when reaching the edges of the list.\n */\n loop?: boolean\n /**\n * Space (in pixels) between items.\n */\n gap?: number\n /**\n * Offset (in pixels) of the left of the optimal viewing region of the list.\n */\n scrollPadding?: number\n className?: string\n}\n\ninterface ScrollingListContextState extends SnapCarouselResult {\n snapType: SnapType\n snapStop: SnapStop\n scrollBehavior: ScrollBehavior\n visibleItemsRange: readonly [number, number]\n loop: boolean\n gap: number\n withFade: boolean\n scrollPadding: number\n scrollAreaRef: RefObject<HTMLDivElement | null>\n overflow: ScrollOverflow\n skipKeyboardNavigation: () => void\n}\n\nexport const ScrollingListContext = createContext<ScrollingListContextState>(\n null as unknown as ScrollingListContextState\n)\n\nexport const ScrollingList = ({\n snapType = 'none',\n snapStop = 'normal',\n scrollBehavior = 'smooth',\n loop = false,\n gap = 16,\n withFade = false,\n scrollPadding = 0,\n children,\n className,\n ...rest\n}: Props) => {\n const scrollAreaRef = useRef<HTMLDivElement>(null)\n const skipAnchorRef = useRef<HTMLButtonElement>(null)\n\n const snapCarouselAPI = useSnapCarousel()\n\n const { overflow, refresh: refreshOverflow } = useScrollOverflow(scrollAreaRef, {\n precisionTreshold: 1,\n })\n\n const { activePageIndex, pages, refresh } = snapCarouselAPI\n\n const visibleItems = pages[activePageIndex] as number[]\n\n const visibleItemsRange = visibleItems\n ? ([visibleItems[0]! + 1, visibleItems[visibleItems.length - 1]! + 1] as const)\n : ([0, 0] as const)\n\n // Force refresh of the carousel API when children change\n const forceRefresh = useCallback(() => {\n if (refresh && scrollAreaRef.current) {\n // Small delay to ensure DOM is updated\n setTimeout(() => {\n refresh()\n }, 0)\n }\n }, [refresh])\n\n useEffect(() => {\n forceRefresh()\n }, [children, forceRefresh])\n\n useLayoutEffect(() => {\n if (scrollAreaRef.current) {\n // Use requestAnimationFrame to ensure proper timing with the render cycle\n // This prevents race conditions that occur when the console is closed\n requestAnimationFrame(() => {\n refreshOverflow()\n })\n }\n }, [children, refreshOverflow])\n\n const skipKeyboardNavigation = () => {\n skipAnchorRef.current?.focus()\n }\n\n const ctxValue: ScrollingListContextState = {\n ...snapCarouselAPI,\n snapType,\n snapStop,\n skipKeyboardNavigation,\n scrollBehavior,\n visibleItemsRange,\n loop,\n gap,\n withFade,\n scrollPadding,\n scrollAreaRef,\n overflow,\n }\n\n return (\n <ScrollingListContext value={ctxValue}>\n <div\n data-spark-component=\"scrolling-list\"\n className={cx(\n 'gap-lg group/scrolling-list relative flex flex-col default:w-full',\n className\n )}\n {...rest}\n >\n {children}\n </div>\n <span ref={skipAnchorRef} className=\"size-0 overflow-hidden\" tabIndex={-1} />\n </ScrollingListContext>\n )\n}\n\nScrollingList.displayName = 'ScrollingList'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, CSSProperties, ReactNode } from 'react'\n\ninterface ScrollingListControls extends ComponentPropsWithoutRef<'div'> {\n /**\n * Visibility behavior of the control buttons:\n * - `always`: buttons are always visible.\n * - `hover`: buttons only appear on hover.\n *\n * a11y: `hover` is dangerous for accessibility as it disabled controls for touch screen users.\n * When using it, you must provide an alternative control outside of the list to replace them.\n */\n visibility?: 'hover' | 'always'\n children: ReactNode\n}\n\n/** Container for navigation controls (previous/next buttons) of the scrolling list. Renders a <div> element. */\nexport const ScrollingListControls = ({\n children,\n visibility = 'always',\n className,\n ...rest\n}: ScrollingListControls) => {\n return (\n <div\n data-spark-component=\"scrolling-list-controls\"\n className={cx(\n 'default:px-md pointer-events-none absolute inset-0 flex flex-row items-center justify-between overflow-hidden',\n className\n )}\n style={\n {\n '--scrolling-list-controls-opacity': visibility === 'hover' ? '0' : '1',\n } as CSSProperties\n }\n data-orientation=\"horizontal\"\n {...rest}\n >\n {children}\n </div>\n )\n}\n\nScrollingListControls.displayName = 'ScrollingList.Controls'\n","import { RefObject, useEffect, useState } from 'react'\n\nexport function useFocusWithinScroll<T extends HTMLElement | null>(\n ref: RefObject<T>, // The container to detect focus within\n scrollRef: RefObject<HTMLDivElement | null> // The scrollable container\n) {\n const [isFocusWithin, setIsFocusWithin] = useState(false)\n\n useEffect(() => {\n const handleFocusIn = (event: FocusEvent) => {\n setIsFocusWithin(true)\n\n const focusedElement = event.target as HTMLElement\n const scrollContainer = scrollRef.current\n\n if (focusedElement && scrollContainer) {\n const focusRect = focusedElement.getBoundingClientRect()\n const scrollRect = scrollContainer.getBoundingClientRect()\n\n // Check if the focused element is fully visible inside the scroll container\n const isFullyVisible =\n focusRect.left >= scrollRect.left &&\n focusRect.right <= scrollRect.right &&\n focusRect.top >= scrollRect.top &&\n focusRect.bottom <= scrollRect.bottom\n\n if (!isFullyVisible) {\n focusedElement.scrollIntoView({ behavior: 'smooth', inline: 'center', block: 'nearest' })\n }\n }\n }\n\n const handleFocusOut = (event: FocusEvent) => {\n if (ref.current && !ref.current.contains(event.relatedTarget as Node)) {\n setIsFocusWithin(false)\n }\n }\n\n const node = ref.current\n if (node) {\n node.addEventListener('focusin', handleFocusIn)\n node.addEventListener('focusout', handleFocusOut)\n }\n\n return () => {\n if (node) {\n node.removeEventListener('focusin', handleFocusIn)\n node.removeEventListener('focusout', handleFocusOut)\n }\n }\n }, [ref, scrollRef])\n\n return isFocusWithin\n}\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, ReactNode, useContext, useRef } from 'react'\n\nimport { Slot } from '../slot'\nimport { ScrollingListContext } from './ScrollingList'\nimport { useFocusWithinScroll } from './useFocusWithinScroll'\n\nexport interface ScrollingListItemProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n children?: ReactNode\n /**\n * DO NOT USE. This prop is automatically managed by the parent ScrollingList.ListItems\n */\n index?: number\n className?: string\n}\n\n/** A single item in the scrolling list. Renders a <div> element. */\nexport const ScrollingListItem = ({\n asChild = false,\n children,\n index = 0,\n className = '',\n ...rest\n}: ScrollingListItemProps) => {\n const ctx = useContext(ScrollingListContext)\n const itemRef = useRef<HTMLDivElement>(null)\n\n const isSnapPoint = ctx.snapPointIndexes.has(index)\n\n useFocusWithinScroll(itemRef, ctx.scrollAreaRef)\n\n const Component = asChild ? Slot : 'div'\n\n return (\n <Component\n data-spark-component=\"scrolling-list-item\"\n role=\"listitem\"\n ref={itemRef}\n className={cx(\n 'default:w-auto default:shrink-0',\n {\n 'snap-start': isSnapPoint,\n 'snap-normal': isSnapPoint && ctx.snapStop === 'normal',\n 'snap-always': isSnapPoint && ctx.snapStop === 'always',\n },\n className\n )}\n {...rest}\n >\n {children}\n </Component>\n )\n}\n\nScrollingListItem.displayName = 'ScrollingList.Item'\n","import { cx } from 'class-variance-authority'\nimport {\n Children,\n cloneElement,\n ComponentPropsWithRef,\n CSSProperties,\n isValidElement,\n KeyboardEvent,\n ReactNode,\n Ref,\n RefObject,\n useContext,\n} from 'react'\n\nimport { ScrollingListContext } from './ScrollingList'\nimport { ScrollingListItemProps } from './ScrollingListItem'\n\ninterface Props extends ComponentPropsWithRef<'div'> {\n children?: ReactNode\n className?: string\n}\n\nexport function mergeRefs<T>(...refs: (Ref<T> | undefined | null)[]): Ref<T> {\n return (value: T | null) => {\n refs.forEach(ref => {\n if (typeof ref === 'function') {\n ref(value)\n } else if (ref && typeof ref === 'object' && 'current' in ref) {\n ;(ref as RefObject<T | null>).current = value\n }\n })\n }\n}\n\n/** The scrollable container for the list items. Renders a <div> element. */\nexport const ScrollingListItems = ({ children, ref, className = '', ...rest }: Props) => {\n const ctx = useContext(ScrollingListContext)\n\n const snapConfig = {\n mandatory: 'x mandatory',\n proximity: 'x proximity',\n none: 'none',\n }\n\n const handleLeftArrow = (event: KeyboardEvent<HTMLDivElement>) => {\n if (!ctx.loop && !ctx.hasPrevPage) return\n\n event.preventDefault()\n ctx.goTo(ctx.hasPrevPage ? ctx.activePageIndex - 1 : ctx.pages.length - 1, {\n behavior: ctx.scrollBehavior,\n })\n }\n\n const handleRightArrow = (event: KeyboardEvent<HTMLDivElement>) => {\n if (!ctx.loop && !ctx.hasNextPage) return\n\n event.preventDefault()\n ctx.goTo(ctx.hasNextPage ? ctx.activePageIndex + 1 : 0, { behavior: ctx.scrollBehavior })\n }\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'ArrowLeft') {\n handleLeftArrow(event)\n }\n\n if (event.key === 'ArrowRight') {\n handleRightArrow(event)\n }\n }\n\n interface CustomCSSProperties extends CSSProperties {\n '--scrolling-list-gap'?: string\n '--scrolling-list-px'?: string\n }\n\n const inlineStyles: CustomCSSProperties = {\n scrollSnapType: snapConfig[ctx.snapType],\n scrollPaddingInline: 'var(--scrolling-list-px)',\n '--scrolling-list-px': `${ctx.scrollPadding}px`,\n '--scrolling-list-gap': `${ctx.gap}px`,\n ...(ctx.withFade && {\n maskImage:\n 'linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1) 44px, rgba(0, 0, 0, 1) calc(100% - 44px), rgba(0, 0, 0, 0))',\n maskSize: `calc(100% + ${ctx.overflow.left ? '0px' : '44px'} + ${ctx.overflow.right ? '0px' : '44px'}) 100%`,\n maskPosition: `${ctx.overflow.left ? '0px' : '-44px'} 0`,\n }),\n }\n\n return (\n <div\n data-spark-component=\"scrolling-list-items\"\n id=\"scrolling-list-items\"\n role=\"list\"\n className={cx(\n 'relative transition-all duration-300',\n 'u-no-scrollbar overflow-x-auto scroll-smooth',\n 'w-full gap-(--scrolling-list-gap) default:flex default:flex-row',\n 'focus-visible:u-outline',\n className\n )}\n ref={mergeRefs<HTMLDivElement>(ctx.scrollAreaRef, ctx.scrollRef, ref)}\n style={inlineStyles}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {Children.map(children, (child, index) =>\n isValidElement<ScrollingListItemProps>(child) ? cloneElement(child, { index }) : child\n )}\n </div>\n )\n}\n\nScrollingListItems.displayName = 'ScrollingList.Items'\n","import { ArrowVerticalRight } from '@spark-ui/icons/ArrowVerticalRight'\nimport { cx } from 'class-variance-authority'\nimport { useContext, MouseEvent } from 'react'\n\nimport { Icon } from '../icon'\nimport { IconButton, IconButtonProps } from '../icon-button'\nimport { ScrollingListContext } from './ScrollingList'\n\n/** A button to scroll to the next page of items. Renders a <button> element. */\nexport const ScrollingListNextButton = ({\n 'aria-label': ariaLabel,\n onClick,\n ...rest\n}: IconButtonProps) => {\n const ctx = useContext(ScrollingListContext)\n\n const handleNextPage = (e: MouseEvent<HTMLButtonElement>) => {\n if (ctx.hasNextPage) {\n ctx.next({ behavior: ctx.scrollBehavior })\n } else {\n ctx.goTo(0, { behavior: ctx.scrollBehavior })\n }\n\n onClick?.(e)\n }\n\n const listHasOverflow = ctx.overflow.left || ctx.overflow.right\n const isDisabled = !listHasOverflow || (!ctx.loop && !ctx.overflow.right)\n\n return (\n <IconButton\n data-spark-component=\"scrolling-list-next-button\"\n size=\"sm\"\n intent=\"surface\"\n design=\"filled\"\n className={cx(\n 'pointer-events-auto opacity-(--scrolling-list-controls-opacity) shadow-sm disabled:invisible',\n 'group-hover/scrolling-list:opacity-none focus-visible:opacity-none'\n )}\n onClick={handleNextPage}\n disabled={isDisabled}\n aria-label={ariaLabel}\n aria-controls=\"scrolling-list-items\"\n {...rest}\n >\n <Icon>\n <ArrowVerticalRight />\n </Icon>\n </IconButton>\n )\n}\n\nScrollingListNextButton.displayName = 'ScrollingList.NextButton'\n","import { ArrowVerticalLeft } from '@spark-ui/icons/ArrowVerticalLeft'\nimport { cx } from 'class-variance-authority'\nimport { useContext, MouseEvent } from 'react'\n\nimport { Icon } from '../icon'\nimport { IconButton, IconButtonProps } from '../icon-button'\nimport { ScrollingListContext } from './ScrollingList'\n\n/** A button to scroll to the previous page of items. Renders a <button> element. */\nexport const ScrollingListPrevButton = ({\n 'aria-label': ariaLabel,\n onClick,\n ...rest\n}: IconButtonProps) => {\n const ctx = useContext(ScrollingListContext)\n\n const handlePrevPage = (e: MouseEvent<HTMLButtonElement>) => {\n const shouldSnapFirstPage =\n ctx.activePageIndex === 0 && (ctx.scrollAreaRef.current?.scrollLeft || 0) > 0\n\n if (shouldSnapFirstPage) {\n ctx.goTo(0, { behavior: ctx.scrollBehavior })\n } else if (ctx.hasPrevPage) {\n ctx.prev({ behavior: ctx.scrollBehavior })\n } else {\n ctx.goTo(ctx.pages.length - 1, { behavior: ctx.scrollBehavior })\n }\n\n onClick?.(e)\n }\n\n const listHasOverflow = ctx.overflow.left || ctx.overflow.right\n const isDisabled = !listHasOverflow || (!ctx.loop && !ctx.overflow.left)\n\n return (\n <IconButton\n data-spark-component=\"scrolling-list-prev-button\"\n size=\"sm\"\n intent=\"surface\"\n design=\"filled\"\n className={cx(\n 'pointer-events-auto opacity-(--scrolling-list-controls-opacity) shadow-sm disabled:invisible',\n 'group-hover/scrolling-list:opacity-none focus-visible:opacity-none'\n )}\n onClick={handlePrevPage}\n disabled={isDisabled}\n aria-label={ariaLabel}\n aria-controls=\"scrolling-list-items\"\n {...rest}\n >\n <Icon>\n <ArrowVerticalLeft />\n </Icon>\n </IconButton>\n )\n}\n\nScrollingListPrevButton.displayName = 'ScrollingList.PrevButton'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, useContext } from 'react'\n\nimport { Button } from '../button'\nimport { ScrollingListContext } from './ScrollingList'\n\ninterface Props extends ComponentPropsWithoutRef<'button'> {\n children: string\n}\n\n/** A button to skip keyboard navigation, improving accessibility. Renders a <button> element. */\nexport const ScrollingListSkipButton = ({ children, ...rest }: Props) => {\n const ctx = useContext(ScrollingListContext)\n\n return (\n <Button\n type=\"button\"\n design=\"tinted\"\n intent=\"surface\"\n tabIndex={0}\n className={cx(\n 'z-raised absolute top-1/2 left-0 -translate-y-1/2',\n 'not-focus-visible:pointer-events-none not-focus-visible:size-0 not-focus-visible:opacity-0'\n )}\n onClick={ctx.skipKeyboardNavigation}\n {...rest}\n >\n {children}\n </Button>\n )\n}\n\nScrollingListSkipButton.displayName = 'ScrollingList.SkipButton'\n","import { ScrollingList as Root } from './ScrollingList'\nimport { ScrollingListControls as Controls } from './ScrollingListControls'\nimport { ScrollingListItem as Item } from './ScrollingListItem'\nimport { ScrollingListItems as Items } from './ScrollingListItems'\nimport { ScrollingListNextButton as NextButton } from './ScrollingListNextButton'\nimport { ScrollingListPrevButton as PrevButton } from './ScrollingListPrevButton'\nimport { ScrollingListSkipButton as SkipButton } from './ScrollingListSkipButton'\n\n/**\n * A horizontal scrollable list component with optional snap points and navigation controls.\n */\nexport const ScrollingList: typeof Root & {\n Controls: typeof Controls\n NextButton: typeof NextButton\n PrevButton: typeof PrevButton\n Item: typeof Item\n Items: typeof Items\n SkipButton: typeof SkipButton\n} = Object.assign(Root, {\n Controls,\n NextButton,\n PrevButton,\n Item,\n Items,\n SkipButton,\n})\n\nScrollingList.displayName = 'ScrollingList'\n"],"mappings":"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"}
|
|
@@ -153,42 +153,42 @@ var D = ({ children: e, ref: t, className: n = "", ...r }) => {
|
|
|
153
153
|
D.displayName = "ScrollingList.Items";
|
|
154
154
|
//#endregion
|
|
155
155
|
//#region src/scrolling-list/ScrollingListNextButton.tsx
|
|
156
|
-
var O = ({ "aria-label": e,
|
|
157
|
-
let
|
|
158
|
-
|
|
159
|
-
},
|
|
156
|
+
var O = ({ "aria-label": e, onClick: n, ...a }) => {
|
|
157
|
+
let o = u(x), s = (e) => {
|
|
158
|
+
o.hasNextPage ? o.next({ behavior: o.scrollBehavior }) : o.goTo(0, { behavior: o.scrollBehavior }), n?.(e);
|
|
159
|
+
}, c = !(o.overflow.left || o.overflow.right) || !o.loop && !o.overflow.right;
|
|
160
160
|
return /* @__PURE__ */ h(r, {
|
|
161
161
|
"data-spark-component": "scrolling-list-next-button",
|
|
162
162
|
size: "sm",
|
|
163
163
|
intent: "surface",
|
|
164
164
|
design: "filled",
|
|
165
165
|
className: i("pointer-events-auto opacity-(--scrolling-list-controls-opacity) shadow-sm disabled:invisible", "group-hover/scrolling-list:opacity-none focus-visible:opacity-none"),
|
|
166
|
-
onClick:
|
|
167
|
-
disabled:
|
|
166
|
+
onClick: s,
|
|
167
|
+
disabled: c,
|
|
168
168
|
"aria-label": e,
|
|
169
169
|
"aria-controls": "scrolling-list-items",
|
|
170
|
-
...
|
|
170
|
+
...a,
|
|
171
171
|
children: /* @__PURE__ */ h(t, { children: /* @__PURE__ */ h(v, {}) })
|
|
172
172
|
});
|
|
173
173
|
};
|
|
174
174
|
O.displayName = "ScrollingList.NextButton";
|
|
175
175
|
//#endregion
|
|
176
176
|
//#region src/scrolling-list/ScrollingListPrevButton.tsx
|
|
177
|
-
var k = ({ "aria-label": e,
|
|
178
|
-
let
|
|
179
|
-
|
|
180
|
-
},
|
|
177
|
+
var k = ({ "aria-label": e, onClick: n, ...a }) => {
|
|
178
|
+
let o = u(x), s = (e) => {
|
|
179
|
+
o.activePageIndex === 0 && (o.scrollAreaRef.current?.scrollLeft || 0) > 0 ? o.goTo(0, { behavior: o.scrollBehavior }) : o.hasPrevPage ? o.prev({ behavior: o.scrollBehavior }) : o.goTo(o.pages.length - 1, { behavior: o.scrollBehavior }), n?.(e);
|
|
180
|
+
}, c = !(o.overflow.left || o.overflow.right) || !o.loop && !o.overflow.left;
|
|
181
181
|
return /* @__PURE__ */ h(r, {
|
|
182
182
|
"data-spark-component": "scrolling-list-prev-button",
|
|
183
183
|
size: "sm",
|
|
184
184
|
intent: "surface",
|
|
185
185
|
design: "filled",
|
|
186
186
|
className: i("pointer-events-auto opacity-(--scrolling-list-controls-opacity) shadow-sm disabled:invisible", "group-hover/scrolling-list:opacity-none focus-visible:opacity-none"),
|
|
187
|
-
onClick:
|
|
188
|
-
disabled:
|
|
187
|
+
onClick: s,
|
|
188
|
+
disabled: c,
|
|
189
189
|
"aria-label": e,
|
|
190
190
|
"aria-controls": "scrolling-list-items",
|
|
191
|
-
...
|
|
191
|
+
...a,
|
|
192
192
|
children: /* @__PURE__ */ h(t, { children: /* @__PURE__ */ h(y, {}) })
|
|
193
193
|
});
|
|
194
194
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/scrolling-list/ScrollingList.tsx","../../src/scrolling-list/ScrollingListControls.tsx","../../src/scrolling-list/useFocusWithinScroll.tsx","../../src/scrolling-list/ScrollingListItem.tsx","../../src/scrolling-list/ScrollingListItems.tsx","../../src/scrolling-list/ScrollingListNextButton.tsx","../../src/scrolling-list/ScrollingListPrevButton.tsx","../../src/scrolling-list/ScrollingListSkipButton.tsx","../../src/scrolling-list/index.ts"],"sourcesContent":["import { ScrollOverflow, useScrollOverflow } from '@spark-ui/hooks/use-scroll-overflow'\nimport { cx } from 'class-variance-authority'\nimport {\n ComponentPropsWithRef,\n createContext,\n ReactNode,\n RefObject,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n} from 'react'\nimport { SnapCarouselResult, useSnapCarousel } from 'react-snap-carousel'\n\ntype SnapType = 'mandatory' | 'proximity' | 'none'\ntype ScrollBehavior = 'smooth' | 'instant'\ntype SnapStop = 'normal' | 'always'\n\ninterface Props extends ComponentPropsWithRef<'div'> {\n /**\n * CSS scroll snap behavior.\n * - `mandatory` to force snapping on each \"page\".\n * - `proximity` to force snapping only when scroll position is near the edge of a \"page\". Behavior can change depending on each browser.\n * - `none` to disabled scroll snapping.\n */\n snapType?: SnapType\n /**\n * Defines whether or not the scroll container is allowed to \"pass over\" possible snap positions.\n */\n snapStop?: SnapStop\n scrollBehavior?: ScrollBehavior\n /**\n * Add a fade effect to indicate content overflow.\n */\n withFade?: boolean\n children?: ReactNode\n /**\n * When `true`, allow previous and next buttons to be used when reaching the edges of the list.\n */\n loop?: boolean\n /**\n * Space (in pixels) between items.\n */\n gap?: number\n /**\n * Offset (in pixels) of the left of the optimal viewing region of the list.\n */\n scrollPadding?: number\n className?: string\n}\n\ninterface ScrollingListContextState extends SnapCarouselResult {\n snapType: SnapType\n snapStop: SnapStop\n scrollBehavior: ScrollBehavior\n visibleItemsRange: readonly [number, number]\n loop: boolean\n gap: number\n withFade: boolean\n scrollPadding: number\n scrollAreaRef: RefObject<HTMLDivElement | null>\n overflow: ScrollOverflow\n skipKeyboardNavigation: () => void\n}\n\nexport const ScrollingListContext = createContext<ScrollingListContextState>(\n null as unknown as ScrollingListContextState\n)\n\nexport const ScrollingList = ({\n snapType = 'none',\n snapStop = 'normal',\n scrollBehavior = 'smooth',\n loop = false,\n gap = 16,\n withFade = false,\n scrollPadding = 0,\n children,\n className,\n ...rest\n}: Props) => {\n const scrollAreaRef = useRef<HTMLDivElement>(null)\n const skipAnchorRef = useRef<HTMLButtonElement>(null)\n\n const snapCarouselAPI = useSnapCarousel()\n\n const { overflow, refresh: refreshOverflow } = useScrollOverflow(scrollAreaRef, {\n precisionTreshold: 1,\n })\n\n const { activePageIndex, pages, refresh } = snapCarouselAPI\n\n const visibleItems = pages[activePageIndex] as number[]\n\n const visibleItemsRange = visibleItems\n ? ([visibleItems[0]! + 1, visibleItems[visibleItems.length - 1]! + 1] as const)\n : ([0, 0] as const)\n\n // Force refresh of the carousel API when children change\n const forceRefresh = useCallback(() => {\n if (refresh && scrollAreaRef.current) {\n // Small delay to ensure DOM is updated\n setTimeout(() => {\n refresh()\n }, 0)\n }\n }, [refresh])\n\n useEffect(() => {\n forceRefresh()\n }, [children, forceRefresh])\n\n useLayoutEffect(() => {\n if (scrollAreaRef.current) {\n // Use requestAnimationFrame to ensure proper timing with the render cycle\n // This prevents race conditions that occur when the console is closed\n requestAnimationFrame(() => {\n refreshOverflow()\n })\n }\n }, [children, refreshOverflow])\n\n const skipKeyboardNavigation = () => {\n skipAnchorRef.current?.focus()\n }\n\n const ctxValue: ScrollingListContextState = {\n ...snapCarouselAPI,\n snapType,\n snapStop,\n skipKeyboardNavigation,\n scrollBehavior,\n visibleItemsRange,\n loop,\n gap,\n withFade,\n scrollPadding,\n scrollAreaRef,\n overflow,\n }\n\n return (\n <ScrollingListContext value={ctxValue}>\n <div\n data-spark-component=\"scrolling-list\"\n className={cx(\n 'gap-lg group/scrolling-list relative flex flex-col default:w-full',\n className\n )}\n {...rest}\n >\n {children}\n </div>\n <span ref={skipAnchorRef} className=\"size-0 overflow-hidden\" tabIndex={-1} />\n </ScrollingListContext>\n )\n}\n\nScrollingList.displayName = 'ScrollingList'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, CSSProperties, ReactNode } from 'react'\n\ninterface ScrollingListControls extends ComponentPropsWithoutRef<'div'> {\n /**\n * Visibility behavior of the control buttons:\n * - `always`: buttons are always visible.\n * - `hover`: buttons only appear on hover.\n *\n * a11y: `hover` is dangerous for accessibility as it disabled controls for touch screen users.\n * When using it, you must provide an alternative control outside of the list to replace them.\n */\n visibility?: 'hover' | 'always'\n children: ReactNode\n}\n\n/** Container for navigation controls (previous/next buttons) of the scrolling list. Renders a <div> element. */\nexport const ScrollingListControls = ({\n children,\n visibility = 'always',\n className,\n ...rest\n}: ScrollingListControls) => {\n return (\n <div\n data-spark-component=\"scrolling-list-controls\"\n className={cx(\n 'default:px-md pointer-events-none absolute inset-0 flex flex-row items-center justify-between overflow-hidden',\n className\n )}\n style={\n {\n '--scrolling-list-controls-opacity': visibility === 'hover' ? '0' : '1',\n } as CSSProperties\n }\n data-orientation=\"horizontal\"\n {...rest}\n >\n {children}\n </div>\n )\n}\n\nScrollingListControls.displayName = 'ScrollingList.Controls'\n","import { RefObject, useEffect, useState } from 'react'\n\nexport function useFocusWithinScroll<T extends HTMLElement | null>(\n ref: RefObject<T>, // The container to detect focus within\n scrollRef: RefObject<HTMLDivElement | null> // The scrollable container\n) {\n const [isFocusWithin, setIsFocusWithin] = useState(false)\n\n useEffect(() => {\n const handleFocusIn = (event: FocusEvent) => {\n setIsFocusWithin(true)\n\n const focusedElement = event.target as HTMLElement\n const scrollContainer = scrollRef.current\n\n if (focusedElement && scrollContainer) {\n const focusRect = focusedElement.getBoundingClientRect()\n const scrollRect = scrollContainer.getBoundingClientRect()\n\n // Check if the focused element is fully visible inside the scroll container\n const isFullyVisible =\n focusRect.left >= scrollRect.left &&\n focusRect.right <= scrollRect.right &&\n focusRect.top >= scrollRect.top &&\n focusRect.bottom <= scrollRect.bottom\n\n if (!isFullyVisible) {\n focusedElement.scrollIntoView({ behavior: 'smooth', inline: 'center', block: 'nearest' })\n }\n }\n }\n\n const handleFocusOut = (event: FocusEvent) => {\n if (ref.current && !ref.current.contains(event.relatedTarget as Node)) {\n setIsFocusWithin(false)\n }\n }\n\n const node = ref.current\n if (node) {\n node.addEventListener('focusin', handleFocusIn)\n node.addEventListener('focusout', handleFocusOut)\n }\n\n return () => {\n if (node) {\n node.removeEventListener('focusin', handleFocusIn)\n node.removeEventListener('focusout', handleFocusOut)\n }\n }\n }, [ref, scrollRef])\n\n return isFocusWithin\n}\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, ReactNode, useContext, useRef } from 'react'\n\nimport { Slot } from '../slot'\nimport { ScrollingListContext } from './ScrollingList'\nimport { useFocusWithinScroll } from './useFocusWithinScroll'\n\nexport interface ScrollingListItemProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n children?: ReactNode\n /**\n * DO NOT USE. This prop is automatically managed by the parent ScrollingList.ListItems\n */\n index?: number\n className?: string\n}\n\n/** A single item in the scrolling list. Renders a <div> element. */\nexport const ScrollingListItem = ({\n asChild = false,\n children,\n index = 0,\n className = '',\n ...rest\n}: ScrollingListItemProps) => {\n const ctx = useContext(ScrollingListContext)\n const itemRef = useRef<HTMLDivElement>(null)\n\n const isSnapPoint = ctx.snapPointIndexes.has(index)\n\n useFocusWithinScroll(itemRef, ctx.scrollAreaRef)\n\n const Component = asChild ? Slot : 'div'\n\n return (\n <Component\n data-spark-component=\"scrolling-list-item\"\n role=\"listitem\"\n ref={itemRef}\n className={cx(\n 'default:w-auto default:shrink-0',\n {\n 'snap-start': isSnapPoint,\n 'snap-normal': isSnapPoint && ctx.snapStop === 'normal',\n 'snap-always': isSnapPoint && ctx.snapStop === 'always',\n },\n className\n )}\n {...rest}\n >\n {children}\n </Component>\n )\n}\n\nScrollingListItem.displayName = 'ScrollingList.Item'\n","import { cx } from 'class-variance-authority'\nimport {\n Children,\n cloneElement,\n ComponentPropsWithRef,\n CSSProperties,\n isValidElement,\n KeyboardEvent,\n ReactNode,\n Ref,\n RefObject,\n useContext,\n} from 'react'\n\nimport { ScrollingListContext } from './ScrollingList'\nimport { ScrollingListItemProps } from './ScrollingListItem'\n\ninterface Props extends ComponentPropsWithRef<'div'> {\n children?: ReactNode\n className?: string\n}\n\nexport function mergeRefs<T>(...refs: (Ref<T> | undefined | null)[]): Ref<T> {\n return (value: T | null) => {\n refs.forEach(ref => {\n if (typeof ref === 'function') {\n ref(value)\n } else if (ref && typeof ref === 'object' && 'current' in ref) {\n ;(ref as RefObject<T | null>).current = value\n }\n })\n }\n}\n\n/** The scrollable container for the list items. Renders a <div> element. */\nexport const ScrollingListItems = ({ children, ref, className = '', ...rest }: Props) => {\n const ctx = useContext(ScrollingListContext)\n\n const snapConfig = {\n mandatory: 'x mandatory',\n proximity: 'x proximity',\n none: 'none',\n }\n\n const handleLeftArrow = (event: KeyboardEvent<HTMLDivElement>) => {\n if (!ctx.loop && !ctx.hasPrevPage) return\n\n event.preventDefault()\n ctx.goTo(ctx.hasPrevPage ? ctx.activePageIndex - 1 : ctx.pages.length - 1, {\n behavior: ctx.scrollBehavior,\n })\n }\n\n const handleRightArrow = (event: KeyboardEvent<HTMLDivElement>) => {\n if (!ctx.loop && !ctx.hasNextPage) return\n\n event.preventDefault()\n ctx.goTo(ctx.hasNextPage ? ctx.activePageIndex + 1 : 0, { behavior: ctx.scrollBehavior })\n }\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'ArrowLeft') {\n handleLeftArrow(event)\n }\n\n if (event.key === 'ArrowRight') {\n handleRightArrow(event)\n }\n }\n\n interface CustomCSSProperties extends CSSProperties {\n '--scrolling-list-gap'?: string\n '--scrolling-list-px'?: string\n }\n\n const inlineStyles: CustomCSSProperties = {\n scrollSnapType: snapConfig[ctx.snapType],\n scrollPaddingInline: 'var(--scrolling-list-px)',\n '--scrolling-list-px': `${ctx.scrollPadding}px`,\n '--scrolling-list-gap': `${ctx.gap}px`,\n ...(ctx.withFade && {\n maskImage:\n 'linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1) 44px, rgba(0, 0, 0, 1) calc(100% - 44px), rgba(0, 0, 0, 0))',\n maskSize: `calc(100% + ${ctx.overflow.left ? '0px' : '44px'} + ${ctx.overflow.right ? '0px' : '44px'}) 100%`,\n maskPosition: `${ctx.overflow.left ? '0px' : '-44px'} 0`,\n }),\n }\n\n return (\n <div\n data-spark-component=\"scrolling-list-items\"\n id=\"scrolling-list-items\"\n role=\"list\"\n className={cx(\n 'relative transition-all duration-300',\n 'u-no-scrollbar overflow-x-auto scroll-smooth',\n 'w-full gap-(--scrolling-list-gap) default:flex default:flex-row',\n 'focus-visible:u-outline',\n className\n )}\n ref={mergeRefs<HTMLDivElement>(ctx.scrollAreaRef, ctx.scrollRef, ref)}\n style={inlineStyles}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {Children.map(children, (child, index) =>\n isValidElement<ScrollingListItemProps>(child) ? cloneElement(child, { index }) : child\n )}\n </div>\n )\n}\n\nScrollingListItems.displayName = 'ScrollingList.Items'\n","import { ArrowVerticalRight } from '@spark-ui/icons/ArrowVerticalRight'\nimport { cx } from 'class-variance-authority'\nimport { useContext } from 'react'\n\nimport { Icon } from '../icon'\nimport { IconButton, IconButtonProps } from '../icon-button'\nimport { ScrollingListContext } from './ScrollingList'\n\n/** A button to scroll to the next page of items. Renders a <button> element. */\nexport const ScrollingListNextButton = ({ 'aria-label': ariaLabel, ...rest }: IconButtonProps) => {\n const ctx = useContext(ScrollingListContext)\n\n const handleNextPage = () => {\n if (ctx.hasNextPage) {\n ctx.next({ behavior: ctx.scrollBehavior })\n } else {\n ctx.goTo(0, { behavior: ctx.scrollBehavior })\n }\n }\n\n const listHasOverflow = ctx.overflow.left || ctx.overflow.right\n const isDisabled = !listHasOverflow || (!ctx.loop && !ctx.overflow.right)\n\n return (\n <IconButton\n data-spark-component=\"scrolling-list-next-button\"\n size=\"sm\"\n intent=\"surface\"\n design=\"filled\"\n className={cx(\n 'pointer-events-auto opacity-(--scrolling-list-controls-opacity) shadow-sm disabled:invisible',\n 'group-hover/scrolling-list:opacity-none focus-visible:opacity-none'\n )}\n onClick={handleNextPage}\n disabled={isDisabled}\n aria-label={ariaLabel}\n aria-controls=\"scrolling-list-items\"\n {...rest}\n >\n <Icon>\n <ArrowVerticalRight />\n </Icon>\n </IconButton>\n )\n}\n\nScrollingListNextButton.displayName = 'ScrollingList.NextButton'\n","import { ArrowVerticalLeft } from '@spark-ui/icons/ArrowVerticalLeft'\nimport { cx } from 'class-variance-authority'\nimport { useContext } from 'react'\n\nimport { Icon } from '../icon'\nimport { IconButton, IconButtonProps } from '../icon-button'\nimport { ScrollingListContext } from './ScrollingList'\n\n/** A button to scroll to the previous page of items. Renders a <button> element. */\nexport const ScrollingListPrevButton = ({\n 'aria-label': ariaLabel,\n\n ...rest\n}: IconButtonProps) => {\n const ctx = useContext(ScrollingListContext)\n\n const handlePrevPage = () => {\n const shouldSnapFirstPage =\n ctx.activePageIndex === 0 && (ctx.scrollAreaRef.current?.scrollLeft || 0) > 0\n\n if (shouldSnapFirstPage) {\n ctx.goTo(0, { behavior: ctx.scrollBehavior })\n } else if (ctx.hasPrevPage) {\n ctx.prev({ behavior: ctx.scrollBehavior })\n } else {\n ctx.goTo(ctx.pages.length - 1, { behavior: ctx.scrollBehavior })\n }\n }\n\n const listHasOverflow = ctx.overflow.left || ctx.overflow.right\n const isDisabled = !listHasOverflow || (!ctx.loop && !ctx.overflow.left)\n\n return (\n <IconButton\n data-spark-component=\"scrolling-list-prev-button\"\n size=\"sm\"\n intent=\"surface\"\n design=\"filled\"\n className={cx(\n 'pointer-events-auto opacity-(--scrolling-list-controls-opacity) shadow-sm disabled:invisible',\n 'group-hover/scrolling-list:opacity-none focus-visible:opacity-none'\n )}\n onClick={handlePrevPage}\n disabled={isDisabled}\n aria-label={ariaLabel}\n aria-controls=\"scrolling-list-items\"\n {...rest}\n >\n <Icon>\n <ArrowVerticalLeft />\n </Icon>\n </IconButton>\n )\n}\n\nScrollingListPrevButton.displayName = 'ScrollingList.PrevButton'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, useContext } from 'react'\n\nimport { Button } from '../button'\nimport { ScrollingListContext } from './ScrollingList'\n\ninterface Props extends ComponentPropsWithoutRef<'button'> {\n children: string\n}\n\n/** A button to skip keyboard navigation, improving accessibility. Renders a <button> element. */\nexport const ScrollingListSkipButton = ({ children, ...rest }: Props) => {\n const ctx = useContext(ScrollingListContext)\n\n return (\n <Button\n type=\"button\"\n design=\"tinted\"\n intent=\"surface\"\n tabIndex={0}\n className={cx(\n 'z-raised absolute top-1/2 left-0 -translate-y-1/2',\n 'not-focus-visible:pointer-events-none not-focus-visible:size-0 not-focus-visible:opacity-0'\n )}\n onClick={ctx.skipKeyboardNavigation}\n {...rest}\n >\n {children}\n </Button>\n )\n}\n\nScrollingListSkipButton.displayName = 'ScrollingList.SkipButton'\n","import { ScrollingList as Root } from './ScrollingList'\nimport { ScrollingListControls as Controls } from './ScrollingListControls'\nimport { ScrollingListItem as Item } from './ScrollingListItem'\nimport { ScrollingListItems as Items } from './ScrollingListItems'\nimport { ScrollingListNextButton as NextButton } from './ScrollingListNextButton'\nimport { ScrollingListPrevButton as PrevButton } from './ScrollingListPrevButton'\nimport { ScrollingListSkipButton as SkipButton } from './ScrollingListSkipButton'\n\n/**\n * A horizontal scrollable list component with optional snap points and navigation controls.\n */\nexport const ScrollingList: typeof Root & {\n Controls: typeof Controls\n NextButton: typeof NextButton\n PrevButton: typeof PrevButton\n Item: typeof Item\n Items: typeof Items\n SkipButton: typeof SkipButton\n} = Object.assign(Root, {\n Controls,\n NextButton,\n PrevButton,\n Item,\n Items,\n SkipButton,\n})\n\nScrollingList.displayName = 'ScrollingList'\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/scrolling-list/ScrollingList.tsx","../../src/scrolling-list/ScrollingListControls.tsx","../../src/scrolling-list/useFocusWithinScroll.tsx","../../src/scrolling-list/ScrollingListItem.tsx","../../src/scrolling-list/ScrollingListItems.tsx","../../src/scrolling-list/ScrollingListNextButton.tsx","../../src/scrolling-list/ScrollingListPrevButton.tsx","../../src/scrolling-list/ScrollingListSkipButton.tsx","../../src/scrolling-list/index.ts"],"sourcesContent":["import { ScrollOverflow, useScrollOverflow } from '@spark-ui/hooks/use-scroll-overflow'\nimport { cx } from 'class-variance-authority'\nimport {\n ComponentPropsWithRef,\n createContext,\n ReactNode,\n RefObject,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n} from 'react'\nimport { SnapCarouselResult, useSnapCarousel } from 'react-snap-carousel'\n\ntype SnapType = 'mandatory' | 'proximity' | 'none'\ntype ScrollBehavior = 'smooth' | 'instant'\ntype SnapStop = 'normal' | 'always'\n\ninterface Props extends ComponentPropsWithRef<'div'> {\n /**\n * CSS scroll snap behavior.\n * - `mandatory` to force snapping on each \"page\".\n * - `proximity` to force snapping only when scroll position is near the edge of a \"page\". Behavior can change depending on each browser.\n * - `none` to disabled scroll snapping.\n */\n snapType?: SnapType\n /**\n * Defines whether or not the scroll container is allowed to \"pass over\" possible snap positions.\n */\n snapStop?: SnapStop\n scrollBehavior?: ScrollBehavior\n /**\n * Add a fade effect to indicate content overflow.\n */\n withFade?: boolean\n children?: ReactNode\n /**\n * When `true`, allow previous and next buttons to be used when reaching the edges of the list.\n */\n loop?: boolean\n /**\n * Space (in pixels) between items.\n */\n gap?: number\n /**\n * Offset (in pixels) of the left of the optimal viewing region of the list.\n */\n scrollPadding?: number\n className?: string\n}\n\ninterface ScrollingListContextState extends SnapCarouselResult {\n snapType: SnapType\n snapStop: SnapStop\n scrollBehavior: ScrollBehavior\n visibleItemsRange: readonly [number, number]\n loop: boolean\n gap: number\n withFade: boolean\n scrollPadding: number\n scrollAreaRef: RefObject<HTMLDivElement | null>\n overflow: ScrollOverflow\n skipKeyboardNavigation: () => void\n}\n\nexport const ScrollingListContext = createContext<ScrollingListContextState>(\n null as unknown as ScrollingListContextState\n)\n\nexport const ScrollingList = ({\n snapType = 'none',\n snapStop = 'normal',\n scrollBehavior = 'smooth',\n loop = false,\n gap = 16,\n withFade = false,\n scrollPadding = 0,\n children,\n className,\n ...rest\n}: Props) => {\n const scrollAreaRef = useRef<HTMLDivElement>(null)\n const skipAnchorRef = useRef<HTMLButtonElement>(null)\n\n const snapCarouselAPI = useSnapCarousel()\n\n const { overflow, refresh: refreshOverflow } = useScrollOverflow(scrollAreaRef, {\n precisionTreshold: 1,\n })\n\n const { activePageIndex, pages, refresh } = snapCarouselAPI\n\n const visibleItems = pages[activePageIndex] as number[]\n\n const visibleItemsRange = visibleItems\n ? ([visibleItems[0]! + 1, visibleItems[visibleItems.length - 1]! + 1] as const)\n : ([0, 0] as const)\n\n // Force refresh of the carousel API when children change\n const forceRefresh = useCallback(() => {\n if (refresh && scrollAreaRef.current) {\n // Small delay to ensure DOM is updated\n setTimeout(() => {\n refresh()\n }, 0)\n }\n }, [refresh])\n\n useEffect(() => {\n forceRefresh()\n }, [children, forceRefresh])\n\n useLayoutEffect(() => {\n if (scrollAreaRef.current) {\n // Use requestAnimationFrame to ensure proper timing with the render cycle\n // This prevents race conditions that occur when the console is closed\n requestAnimationFrame(() => {\n refreshOverflow()\n })\n }\n }, [children, refreshOverflow])\n\n const skipKeyboardNavigation = () => {\n skipAnchorRef.current?.focus()\n }\n\n const ctxValue: ScrollingListContextState = {\n ...snapCarouselAPI,\n snapType,\n snapStop,\n skipKeyboardNavigation,\n scrollBehavior,\n visibleItemsRange,\n loop,\n gap,\n withFade,\n scrollPadding,\n scrollAreaRef,\n overflow,\n }\n\n return (\n <ScrollingListContext value={ctxValue}>\n <div\n data-spark-component=\"scrolling-list\"\n className={cx(\n 'gap-lg group/scrolling-list relative flex flex-col default:w-full',\n className\n )}\n {...rest}\n >\n {children}\n </div>\n <span ref={skipAnchorRef} className=\"size-0 overflow-hidden\" tabIndex={-1} />\n </ScrollingListContext>\n )\n}\n\nScrollingList.displayName = 'ScrollingList'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, CSSProperties, ReactNode } from 'react'\n\ninterface ScrollingListControls extends ComponentPropsWithoutRef<'div'> {\n /**\n * Visibility behavior of the control buttons:\n * - `always`: buttons are always visible.\n * - `hover`: buttons only appear on hover.\n *\n * a11y: `hover` is dangerous for accessibility as it disabled controls for touch screen users.\n * When using it, you must provide an alternative control outside of the list to replace them.\n */\n visibility?: 'hover' | 'always'\n children: ReactNode\n}\n\n/** Container for navigation controls (previous/next buttons) of the scrolling list. Renders a <div> element. */\nexport const ScrollingListControls = ({\n children,\n visibility = 'always',\n className,\n ...rest\n}: ScrollingListControls) => {\n return (\n <div\n data-spark-component=\"scrolling-list-controls\"\n className={cx(\n 'default:px-md pointer-events-none absolute inset-0 flex flex-row items-center justify-between overflow-hidden',\n className\n )}\n style={\n {\n '--scrolling-list-controls-opacity': visibility === 'hover' ? '0' : '1',\n } as CSSProperties\n }\n data-orientation=\"horizontal\"\n {...rest}\n >\n {children}\n </div>\n )\n}\n\nScrollingListControls.displayName = 'ScrollingList.Controls'\n","import { RefObject, useEffect, useState } from 'react'\n\nexport function useFocusWithinScroll<T extends HTMLElement | null>(\n ref: RefObject<T>, // The container to detect focus within\n scrollRef: RefObject<HTMLDivElement | null> // The scrollable container\n) {\n const [isFocusWithin, setIsFocusWithin] = useState(false)\n\n useEffect(() => {\n const handleFocusIn = (event: FocusEvent) => {\n setIsFocusWithin(true)\n\n const focusedElement = event.target as HTMLElement\n const scrollContainer = scrollRef.current\n\n if (focusedElement && scrollContainer) {\n const focusRect = focusedElement.getBoundingClientRect()\n const scrollRect = scrollContainer.getBoundingClientRect()\n\n // Check if the focused element is fully visible inside the scroll container\n const isFullyVisible =\n focusRect.left >= scrollRect.left &&\n focusRect.right <= scrollRect.right &&\n focusRect.top >= scrollRect.top &&\n focusRect.bottom <= scrollRect.bottom\n\n if (!isFullyVisible) {\n focusedElement.scrollIntoView({ behavior: 'smooth', inline: 'center', block: 'nearest' })\n }\n }\n }\n\n const handleFocusOut = (event: FocusEvent) => {\n if (ref.current && !ref.current.contains(event.relatedTarget as Node)) {\n setIsFocusWithin(false)\n }\n }\n\n const node = ref.current\n if (node) {\n node.addEventListener('focusin', handleFocusIn)\n node.addEventListener('focusout', handleFocusOut)\n }\n\n return () => {\n if (node) {\n node.removeEventListener('focusin', handleFocusIn)\n node.removeEventListener('focusout', handleFocusOut)\n }\n }\n }, [ref, scrollRef])\n\n return isFocusWithin\n}\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, ReactNode, useContext, useRef } from 'react'\n\nimport { Slot } from '../slot'\nimport { ScrollingListContext } from './ScrollingList'\nimport { useFocusWithinScroll } from './useFocusWithinScroll'\n\nexport interface ScrollingListItemProps extends ComponentPropsWithoutRef<'div'> {\n /**\n * Change the default rendered element for the one passed as a child, merging their props and behavior.\n */\n asChild?: boolean\n children?: ReactNode\n /**\n * DO NOT USE. This prop is automatically managed by the parent ScrollingList.ListItems\n */\n index?: number\n className?: string\n}\n\n/** A single item in the scrolling list. Renders a <div> element. */\nexport const ScrollingListItem = ({\n asChild = false,\n children,\n index = 0,\n className = '',\n ...rest\n}: ScrollingListItemProps) => {\n const ctx = useContext(ScrollingListContext)\n const itemRef = useRef<HTMLDivElement>(null)\n\n const isSnapPoint = ctx.snapPointIndexes.has(index)\n\n useFocusWithinScroll(itemRef, ctx.scrollAreaRef)\n\n const Component = asChild ? Slot : 'div'\n\n return (\n <Component\n data-spark-component=\"scrolling-list-item\"\n role=\"listitem\"\n ref={itemRef}\n className={cx(\n 'default:w-auto default:shrink-0',\n {\n 'snap-start': isSnapPoint,\n 'snap-normal': isSnapPoint && ctx.snapStop === 'normal',\n 'snap-always': isSnapPoint && ctx.snapStop === 'always',\n },\n className\n )}\n {...rest}\n >\n {children}\n </Component>\n )\n}\n\nScrollingListItem.displayName = 'ScrollingList.Item'\n","import { cx } from 'class-variance-authority'\nimport {\n Children,\n cloneElement,\n ComponentPropsWithRef,\n CSSProperties,\n isValidElement,\n KeyboardEvent,\n ReactNode,\n Ref,\n RefObject,\n useContext,\n} from 'react'\n\nimport { ScrollingListContext } from './ScrollingList'\nimport { ScrollingListItemProps } from './ScrollingListItem'\n\ninterface Props extends ComponentPropsWithRef<'div'> {\n children?: ReactNode\n className?: string\n}\n\nexport function mergeRefs<T>(...refs: (Ref<T> | undefined | null)[]): Ref<T> {\n return (value: T | null) => {\n refs.forEach(ref => {\n if (typeof ref === 'function') {\n ref(value)\n } else if (ref && typeof ref === 'object' && 'current' in ref) {\n ;(ref as RefObject<T | null>).current = value\n }\n })\n }\n}\n\n/** The scrollable container for the list items. Renders a <div> element. */\nexport const ScrollingListItems = ({ children, ref, className = '', ...rest }: Props) => {\n const ctx = useContext(ScrollingListContext)\n\n const snapConfig = {\n mandatory: 'x mandatory',\n proximity: 'x proximity',\n none: 'none',\n }\n\n const handleLeftArrow = (event: KeyboardEvent<HTMLDivElement>) => {\n if (!ctx.loop && !ctx.hasPrevPage) return\n\n event.preventDefault()\n ctx.goTo(ctx.hasPrevPage ? ctx.activePageIndex - 1 : ctx.pages.length - 1, {\n behavior: ctx.scrollBehavior,\n })\n }\n\n const handleRightArrow = (event: KeyboardEvent<HTMLDivElement>) => {\n if (!ctx.loop && !ctx.hasNextPage) return\n\n event.preventDefault()\n ctx.goTo(ctx.hasNextPage ? ctx.activePageIndex + 1 : 0, { behavior: ctx.scrollBehavior })\n }\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (event.key === 'ArrowLeft') {\n handleLeftArrow(event)\n }\n\n if (event.key === 'ArrowRight') {\n handleRightArrow(event)\n }\n }\n\n interface CustomCSSProperties extends CSSProperties {\n '--scrolling-list-gap'?: string\n '--scrolling-list-px'?: string\n }\n\n const inlineStyles: CustomCSSProperties = {\n scrollSnapType: snapConfig[ctx.snapType],\n scrollPaddingInline: 'var(--scrolling-list-px)',\n '--scrolling-list-px': `${ctx.scrollPadding}px`,\n '--scrolling-list-gap': `${ctx.gap}px`,\n ...(ctx.withFade && {\n maskImage:\n 'linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1) 44px, rgba(0, 0, 0, 1) calc(100% - 44px), rgba(0, 0, 0, 0))',\n maskSize: `calc(100% + ${ctx.overflow.left ? '0px' : '44px'} + ${ctx.overflow.right ? '0px' : '44px'}) 100%`,\n maskPosition: `${ctx.overflow.left ? '0px' : '-44px'} 0`,\n }),\n }\n\n return (\n <div\n data-spark-component=\"scrolling-list-items\"\n id=\"scrolling-list-items\"\n role=\"list\"\n className={cx(\n 'relative transition-all duration-300',\n 'u-no-scrollbar overflow-x-auto scroll-smooth',\n 'w-full gap-(--scrolling-list-gap) default:flex default:flex-row',\n 'focus-visible:u-outline',\n className\n )}\n ref={mergeRefs<HTMLDivElement>(ctx.scrollAreaRef, ctx.scrollRef, ref)}\n style={inlineStyles}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {Children.map(children, (child, index) =>\n isValidElement<ScrollingListItemProps>(child) ? cloneElement(child, { index }) : child\n )}\n </div>\n )\n}\n\nScrollingListItems.displayName = 'ScrollingList.Items'\n","import { ArrowVerticalRight } from '@spark-ui/icons/ArrowVerticalRight'\nimport { cx } from 'class-variance-authority'\nimport { useContext, MouseEvent } from 'react'\n\nimport { Icon } from '../icon'\nimport { IconButton, IconButtonProps } from '../icon-button'\nimport { ScrollingListContext } from './ScrollingList'\n\n/** A button to scroll to the next page of items. Renders a <button> element. */\nexport const ScrollingListNextButton = ({\n 'aria-label': ariaLabel,\n onClick,\n ...rest\n}: IconButtonProps) => {\n const ctx = useContext(ScrollingListContext)\n\n const handleNextPage = (e: MouseEvent<HTMLButtonElement>) => {\n if (ctx.hasNextPage) {\n ctx.next({ behavior: ctx.scrollBehavior })\n } else {\n ctx.goTo(0, { behavior: ctx.scrollBehavior })\n }\n\n onClick?.(e)\n }\n\n const listHasOverflow = ctx.overflow.left || ctx.overflow.right\n const isDisabled = !listHasOverflow || (!ctx.loop && !ctx.overflow.right)\n\n return (\n <IconButton\n data-spark-component=\"scrolling-list-next-button\"\n size=\"sm\"\n intent=\"surface\"\n design=\"filled\"\n className={cx(\n 'pointer-events-auto opacity-(--scrolling-list-controls-opacity) shadow-sm disabled:invisible',\n 'group-hover/scrolling-list:opacity-none focus-visible:opacity-none'\n )}\n onClick={handleNextPage}\n disabled={isDisabled}\n aria-label={ariaLabel}\n aria-controls=\"scrolling-list-items\"\n {...rest}\n >\n <Icon>\n <ArrowVerticalRight />\n </Icon>\n </IconButton>\n )\n}\n\nScrollingListNextButton.displayName = 'ScrollingList.NextButton'\n","import { ArrowVerticalLeft } from '@spark-ui/icons/ArrowVerticalLeft'\nimport { cx } from 'class-variance-authority'\nimport { useContext, MouseEvent } from 'react'\n\nimport { Icon } from '../icon'\nimport { IconButton, IconButtonProps } from '../icon-button'\nimport { ScrollingListContext } from './ScrollingList'\n\n/** A button to scroll to the previous page of items. Renders a <button> element. */\nexport const ScrollingListPrevButton = ({\n 'aria-label': ariaLabel,\n onClick,\n ...rest\n}: IconButtonProps) => {\n const ctx = useContext(ScrollingListContext)\n\n const handlePrevPage = (e: MouseEvent<HTMLButtonElement>) => {\n const shouldSnapFirstPage =\n ctx.activePageIndex === 0 && (ctx.scrollAreaRef.current?.scrollLeft || 0) > 0\n\n if (shouldSnapFirstPage) {\n ctx.goTo(0, { behavior: ctx.scrollBehavior })\n } else if (ctx.hasPrevPage) {\n ctx.prev({ behavior: ctx.scrollBehavior })\n } else {\n ctx.goTo(ctx.pages.length - 1, { behavior: ctx.scrollBehavior })\n }\n\n onClick?.(e)\n }\n\n const listHasOverflow = ctx.overflow.left || ctx.overflow.right\n const isDisabled = !listHasOverflow || (!ctx.loop && !ctx.overflow.left)\n\n return (\n <IconButton\n data-spark-component=\"scrolling-list-prev-button\"\n size=\"sm\"\n intent=\"surface\"\n design=\"filled\"\n className={cx(\n 'pointer-events-auto opacity-(--scrolling-list-controls-opacity) shadow-sm disabled:invisible',\n 'group-hover/scrolling-list:opacity-none focus-visible:opacity-none'\n )}\n onClick={handlePrevPage}\n disabled={isDisabled}\n aria-label={ariaLabel}\n aria-controls=\"scrolling-list-items\"\n {...rest}\n >\n <Icon>\n <ArrowVerticalLeft />\n </Icon>\n </IconButton>\n )\n}\n\nScrollingListPrevButton.displayName = 'ScrollingList.PrevButton'\n","import { cx } from 'class-variance-authority'\nimport { ComponentPropsWithoutRef, useContext } from 'react'\n\nimport { Button } from '../button'\nimport { ScrollingListContext } from './ScrollingList'\n\ninterface Props extends ComponentPropsWithoutRef<'button'> {\n children: string\n}\n\n/** A button to skip keyboard navigation, improving accessibility. Renders a <button> element. */\nexport const ScrollingListSkipButton = ({ children, ...rest }: Props) => {\n const ctx = useContext(ScrollingListContext)\n\n return (\n <Button\n type=\"button\"\n design=\"tinted\"\n intent=\"surface\"\n tabIndex={0}\n className={cx(\n 'z-raised absolute top-1/2 left-0 -translate-y-1/2',\n 'not-focus-visible:pointer-events-none not-focus-visible:size-0 not-focus-visible:opacity-0'\n )}\n onClick={ctx.skipKeyboardNavigation}\n {...rest}\n >\n {children}\n </Button>\n )\n}\n\nScrollingListSkipButton.displayName = 'ScrollingList.SkipButton'\n","import { ScrollingList as Root } from './ScrollingList'\nimport { ScrollingListControls as Controls } from './ScrollingListControls'\nimport { ScrollingListItem as Item } from './ScrollingListItem'\nimport { ScrollingListItems as Items } from './ScrollingListItems'\nimport { ScrollingListNextButton as NextButton } from './ScrollingListNextButton'\nimport { ScrollingListPrevButton as PrevButton } from './ScrollingListPrevButton'\nimport { ScrollingListSkipButton as SkipButton } from './ScrollingListSkipButton'\n\n/**\n * A horizontal scrollable list component with optional snap points and navigation controls.\n */\nexport const ScrollingList: typeof Root & {\n Controls: typeof Controls\n NextButton: typeof NextButton\n PrevButton: typeof PrevButton\n Item: typeof Item\n Items: typeof Items\n SkipButton: typeof SkipButton\n} = Object.assign(Root, {\n Controls,\n NextButton,\n PrevButton,\n Item,\n Items,\n SkipButton,\n})\n\nScrollingList.displayName = 'ScrollingList'\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const thumbVariants: (props?: ({
|
|
3
|
-
intent?: "main" | "alert" | "
|
|
3
|
+
intent?: "main" | "alert" | "support" | "error" | "accent" | "success" | "info" | "neutral" | null | undefined;
|
|
4
4
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
5
5
|
export type SliderThumbVariantsProps = VariantProps<typeof thumbVariants>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const trackVariants: (props?: import('class-variance-authority/types').ClassProp | undefined) => string;
|
|
3
3
|
export declare const rangeVariants: (props?: ({
|
|
4
|
-
intent?: "main" | "alert" | "
|
|
4
|
+
intent?: "main" | "alert" | "support" | "error" | "accent" | "success" | "info" | "neutral" | null | undefined;
|
|
5
5
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
6
6
|
export type SliderRangeVariantsProps = VariantProps<typeof rangeVariants>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const spinnerStyles: (props?: ({
|
|
3
3
|
size?: "current" | "sm" | "md" | "full" | null | undefined;
|
|
4
|
-
intent?: "main" | "current" | "alert" | "
|
|
4
|
+
intent?: "main" | "current" | "alert" | "support" | "error" | "accent" | "success" | "info" | "neutral" | null | undefined;
|
|
5
5
|
isBackgroundVisible?: boolean | null | undefined;
|
|
6
6
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
7
7
|
export type SpinnerStylesProps = VariantProps<typeof spinnerStyles>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const styles: (props?: ({
|
|
3
3
|
size?: "sm" | "md" | null | undefined;
|
|
4
|
-
intent?: "main" | "alert" | "
|
|
4
|
+
intent?: "main" | "alert" | "support" | "error" | "accent" | "success" | "info" | "neutral" | null | undefined;
|
|
5
5
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
6
6
|
export type StylesProps = VariantProps<typeof styles>;
|
|
7
7
|
export declare const thumbWrapperStyles: (props?: ({
|
package/dist/tag/Tag.styles.d.ts
CHANGED
|
@@ -3,6 +3,6 @@ export declare const tagStyles: (props?: ({
|
|
|
3
3
|
design?: "filled" | "outlined" | "tinted" | null | undefined;
|
|
4
4
|
size?: "md" | "lg" | null | undefined;
|
|
5
5
|
shape?: "square" | "rounded" | "pill" | null | undefined;
|
|
6
|
-
intent?: "main" | "alert" | "support" | "accent" | "success" | "info" | "neutral" | "danger" |
|
|
6
|
+
intent?: "main" | "alert" | "surface" | "support" | "accent" | "success" | "info" | "neutral" | "danger" | null | undefined;
|
|
7
7
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
8
8
|
export type TagStylesProps = VariantProps<typeof tagStyles>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
export declare const toastStyles: (props?: ({
|
|
3
3
|
design?: "filled" | "tinted" | null | undefined;
|
|
4
|
-
intent?: "main" | "alert" | "
|
|
4
|
+
intent?: "main" | "alert" | "surface" | "support" | "error" | "accent" | "success" | "info" | "neutral" | "surfaceInverse" | null | undefined;
|
|
5
5
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
6
6
|
export type ToastVariantProps = VariantProps<typeof toastStyles>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spark-ui/components",
|
|
3
|
-
"version": "17.
|
|
3
|
+
"version": "17.14.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Spark (Leboncoin design system) components.",
|
|
6
6
|
"exports": {
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@base-ui/react": "^1.5.0",
|
|
51
|
-
"@spark-ui/hooks": "17.
|
|
52
|
-
"@spark-ui/icons": "17.
|
|
53
|
-
"@spark-ui/internal-utils": "17.
|
|
51
|
+
"@spark-ui/hooks": "17.14.0",
|
|
52
|
+
"@spark-ui/icons": "17.14.0",
|
|
53
|
+
"@spark-ui/internal-utils": "17.14.0",
|
|
54
54
|
"@zag-js/pagination": "1.30.0",
|
|
55
55
|
"@zag-js/react": "1.30.0",
|
|
56
56
|
"class-variance-authority": "0.7.1",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"react-snap-carousel": "0.5.1"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"@spark-ui/theme-utils": "17.
|
|
65
|
+
"@spark-ui/theme-utils": "17.14.0",
|
|
66
66
|
"react": "19.2.4",
|
|
67
67
|
"react-dom": "19.2.4",
|
|
68
68
|
"tailwindcss": "4.1.18"
|