@torpor/ui 0.4.0 → 1.0.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/README.md +83 -7
- package/dist/Accordion/Accordion.torp +42 -165
- package/dist/Accordion/AccordionContent.torp +6 -6
- package/dist/Accordion/AccordionHeader.torp +7 -11
- package/dist/Accordion/AccordionItem.torp +24 -24
- package/dist/Accordion/AccordionTrigger.torp +17 -8
- package/dist/Accordion/AccordionTypes.ts +1 -1
- package/dist/Accordion/index.d.ts +23 -25
- package/dist/Accordion/index.js +6 -22
- package/dist/Breadcrumb/Breadcrumb.torp +12 -10
- package/dist/Breadcrumb/BreadcrumbItem.torp +6 -6
- package/dist/Breadcrumb/BreadcrumbList.torp +21 -0
- package/dist/Breadcrumb/BreadcrumbSeparator.torp +4 -4
- package/dist/Breadcrumb/index.d.ts +39 -15
- package/dist/Breadcrumb/index.js +5 -14
- package/dist/Calendar/Calendar.torp +163 -156
- package/dist/Calendar/CalendarDay.torp +91 -45
- package/dist/Calendar/CalendarDayHeader.torp +36 -0
- package/dist/Calendar/CalendarGrid.torp +104 -0
- package/dist/Calendar/CalendarGridHeader.torp +43 -0
- package/dist/Calendar/CalendarHeader.torp +48 -0
- package/dist/Calendar/CalendarHeaderTrigger.torp +54 -0
- package/dist/Calendar/CalendarTypes.ts +24 -3
- package/dist/Calendar/buildDays.ts +54 -0
- package/dist/Calendar/index.d.ts +191 -5
- package/dist/Calendar/index.js +8 -10
- package/dist/Carousel/Carousel.torp +180 -0
- package/dist/Carousel/CarouselIndicators.torp +65 -0
- package/dist/Carousel/CarouselNext.torp +43 -0
- package/dist/Carousel/CarouselPrevious.torp +44 -0
- package/dist/Carousel/CarouselSlide.torp +57 -0
- package/dist/Carousel/CarouselTypes.ts +28 -0
- package/dist/Carousel/index.d.ts +147 -0
- package/dist/Carousel/index.js +6 -0
- package/dist/Charts/BarChart.torp +55 -144
- package/dist/Charts/Chart.torp +120 -0
- package/dist/Charts/ChartBars.torp +78 -0
- package/dist/Charts/ChartColumns.torp +66 -0
- package/dist/Charts/ChartGrid.torp +54 -0
- package/dist/Charts/ChartLines.torp +60 -0
- package/dist/Charts/ChartTypes.ts +25 -0
- package/dist/Charts/ChartXAxis.torp +83 -0
- package/dist/Charts/ChartYAxis.torp +105 -0
- package/dist/Charts/ColumnChart.torp +70 -0
- package/dist/Charts/GridLines.torp +4 -4
- package/dist/Charts/LineChart.torp +55 -178
- package/dist/Charts/PieChart.torp +14 -20
- package/dist/Charts/ScatterChart.torp +45 -38
- package/dist/Charts/SparkLine.torp +16 -19
- package/dist/Charts/XAxis.torp +11 -11
- package/dist/Charts/YAxis.torp +8 -8
- package/dist/Charts/index.d.ts +328 -79
- package/dist/Charts/index.js +17 -34
- package/dist/ColorPicker/ColorPalette.torp +154 -0
- package/dist/ColorPicker/ColorPicker.torp +157 -0
- package/dist/ColorPicker/index.d.ts +85 -0
- package/dist/ColorPicker/index.js +3 -0
- package/dist/ComboBox/ComboBox.torp +205 -0
- package/dist/ComboBox/ComboBoxContent.torp +112 -0
- package/dist/ComboBox/ComboBoxInput.torp +145 -0
- package/dist/ComboBox/ComboBoxTrigger.torp +49 -0
- package/dist/ComboBox/ComboBoxTypes.ts +39 -0
- package/dist/ComboBox/index.d.ts +152 -0
- package/dist/ComboBox/index.js +6 -0
- package/dist/CommandPalette/CommandPalette.torp +220 -0
- package/dist/CommandPalette/CommandTypes.ts +14 -0
- package/dist/CommandPalette/index.d.ts +45 -0
- package/dist/CommandPalette/index.js +2 -0
- package/dist/Contextual/Contextual.torp +32 -50
- package/dist/Contextual/ContextualContent.torp +29 -73
- package/dist/Contextual/ContextualHover.torp +112 -0
- package/dist/Contextual/ContextualTrigger.torp +31 -42
- package/dist/Contextual/ContextualTypes.ts +4 -17
- package/dist/Contextual/index.d.ts +44 -27
- package/dist/Contextual/index.js +5 -14
- package/dist/DataGrid/DataGrid.torp +496 -0
- package/dist/DataGrid/DataGridTypes.ts +25 -0
- package/dist/DataGrid/index.d.ts +90 -0
- package/dist/DataGrid/index.js +3 -0
- package/dist/DataGrid/sortRows.ts +32 -0
- package/dist/DatePicker/DatePicker.torp +222 -0
- package/dist/DatePicker/DatePickerHeader.torp +20 -0
- package/dist/DatePicker/index.d.ts +55 -0
- package/dist/DatePicker/index.js +2 -0
- package/dist/DateRangePicker/DateRangePicker.torp +311 -0
- package/dist/DateRangePicker/DateRangePickerDay.torp +137 -0
- package/dist/DateRangePicker/DateRangePickerTypes.ts +21 -0
- package/dist/DateRangePicker/index.d.ts +76 -0
- package/dist/DateRangePicker/index.js +3 -0
- package/dist/Dialog/Dialog.torp +24 -17
- package/dist/Dialog/DialogBody.torp +5 -9
- package/dist/Dialog/DialogButton.torp +12 -12
- package/dist/Dialog/DialogFooter.torp +3 -7
- package/dist/Dialog/DialogHeader.torp +6 -10
- package/dist/Dialog/index.d.ts +27 -27
- package/dist/Dialog/index.js +6 -22
- package/dist/Disclosure/Disclosure.torp +18 -18
- package/dist/Disclosure/DisclosureContent.torp +5 -6
- package/dist/Disclosure/DisclosureHeader.torp +7 -11
- package/dist/Disclosure/DisclosureTrigger.torp +4 -5
- package/dist/Disclosure/index.d.ts +14 -16
- package/dist/Disclosure/index.js +5 -18
- package/dist/Drawer/Drawer.torp +19 -49
- package/dist/Drawer/DrawerContent.torp +67 -13
- package/dist/Drawer/DrawerOverlay.torp +4 -4
- package/dist/Drawer/DrawerTrigger.torp +16 -4
- package/dist/Drawer/DrawerTypes.ts +3 -0
- package/dist/Drawer/index.d.ts +16 -20
- package/dist/Drawer/index.js +5 -18
- package/dist/FocusGroup/FocusGroup.torp +70 -0
- package/dist/FocusGroup/FocusGroupButton.torp +59 -0
- package/dist/FocusGroup/FocusGroupTypes.ts +14 -0
- package/dist/FocusGroup/index.d.ts +44 -0
- package/dist/FocusGroup/index.js +3 -0
- package/dist/Form/CheckBox.torp +27 -18
- package/dist/Form/Field.torp +17 -17
- package/dist/Form/File.torp +31 -22
- package/dist/Form/FileDrop.torp +187 -0
- package/dist/Form/Form.torp +24 -22
- package/dist/Form/FormTypes.ts +2 -0
- package/dist/Form/FormValues.torp +37 -0
- package/dist/Form/Hidden.torp +4 -12
- package/dist/Form/Input.torp +38 -32
- package/dist/Form/Label.torp +3 -3
- package/dist/Form/Message.torp +13 -5
- package/dist/Form/MessageSummary.torp +5 -4
- package/dist/Form/Option.torp +11 -7
- package/dist/Form/Select.torp +32 -28
- package/dist/Form/TextArea.torp +35 -31
- package/dist/Form/Toggle.torp +109 -0
- package/dist/Form/index.d.ts +178 -79
- package/dist/Form/index.js +16 -50
- package/dist/ListBox/ListBox.torp +253 -150
- package/dist/ListBox/ListBoxItem.torp +54 -30
- package/dist/ListBox/ListBoxSeparator.torp +5 -2
- package/dist/ListBox/ListBoxTypes.ts +23 -5
- package/dist/ListBox/LoadedListBoxItems.torp +41 -0
- package/dist/ListBox/index.d.ts +56 -17
- package/dist/ListBox/index.js +4 -14
- package/dist/MaskedInput/MaskedInput.torp +143 -0
- package/dist/MaskedInput/index.d.ts +52 -0
- package/dist/MaskedInput/index.js +2 -0
- package/dist/Menu/Menu.torp +86 -71
- package/dist/Menu/MenuButton.torp +17 -10
- package/dist/Menu/MenuCheck.torp +22 -18
- package/dist/Menu/MenuGroup.torp +4 -4
- package/dist/Menu/MenuIndicator.torp +5 -13
- package/dist/Menu/MenuPopout.torp +20 -50
- package/dist/Menu/MenuPopoutContent.torp +15 -66
- package/dist/Menu/MenuPopoutTrigger.torp +19 -100
- package/dist/Menu/MenuRadio.torp +25 -26
- package/dist/Menu/MenuRadioGroup.torp +25 -68
- package/dist/Menu/MenuSeparator.torp +3 -2
- package/dist/Menu/MenuTypes.ts +9 -19
- package/dist/Menu/index.d.ts +45 -51
- package/dist/Menu/index.js +12 -46
- package/dist/MenuBar/MenuBar.torp +31 -83
- package/dist/MenuBar/MenuBarItem.torp +33 -51
- package/dist/MenuBar/MenuBarItemContent.torp +15 -101
- package/dist/MenuBar/MenuBarItemTrigger.torp +20 -55
- package/dist/MenuBar/MenuBarTypes.ts +11 -10
- package/dist/MenuBar/index.d.ts +17 -19
- package/dist/MenuBar/index.js +5 -18
- package/dist/Modal/Modal.torp +22 -47
- package/dist/Modal/ModalContent.torp +21 -44
- package/dist/Modal/ModalOverlay.torp +4 -4
- package/dist/Modal/ModalTrigger.torp +16 -32
- package/dist/Modal/ModalTypes.ts +5 -16
- package/dist/Modal/index.d.ts +17 -29
- package/dist/Modal/index.js +29 -28
- package/dist/Modal/index.js.map +1 -1
- package/dist/Modal/showPrompt.ts +2 -2
- package/dist/NavMenu/NavMenu.torp +22 -111
- package/dist/NavMenu/NavMenuButton.torp +7 -8
- package/dist/NavMenu/NavMenuElement.torp +6 -7
- package/dist/NavMenu/NavMenuGroup.torp +5 -5
- package/dist/NavMenu/NavMenuGroupHeader.torp +5 -8
- package/dist/NavMenu/NavMenuLink.torp +7 -10
- package/dist/NavMenu/NavMenuPopout.torp +15 -60
- package/dist/NavMenu/NavMenuPopoutContent.torp +14 -73
- package/dist/NavMenu/NavMenuPopoutTrigger.torp +17 -99
- package/dist/NavMenu/NavMenuSeparator.torp +3 -7
- package/dist/NavMenu/NavMenuTypes.ts +4 -14
- package/dist/NavMenu/index.d.ts +40 -44
- package/dist/NavMenu/index.js +11 -42
- package/dist/Notification/Notification.torp +12 -24
- package/dist/Notification/NotificationClose.torp +6 -3
- package/dist/Notification/NotificationContainer.torp +3 -7
- package/dist/Notification/NotificationContent.torp +3 -7
- package/dist/Notification/NotificationTypes.ts +1 -1
- package/dist/Notification/index.d.ts +15 -12
- package/dist/Notification/index.js +22 -32
- package/dist/Notification/index.js.map +1 -1
- package/dist/NumberInput/NumberInput.torp +255 -0
- package/dist/NumberInput/index.d.ts +44 -0
- package/dist/NumberInput/index.js +2 -0
- package/dist/Pagination/Pagination.torp +41 -34
- package/dist/Pagination/PaginationItem.torp +50 -13
- package/dist/Pagination/PaginationTypes.ts +3 -6
- package/dist/Pagination/buildPages.ts +9 -5
- package/dist/Pagination/index.d.ts +19 -9
- package/dist/Pagination/index.js +3 -40
- package/dist/Popover/Popover.torp +32 -50
- package/dist/Popover/PopoverContent.torp +27 -76
- package/dist/Popover/PopoverHover.torp +90 -0
- package/dist/Popover/PopoverTrigger.torp +17 -40
- package/dist/Popover/PopoverTypes.ts +4 -17
- package/dist/Popover/index.d.ts +40 -25
- package/dist/Popover/index.js +18 -18
- package/dist/Popover/index.js.map +1 -1
- package/dist/Progress/Progress.torp +88 -0
- package/dist/Progress/index.d.ts +37 -0
- package/dist/Progress/index.js +2 -0
- package/dist/Rating/Rating.torp +225 -0
- package/dist/Rating/index.d.ts +44 -0
- package/dist/Rating/index.js +2 -0
- package/dist/SegmentedControl/SegmentedControl.torp +233 -0
- package/dist/SegmentedControl/SegmentedControlTypes.ts +26 -0
- package/dist/SegmentedControl/SegmentedItem.torp +78 -0
- package/dist/SegmentedControl/index.d.ts +74 -0
- package/dist/SegmentedControl/index.js +3 -0
- package/dist/SelectBox/SelectBox.torp +107 -53
- package/dist/SelectBox/SelectBoxContent.torp +45 -19
- package/dist/SelectBox/SelectBoxTrigger.torp +108 -8
- package/dist/SelectBox/SelectBoxTypes.ts +26 -11
- package/dist/SelectBox/index.d.ts +39 -54
- package/dist/SelectBox/index.js +5 -18
- package/dist/Slider/Slider.torp +248 -0
- package/dist/Slider/index.d.ts +45 -0
- package/dist/Slider/index.js +2 -0
- package/dist/Splitter/Splitter.torp +156 -0
- package/dist/Splitter/SplitterHandle.torp +161 -0
- package/dist/Splitter/SplitterPane.torp +63 -0
- package/dist/Splitter/SplitterTypes.ts +31 -0
- package/dist/Splitter/index.d.ts +103 -0
- package/dist/Splitter/index.js +4 -0
- package/dist/Stepper/Stepper.torp +146 -0
- package/dist/Stepper/StepperMarker.torp +24 -0
- package/dist/Stepper/StepperNext.torp +44 -0
- package/dist/Stepper/StepperPrevious.torp +44 -0
- package/dist/Stepper/StepperStep.torp +90 -0
- package/dist/Stepper/StepperTypes.ts +30 -0
- package/dist/Stepper/index.d.ts +149 -0
- package/dist/Stepper/index.js +6 -0
- package/dist/TabGroup/TabContent.torp +6 -6
- package/dist/TabGroup/TabGroup.torp +97 -113
- package/dist/TabGroup/TabGroupTypes.ts +1 -1
- package/dist/TabGroup/TabHeader.torp +23 -19
- package/dist/TabGroup/TabList.torp +8 -21
- package/dist/TabGroup/TabTrigger.torp +6 -7
- package/dist/TabGroup/index.d.ts +26 -26
- package/dist/TabGroup/index.js +6 -22
- package/dist/TagInput/TagInput.torp +378 -0
- package/dist/TagInput/index.d.ts +48 -0
- package/dist/TagInput/index.js +2 -0
- package/dist/TimePicker/TimePicker.torp +462 -0
- package/dist/TimePicker/index.d.ts +53 -0
- package/dist/TimePicker/index.js +2 -0
- package/dist/ToolBar/ToolBar.torp +29 -110
- package/dist/ToolBar/ToolBarButton.torp +7 -8
- package/dist/ToolBar/ToolBarElement.torp +7 -11
- package/dist/ToolBar/ToolBarPopout.torp +16 -68
- package/dist/ToolBar/ToolBarPopoutContent.torp +15 -73
- package/dist/ToolBar/ToolBarPopoutTrigger.torp +19 -110
- package/dist/ToolBar/ToolBarSeparator.torp +3 -7
- package/dist/ToolBar/ToolBarTypes.ts +7 -14
- package/dist/ToolBar/index.d.ts +30 -32
- package/dist/ToolBar/index.js +8 -30
- package/dist/Tree/Tree.torp +395 -0
- package/dist/Tree/TreeItem.torp +176 -0
- package/dist/Tree/TreeItemChildren.torp +60 -0
- package/dist/Tree/TreeItemContent.torp +46 -0
- package/dist/Tree/TreeItemLabel.torp +94 -0
- package/dist/Tree/TreeItemTrigger.torp +78 -0
- package/dist/Tree/TreeLoadedChildren.torp +122 -0
- package/dist/Tree/TreeTypes.ts +63 -0
- package/dist/Tree/index.d.ts +262 -0
- package/dist/Tree/index.js +7 -0
- package/dist/icons/ChevronDoubleLeft.torp +19 -0
- package/dist/icons/ChevronDoubleRight.torp +19 -0
- package/dist/icons/index.d.ts +61 -1
- package/dist/icons/index.js +17 -58
- package/dist/loader-DEeG5vFY.js +44 -0
- package/dist/loader-DEeG5vFY.js.map +1 -0
- package/dist/motion/index.d.ts +12 -8
- package/dist/motion/index.d.ts.map +1 -0
- package/dist/motion/index.js +72 -88
- package/dist/motion/index.js.map +1 -1
- package/dist/mount/draggable.ts +63 -0
- package/dist/mount/dropTarget.ts +108 -0
- package/dist/mount/hoverTrigger.ts +1 -1
- package/dist/utils/$handle.ts +23 -0
- package/dist/utils/LoadedItems.torp +47 -0
- package/dist/utils/PopoutClickTrigger.torp +99 -0
- package/dist/utils/PopoutTypes.ts +59 -12
- package/dist/utils/SubmenuPopout.torp +89 -0
- package/dist/utils/SubmenuPopoutContent.torp +87 -0
- package/dist/utils/SubmenuPopoutTrigger.torp +160 -0
- package/dist/utils/chartColors.ts +13 -13
- package/dist/utils/chartLayout.ts +143 -0
- package/dist/utils/colorUtils.ts +103 -0
- package/dist/utils/createItemGroup.ts +152 -0
- package/dist/utils/dateUtils.ts +8 -7
- package/dist/utils/documentEvents.ts +4 -4
- package/dist/utils/dragState.ts +86 -0
- package/dist/utils/focusGroup.ts +204 -0
- package/dist/utils/focusItem.ts +44 -0
- package/dist/utils/formField.ts +70 -0
- package/dist/utils/hoverOpen.ts +50 -0
- package/dist/utils/hoverReveal.ts +194 -0
- package/dist/utils/loader.ts +113 -0
- package/dist/utils/maskUtils.ts +98 -0
- package/dist/utils/popoutContent.ts +137 -0
- package/dist/utils/reorderList.ts +52 -0
- package/package.json +97 -22
- package/dist/Accordion/index.js.map +0 -1
- package/dist/Breadcrumb/index.js.map +0 -1
- package/dist/Calendar/index.js.map +0 -1
- package/dist/Charts/index.js.map +0 -1
- package/dist/Contextual/index.js.map +0 -1
- package/dist/Dialog/index.js.map +0 -1
- package/dist/Disclosure/index.js.map +0 -1
- package/dist/Drawer/index.js.map +0 -1
- package/dist/Form/index.js.map +0 -1
- package/dist/ListBox/index.js.map +0 -1
- package/dist/Menu/index.js.map +0 -1
- package/dist/MenuBar/index.js.map +0 -1
- package/dist/NavMenu/index.js.map +0 -1
- package/dist/Pagination/index.js.map +0 -1
- package/dist/SelectBox/SelectBoxInput.torp +0 -95
- package/dist/SelectBox/index.js.map +0 -1
- package/dist/TabGroup/index.js.map +0 -1
- package/dist/ToolBar/index.js.map +0 -1
- package/dist/icons/index.js.map +0 -1
- package/dist/index.d.ts +0 -19
- package/dist/metafile-esm.json +0 -1
- package/dist/motion/fade.ts +0 -16
- package/dist/motion/grow.ts +0 -23
- package/dist/motion/measure.ts +0 -28
- package/dist/motion/slide.ts +0 -45
- package/dist/mount/index.d.ts +0 -2
- package/dist/utils/index.d.ts +0 -2
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import type { Bindable, ClassValue, StyleValue } from "@torpor/view";
|
|
2
|
+
import $handle from "../utils/$handle";
|
|
3
|
+
import { type CarouselContext, CarouselContextName } from "./CarouselTypes";
|
|
4
|
+
|
|
5
|
+
interface CarouselProps {
|
|
6
|
+
/** An ID for the root element */
|
|
7
|
+
id?: string;
|
|
8
|
+
/** Classes for the root element */
|
|
9
|
+
class?: ClassValue;
|
|
10
|
+
/** Styles for the root element */
|
|
11
|
+
style?: StyleValue;
|
|
12
|
+
/** The index of the active slide */
|
|
13
|
+
value?: Bindable<number>;
|
|
14
|
+
/** Whether the next and previous controls wrap around at the ends (default true) */
|
|
15
|
+
wrap?: boolean;
|
|
16
|
+
/** An accessible label for the carousel region */
|
|
17
|
+
ariaLabel?: string;
|
|
18
|
+
/** Raised when the active slide has changed */
|
|
19
|
+
onchange?: (index: number) => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A carousel that displays a sequence of slides, which the user can move
|
|
24
|
+
* between with previous and next controls, slide indicators, or the keyboard.
|
|
25
|
+
*
|
|
26
|
+
* See [the WAI ARIA guidelines for Carousels](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/).
|
|
27
|
+
*
|
|
28
|
+
* The structure of a Carousel is:
|
|
29
|
+
*
|
|
30
|
+
* ```
|
|
31
|
+
* <Carousel ariaLabel="Featured">
|
|
32
|
+
* <CarouselPrevious />
|
|
33
|
+
* <CarouselSlide>...</CarouselSlide>
|
|
34
|
+
* <CarouselSlide>...</CarouselSlide>
|
|
35
|
+
* <CarouselNext />
|
|
36
|
+
* <CarouselIndicators />
|
|
37
|
+
* </Carousel>
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export default function Carousel($props: CarouselProps | undefined) {
|
|
41
|
+
let $state = $watch({
|
|
42
|
+
value: 0,
|
|
43
|
+
slides: [] as SlideStateLite[],
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
interface SlideStateLite {
|
|
47
|
+
index: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
$bind($state, $props, "value");
|
|
51
|
+
|
|
52
|
+
// Set the context to pass down to slides and controls
|
|
53
|
+
const context: CarouselContext = {
|
|
54
|
+
registerSlide,
|
|
55
|
+
removeSlide,
|
|
56
|
+
goToSlide,
|
|
57
|
+
nextSlide,
|
|
58
|
+
previousSlide,
|
|
59
|
+
isActive,
|
|
60
|
+
canNext,
|
|
61
|
+
canPrevious,
|
|
62
|
+
slides: () => $state.slides,
|
|
63
|
+
count: () => $state.slides.length,
|
|
64
|
+
};
|
|
65
|
+
$context[CarouselContextName] = context;
|
|
66
|
+
|
|
67
|
+
// Dispatch the change event when the active slide changes
|
|
68
|
+
$handle((first) => {
|
|
69
|
+
const value = getValue();
|
|
70
|
+
if (!first) $props?.onchange?.(value);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
function getWrap(): boolean {
|
|
74
|
+
return $props?.wrap !== false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// The clamped index that is displayed and reported to assistive tech
|
|
78
|
+
function getValue(): number {
|
|
79
|
+
const last = Math.max(0, $state.slides.length - 1);
|
|
80
|
+
return Math.min(last, Math.max(0, $state.value));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function isActive(index: number): boolean {
|
|
84
|
+
return getValue() === index;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function canNext(): boolean {
|
|
88
|
+
if ($state.slides.length < 2) return false;
|
|
89
|
+
return getWrap() || getValue() < $state.slides.length - 1;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function canPrevious(): boolean {
|
|
93
|
+
if ($state.slides.length < 2) return false;
|
|
94
|
+
return getWrap() || getValue() > 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function goToSlide(index: number) {
|
|
98
|
+
const last = Math.max(0, $state.slides.length - 1);
|
|
99
|
+
$state.value = Math.min(last, Math.max(0, index));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function nextSlide() {
|
|
103
|
+
const count = $state.slides.length;
|
|
104
|
+
if (count < 2) return;
|
|
105
|
+
if (getWrap()) {
|
|
106
|
+
goToSlide((getValue() + 1) % count);
|
|
107
|
+
} else {
|
|
108
|
+
goToSlide(getValue() + 1);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function previousSlide() {
|
|
113
|
+
const count = $state.slides.length;
|
|
114
|
+
if (count < 2) return;
|
|
115
|
+
if (getWrap()) {
|
|
116
|
+
goToSlide((getValue() - 1 + count) % count);
|
|
117
|
+
} else {
|
|
118
|
+
goToSlide(getValue() - 1);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function registerSlide(): SlideStateLite {
|
|
123
|
+
const state: SlideStateLite = $watch({ index: $state.slides.length });
|
|
124
|
+
$state.slides.push(state);
|
|
125
|
+
return state;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function removeSlide(index: number) {
|
|
129
|
+
if (index >= 0 && index < $state.slides.length) {
|
|
130
|
+
$state.slides.splice(index, 1);
|
|
131
|
+
}
|
|
132
|
+
$state.slides.forEach((slide, i) => (slide.index = i));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// The keyboard interface is the previous / next controls; arrow keys also
|
|
136
|
+
// work when focus is on the region or a slide, but never when it is on an
|
|
137
|
+
// interactive element inside the carousel
|
|
138
|
+
function handleKey(e: KeyboardEvent) {
|
|
139
|
+
const target = e.target as HTMLElement;
|
|
140
|
+
if (target.closest("button, a, input, select, textarea, [contenteditable]")) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
switch (e.key) {
|
|
144
|
+
case "ArrowRight": {
|
|
145
|
+
e.preventDefault();
|
|
146
|
+
nextSlide();
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
case "ArrowLeft": {
|
|
150
|
+
e.preventDefault();
|
|
151
|
+
previousSlide();
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
case "Home": {
|
|
155
|
+
e.preventDefault();
|
|
156
|
+
goToSlide(0);
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
case "End": {
|
|
160
|
+
e.preventDefault();
|
|
161
|
+
goToSlide($state.slides.length - 1);
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@render {
|
|
168
|
+
<div
|
|
169
|
+
{$props?.id}
|
|
170
|
+
class={["torp-carousel", $props?.class]}
|
|
171
|
+
{$props?.style}
|
|
172
|
+
role="region"
|
|
173
|
+
aria-roledescription="carousel"
|
|
174
|
+
aria-label={$props?.ariaLabel ?? "Carousel"}
|
|
175
|
+
onkeydown={handleKey}
|
|
176
|
+
>
|
|
177
|
+
<slot />
|
|
178
|
+
</div>
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { ClassValue, StyleValue } from "@torpor/view";
|
|
2
|
+
import { type CarouselContext, CarouselContextName } from "./CarouselTypes";
|
|
3
|
+
|
|
4
|
+
interface CarouselIndicatorsProps {
|
|
5
|
+
/** An ID for the root element */
|
|
6
|
+
id?: string;
|
|
7
|
+
/** Classes for the root element */
|
|
8
|
+
class?: ClassValue;
|
|
9
|
+
/** Styles for the root element */
|
|
10
|
+
style?: StyleValue;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A series of buttons in a Carousel, one per slide, that a user can press to
|
|
15
|
+
* move directly to that slide.
|
|
16
|
+
*/
|
|
17
|
+
export default function CarouselIndicators($props: CarouselIndicatorsProps | undefined) {
|
|
18
|
+
// Get stuff out of the Carousel context
|
|
19
|
+
const context = $context[CarouselContextName] as CarouselContext;
|
|
20
|
+
if (!context) {
|
|
21
|
+
throw new Error("CarouselIndicators must be contained within a Carousel");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let $state = $watch({
|
|
25
|
+
get slides() {
|
|
26
|
+
return context.slides();
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
function indicatorLabel(index: number): string {
|
|
31
|
+
return `Go to slide ${index + 1}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@render {
|
|
35
|
+
<div
|
|
36
|
+
{$props?.id}
|
|
37
|
+
class={["torp-carousel-indicators", $props?.class]}
|
|
38
|
+
{$props?.style}
|
|
39
|
+
>
|
|
40
|
+
@for (let slide of $state.slides) {
|
|
41
|
+
@key = slide.index
|
|
42
|
+
<button
|
|
43
|
+
type="button"
|
|
44
|
+
class="torp-carousel-indicator"
|
|
45
|
+
aria-label={indicatorLabel(slide.index)}
|
|
46
|
+
aria-current={context.isActive(slide.index) ? "true" : undefined}
|
|
47
|
+
data-state={context.isActive(slide.index) ? "active" : "inactive"}
|
|
48
|
+
onclick={() => context.goToSlide(slide.index)}
|
|
49
|
+
>
|
|
50
|
+
<slot item={{ index: slide.index, active: context.isActive(slide.index) }}>
|
|
51
|
+
<span aria-hidden="true" />
|
|
52
|
+
</slot>
|
|
53
|
+
</button>
|
|
54
|
+
}
|
|
55
|
+
</div>
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@style {
|
|
59
|
+
/* Headless: layout only, so the indicators sit in a row. All appearance
|
|
60
|
+
is up to the consuming theme */
|
|
61
|
+
.torp-carousel-indicators {
|
|
62
|
+
display: flex;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ClassValue, StyleValue } from "@torpor/view";
|
|
2
|
+
import ChevronRight from "../icons/ChevronRight.torp";
|
|
3
|
+
import { type CarouselContext, CarouselContextName } from "./CarouselTypes";
|
|
4
|
+
|
|
5
|
+
interface CarouselNextProps {
|
|
6
|
+
/** An ID for the root element */
|
|
7
|
+
id?: string;
|
|
8
|
+
/** Classes for the root element */
|
|
9
|
+
class?: ClassValue;
|
|
10
|
+
/** Styles for the root element */
|
|
11
|
+
style?: StyleValue;
|
|
12
|
+
/** An ARIA label for the button, for screen readers when the button contains no text */
|
|
13
|
+
ariaLabel?: string;
|
|
14
|
+
/** If set to true, the user cannot interact with this button */
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The button in a Carousel that a user can press to move to the next slide.
|
|
20
|
+
*/
|
|
21
|
+
export default function CarouselNext($props: CarouselNextProps | undefined) {
|
|
22
|
+
// Get stuff out of the Carousel context
|
|
23
|
+
const context = $context[CarouselContextName] as CarouselContext;
|
|
24
|
+
if (!context) {
|
|
25
|
+
throw new Error("CarouselNext must be contained within a Carousel");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@render {
|
|
29
|
+
<button
|
|
30
|
+
{$props?.id}
|
|
31
|
+
class={["torp-carousel-next", $props?.class]}
|
|
32
|
+
{$props?.style}
|
|
33
|
+
type="button"
|
|
34
|
+
aria-label={$props?.ariaLabel ?? "Next slide"}
|
|
35
|
+
disabled={$props?.disabled || !context.canNext()}
|
|
36
|
+
onclick={() => context.nextSlide()}
|
|
37
|
+
>
|
|
38
|
+
<slot>
|
|
39
|
+
<ChevronRight />
|
|
40
|
+
</slot>
|
|
41
|
+
</button>
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ClassValue, StyleValue } from "@torpor/view";
|
|
2
|
+
import ChevronLeft from "../icons/ChevronLeft.torp";
|
|
3
|
+
import { type CarouselContext, CarouselContextName } from "./CarouselTypes";
|
|
4
|
+
|
|
5
|
+
interface CarouselPreviousProps {
|
|
6
|
+
/** An ID for the root element */
|
|
7
|
+
id?: string;
|
|
8
|
+
/** Classes for the root element */
|
|
9
|
+
class?: ClassValue;
|
|
10
|
+
/** Styles for the root element */
|
|
11
|
+
style?: StyleValue;
|
|
12
|
+
/** An ARIA label for the button, for screen readers when the button contains no text */
|
|
13
|
+
ariaLabel?: string;
|
|
14
|
+
/** If set to true, the user cannot interact with this button */
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The button in a Carousel that a user can press to move to the previous
|
|
20
|
+
* slide.
|
|
21
|
+
*/
|
|
22
|
+
export default function CarouselPrevious($props: CarouselPreviousProps | undefined) {
|
|
23
|
+
// Get stuff out of the Carousel context
|
|
24
|
+
const context = $context[CarouselContextName] as CarouselContext;
|
|
25
|
+
if (!context) {
|
|
26
|
+
throw new Error("CarouselPrevious must be contained within a Carousel");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@render {
|
|
30
|
+
<button
|
|
31
|
+
{$props?.id}
|
|
32
|
+
class={["torp-carousel-previous", $props?.class]}
|
|
33
|
+
{$props?.style}
|
|
34
|
+
type="button"
|
|
35
|
+
aria-label={$props?.ariaLabel ?? "Previous slide"}
|
|
36
|
+
disabled={$props?.disabled || !context.canPrevious()}
|
|
37
|
+
onclick={() => context.previousSlide()}
|
|
38
|
+
>
|
|
39
|
+
<slot>
|
|
40
|
+
<ChevronLeft />
|
|
41
|
+
</slot>
|
|
42
|
+
</button>
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { ClassValue, StyleValue } from "@torpor/view";
|
|
2
|
+
import { type CarouselContext, CarouselContextName } from "./CarouselTypes";
|
|
3
|
+
|
|
4
|
+
interface CarouselSlideProps {
|
|
5
|
+
/** An ID for the root element */
|
|
6
|
+
id?: string;
|
|
7
|
+
/** Classes for the root element */
|
|
8
|
+
class?: ClassValue;
|
|
9
|
+
/** Styles for the root element */
|
|
10
|
+
style?: StyleValue;
|
|
11
|
+
/** An accessible label for the slide; defaults to "n of m" */
|
|
12
|
+
ariaLabel?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A slide in a Carousel, only one of which is visible at a time.
|
|
17
|
+
*/
|
|
18
|
+
export default function CarouselSlide($props: CarouselSlideProps | undefined) {
|
|
19
|
+
// Get stuff out of the Carousel context
|
|
20
|
+
const context = $context[CarouselContextName] as CarouselContext;
|
|
21
|
+
if (!context) {
|
|
22
|
+
throw new Error("CarouselSlide must be contained within a Carousel");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Register this slide with the parent Carousel
|
|
26
|
+
let $state = context.registerSlide();
|
|
27
|
+
|
|
28
|
+
$run(() => {
|
|
29
|
+
return () => {
|
|
30
|
+
context.removeSlide($state.index);
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
@render {
|
|
35
|
+
<div
|
|
36
|
+
{$props?.id}
|
|
37
|
+
class={["torp-carousel-slide", $props?.class]}
|
|
38
|
+
{$props?.style}
|
|
39
|
+
role="group"
|
|
40
|
+
aria-roledescription="slide"
|
|
41
|
+
aria-label={$props?.ariaLabel ?? `${$state.index + 1} of ${context.count()}`}
|
|
42
|
+
data-state={context.isActive($state.index) ? "active" : "inactive"}
|
|
43
|
+
>
|
|
44
|
+
@if (context.isActive($state.index)) {
|
|
45
|
+
<slot />
|
|
46
|
+
}
|
|
47
|
+
</div>
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@style {
|
|
51
|
+
/* Headless: inactive slides are hidden from display and the accessibility
|
|
52
|
+
tree. All other appearance is up to the consuming theme */
|
|
53
|
+
.torp-carousel-slide[data-state="inactive"] {
|
|
54
|
+
display: none;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const CarouselContextName: unique symbol = Symbol.for("torp.Carousel");
|
|
2
|
+
|
|
3
|
+
export interface SlideState {
|
|
4
|
+
/** The index of the slide */
|
|
5
|
+
index: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface CarouselContext {
|
|
9
|
+
/** Called from a slide when it is added */
|
|
10
|
+
registerSlide: () => SlideState;
|
|
11
|
+
/** Called from a slide when it is removed */
|
|
12
|
+
removeSlide: (index: number) => void;
|
|
13
|
+
/** Moves to the slide at the given index */
|
|
14
|
+
goToSlide: (index: number) => void;
|
|
15
|
+
/** Moves to the next slide */
|
|
16
|
+
nextSlide: () => void;
|
|
17
|
+
/** Moves to the previous slide */
|
|
18
|
+
previousSlide: () => void;
|
|
19
|
+
/** Whether the slide at the given index is the active one */
|
|
20
|
+
isActive: (index: number) => boolean;
|
|
21
|
+
/** Whether the next / previous controls can move from the current slide */
|
|
22
|
+
canNext: () => boolean;
|
|
23
|
+
canPrevious: () => boolean;
|
|
24
|
+
/** The reactive list of registered slides */
|
|
25
|
+
slides: () => SlideState[];
|
|
26
|
+
/** The number of registered slides */
|
|
27
|
+
count: () => number;
|
|
28
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { type SlotRender } from "@torpor/view";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
interface CarouselProps {
|
|
5
|
+
/** An ID for the root element */
|
|
6
|
+
id?: string;
|
|
7
|
+
/** Classes for the root element */
|
|
8
|
+
class?: ClassValue;
|
|
9
|
+
/** Styles for the root element */
|
|
10
|
+
style?: StyleValue;
|
|
11
|
+
/** The index of the active slide */
|
|
12
|
+
value?: Bindable<number>;
|
|
13
|
+
/** Whether the next and previous controls wrap around at the ends (default true) */
|
|
14
|
+
wrap?: boolean;
|
|
15
|
+
/** An accessible label for the carousel region */
|
|
16
|
+
ariaLabel?: string;
|
|
17
|
+
/** Raised when the active slide has changed */
|
|
18
|
+
onchange?: (index: number) => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A carousel that displays a sequence of slides, which the user can move
|
|
23
|
+
* between with previous and next controls, slide indicators, or the keyboard.
|
|
24
|
+
*
|
|
25
|
+
* See [the WAI ARIA guidelines for Carousels](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/).
|
|
26
|
+
*
|
|
27
|
+
* The structure of a Carousel is:
|
|
28
|
+
*
|
|
29
|
+
* ```
|
|
30
|
+
* <Carousel ariaLabel="Featured">
|
|
31
|
+
* <CarouselPrevious />
|
|
32
|
+
* <CarouselSlide>...</CarouselSlide>
|
|
33
|
+
* <CarouselSlide>...</CarouselSlide>
|
|
34
|
+
* <CarouselNext />
|
|
35
|
+
* <CarouselIndicators />
|
|
36
|
+
* </Carousel>
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
declare function Carousel(
|
|
40
|
+
$parent: ParentNode,
|
|
41
|
+
$anchor: Node | null,
|
|
42
|
+
$props: CarouselProps | undefined,
|
|
43
|
+
$context?: Record<PropertyKey, any>,
|
|
44
|
+
$slots?: Record<string, SlotRender>,
|
|
45
|
+
): void;
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
interface CarouselIndicatorsProps {
|
|
50
|
+
/** An ID for the root element */
|
|
51
|
+
id?: string;
|
|
52
|
+
/** Classes for the root element */
|
|
53
|
+
class?: ClassValue;
|
|
54
|
+
/** Styles for the root element */
|
|
55
|
+
style?: StyleValue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* A series of buttons in a Carousel, one per slide, that a user can press to
|
|
60
|
+
* move directly to that slide.
|
|
61
|
+
*/
|
|
62
|
+
declare function CarouselIndicators(
|
|
63
|
+
$parent: ParentNode,
|
|
64
|
+
$anchor: Node | null,
|
|
65
|
+
$props: CarouselIndicatorsProps | undefined,
|
|
66
|
+
$context?: Record<PropertyKey, any>,
|
|
67
|
+
$slots?: Record<string, SlotRender>,
|
|
68
|
+
): void;
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
interface CarouselNextProps {
|
|
73
|
+
/** An ID for the root element */
|
|
74
|
+
id?: string;
|
|
75
|
+
/** Classes for the root element */
|
|
76
|
+
class?: ClassValue;
|
|
77
|
+
/** Styles for the root element */
|
|
78
|
+
style?: StyleValue;
|
|
79
|
+
/** An ARIA label for the button, for screen readers when the button contains no text */
|
|
80
|
+
ariaLabel?: string;
|
|
81
|
+
/** If set to true, the user cannot interact with this button */
|
|
82
|
+
disabled?: boolean;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The button in a Carousel that a user can press to move to the next slide.
|
|
87
|
+
*/
|
|
88
|
+
declare function CarouselNext(
|
|
89
|
+
$parent: ParentNode,
|
|
90
|
+
$anchor: Node | null,
|
|
91
|
+
$props: CarouselNextProps | undefined,
|
|
92
|
+
$context?: Record<PropertyKey, any>,
|
|
93
|
+
$slots?: Record<string, SlotRender>,
|
|
94
|
+
): void;
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
interface CarouselPreviousProps {
|
|
99
|
+
/** An ID for the root element */
|
|
100
|
+
id?: string;
|
|
101
|
+
/** Classes for the root element */
|
|
102
|
+
class?: ClassValue;
|
|
103
|
+
/** Styles for the root element */
|
|
104
|
+
style?: StyleValue;
|
|
105
|
+
/** An ARIA label for the button, for screen readers when the button contains no text */
|
|
106
|
+
ariaLabel?: string;
|
|
107
|
+
/** If set to true, the user cannot interact with this button */
|
|
108
|
+
disabled?: boolean;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The button in a Carousel that a user can press to move to the previous
|
|
113
|
+
* slide.
|
|
114
|
+
*/
|
|
115
|
+
declare function CarouselPrevious(
|
|
116
|
+
$parent: ParentNode,
|
|
117
|
+
$anchor: Node | null,
|
|
118
|
+
$props: CarouselPreviousProps | undefined,
|
|
119
|
+
$context?: Record<PropertyKey, any>,
|
|
120
|
+
$slots?: Record<string, SlotRender>,
|
|
121
|
+
): void;
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
interface CarouselSlideProps {
|
|
126
|
+
/** An ID for the root element */
|
|
127
|
+
id?: string;
|
|
128
|
+
/** Classes for the root element */
|
|
129
|
+
class?: ClassValue;
|
|
130
|
+
/** Styles for the root element */
|
|
131
|
+
style?: StyleValue;
|
|
132
|
+
/** An accessible label for the slide; defaults to "n of m" */
|
|
133
|
+
ariaLabel?: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* A slide in a Carousel, only one of which is visible at a time.
|
|
138
|
+
*/
|
|
139
|
+
declare function CarouselSlide(
|
|
140
|
+
$parent: ParentNode,
|
|
141
|
+
$anchor: Node | null,
|
|
142
|
+
$props: CarouselSlideProps | undefined,
|
|
143
|
+
$context?: Record<PropertyKey, any>,
|
|
144
|
+
$slots?: Record<string, SlotRender>,
|
|
145
|
+
): void;
|
|
146
|
+
|
|
147
|
+
export { Carousel, CarouselIndicators, CarouselNext, CarouselPrevious, CarouselSlide };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import Carousel from "./Carousel.torp";
|
|
2
|
+
import CarouselIndicators from "./CarouselIndicators.torp";
|
|
3
|
+
import CarouselNext from "./CarouselNext.torp";
|
|
4
|
+
import CarouselPrevious from "./CarouselPrevious.torp";
|
|
5
|
+
import CarouselSlide from "./CarouselSlide.torp";
|
|
6
|
+
export { Carousel, CarouselIndicators, CarouselNext, CarouselPrevious, CarouselSlide };
|