svelora 3.0.1 → 3.0.2

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.
Files changed (107) hide show
  1. package/dist/Accordion/Accordion.svelte +66 -97
  2. package/dist/Alert/Alert.svelte +39 -64
  3. package/dist/Alert/Alert.svelte.d.ts +1 -1
  4. package/dist/Avatar/Avatar.svelte +35 -75
  5. package/dist/AvatarGroup/AvatarGroup.svelte +38 -55
  6. package/dist/Badge/Badge.svelte +28 -50
  7. package/dist/Banner/Banner.svelte +46 -41
  8. package/dist/Banner/Banner.svelte.d.ts +1 -1
  9. package/dist/Breadcrumb/Breadcrumb.svelte +32 -26
  10. package/dist/Button/Button.svelte +70 -138
  11. package/dist/Calendar/Calendar.svelte +94 -157
  12. package/dist/Calendar/Calendar.svelte.d.ts +1 -1
  13. package/dist/Card/Card.svelte +18 -31
  14. package/dist/Carousel/Carousel.svelte +118 -173
  15. package/dist/Checkbox/Checkbox.svelte +52 -97
  16. package/dist/CheckboxGroup/CheckboxGroup.svelte +62 -107
  17. package/dist/CheckboxGroup/CheckboxGroup.svelte.d.ts +1 -1
  18. package/dist/Chip/Chip.svelte +22 -34
  19. package/dist/CodeBlock/CodeBlock.svelte +42 -59
  20. package/dist/Collapsible/Collapsible.svelte +22 -38
  21. package/dist/Collapsible/Collapsible.svelte.d.ts +1 -1
  22. package/dist/Collapsible/CollapsibleTestWrapper.svelte +2 -5
  23. package/dist/Collapsible/CollapsibleTestWrapper.svelte.d.ts +1 -1
  24. package/dist/Command/Command.svelte +40 -77
  25. package/dist/Command/Command.svelte.d.ts +1 -1
  26. package/dist/Command/CommandTestWrapper.svelte +2 -10
  27. package/dist/Command/CommandTestWrapper.svelte.d.ts +1 -1
  28. package/dist/Container/Container.svelte +11 -14
  29. package/dist/ContextMenu/ContextMenu.svelte +51 -114
  30. package/dist/ContextMenu/ContextMenu.svelte.d.ts +1 -1
  31. package/dist/Drawer/Drawer.svelte +72 -110
  32. package/dist/Drawer/DrawerTriggerTestWrapper.svelte +1 -2
  33. package/dist/DropdownMenu/DropdownMenu.svelte +63 -124
  34. package/dist/DropdownMenu/DropdownMenu.svelte.d.ts +1 -1
  35. package/dist/DropdownMenu/DropdownMenuTriggerTestWrapper.svelte +2 -5
  36. package/dist/Editor/Editor.svelte +441 -576
  37. package/dist/Editor/Editor.svelte.d.ts +1 -1
  38. package/dist/Editor/EditorUrlPrompt.svelte +40 -53
  39. package/dist/Editor/SlashPopup.svelte +12 -24
  40. package/dist/Empty/Empty.svelte +32 -63
  41. package/dist/FieldGroup/FieldGroup.svelte +23 -38
  42. package/dist/FileUpload/FileUpload.svelte +242 -320
  43. package/dist/FileUpload/FileUpload.svelte.d.ts +1 -1
  44. package/dist/Fonts/Fonts.svelte +15 -37
  45. package/dist/Form/Form.svelte +112 -170
  46. package/dist/FormField/FormField.svelte +102 -135
  47. package/dist/Icon/Icon.svelte +7 -32
  48. package/dist/Input/Input.svelte +71 -141
  49. package/dist/Input/Input.svelte.d.ts +2 -2
  50. package/dist/Kbd/Kbd.svelte +18 -34
  51. package/dist/Link/Link.svelte +129 -196
  52. package/dist/LocaleButton/LocaleButton.svelte +165 -0
  53. package/dist/LocaleButton/LocaleButton.svelte.d.ts +5 -0
  54. package/dist/LocaleButton/index.d.ts +2 -0
  55. package/dist/LocaleButton/index.js +1 -0
  56. package/dist/LocaleButton/locale-button.types.d.ts +182 -0
  57. package/dist/LocaleButton/locale-button.types.js +1 -0
  58. package/dist/LocaleButton/locale-button.variants.d.ts +61 -0
  59. package/dist/LocaleButton/locale-button.variants.js +34 -0
  60. package/dist/Modal/Modal.svelte +52 -106
  61. package/dist/Modal/ModalTriggerTestWrapper.svelte +1 -2
  62. package/dist/Pagination/Pagination.svelte +48 -92
  63. package/dist/Pagination/pagination.variants.d.ts +1 -1
  64. package/dist/PinInput/PinInput.svelte +57 -111
  65. package/dist/PinInput/PinInput.svelte.d.ts +1 -1
  66. package/dist/Popover/Popover.svelte +28 -61
  67. package/dist/Popover/Popover.svelte.d.ts +1 -1
  68. package/dist/Progress/Progress.svelte +75 -94
  69. package/dist/RadioGroup/RadioGroup.svelte +54 -99
  70. package/dist/RadioGroup/RadioGroup.svelte.d.ts +1 -1
  71. package/dist/Select/Select.svelte +112 -269
  72. package/dist/Select/Select.svelte.d.ts +1 -1
  73. package/dist/SelectMenu/SelectMenu.svelte +211 -409
  74. package/dist/SelectMenu/SelectMenu.svelte.d.ts +1 -1
  75. package/dist/SelectMenu/SelectMenuFormFieldTestWrapper.svelte +3 -6
  76. package/dist/Separator/Separator.svelte +29 -44
  77. package/dist/Skeleton/Skeleton.svelte +11 -23
  78. package/dist/Slideover/Slideover.svelte +52 -106
  79. package/dist/Slideover/SlideoverTriggerTestWrapper.svelte +1 -2
  80. package/dist/Slider/Slider.svelte +48 -84
  81. package/dist/Slider/Slider.svelte.d.ts +1 -1
  82. package/dist/Stepper/Stepper.svelte +139 -132
  83. package/dist/Stepper/Stepper.svelte.d.ts +1 -1
  84. package/dist/Switch/Switch.svelte +62 -98
  85. package/dist/Table/Table.svelte +232 -283
  86. package/dist/Table/table.variants.d.ts +1 -1
  87. package/dist/Tabs/Tabs.svelte +96 -129
  88. package/dist/Tabs/Tabs.svelte.d.ts +1 -1
  89. package/dist/Textarea/Textarea.svelte +90 -173
  90. package/dist/Textarea/Textarea.svelte.d.ts +1 -1
  91. package/dist/ThemeModeButton/ThemeModeButton.svelte +16 -38
  92. package/dist/Timeline/Timeline.svelte +75 -54
  93. package/dist/Toast/Toaster.svelte +8 -25
  94. package/dist/Tooltip/Tooltip.svelte +34 -66
  95. package/dist/Tooltip/Tooltip.svelte.d.ts +1 -1
  96. package/dist/Tooltip/TooltipTestWrapper.svelte +2 -5
  97. package/dist/User/User.svelte +33 -49
  98. package/dist/docs/navigation.js +6 -0
  99. package/dist/hooks/HookContextProbe.svelte +2 -4
  100. package/dist/hooks/HookContextProvider.svelte +8 -6
  101. package/dist/hooks/HookEmitProbe.svelte +8 -11
  102. package/dist/i18n.d.ts +2 -0
  103. package/dist/i18n.js +19 -0
  104. package/dist/index.d.ts +1 -0
  105. package/dist/index.js +1 -0
  106. package/dist/mcp/svelora-docs.data.json +4 -2
  107. package/package.json +16 -8
@@ -1,162 +1,99 @@
1
- <script lang="ts" module>import type { CalendarMultipleProps, CalendarProps, CalendarRangeProps, CalendarSingleProps } from './calendar.types.js';
2
- export type Props = CalendarProps;
1
+ <script lang="ts" module>export {};
3
2
  </script>
4
3
 
5
- <script lang="ts">
6
- import { type DateValue, getLocalTimeZone, today } from '@internationalized/date'
7
- import type { Month } from 'bits-ui'
8
- import { Calendar, RangeCalendar } from 'bits-ui'
9
- import { getComponentConfig } from '../config.js'
10
- import { useFormField, useFormFieldEmit } from '../hooks/useFormField.svelte.js'
11
- import Icon from '../Icon/Icon.svelte'
12
- import { calendarDefaults, calendarVariants } from './calendar.variants.js'
13
-
14
- const config = getComponentConfig('calendar', calendarDefaults)
15
-
16
- let {
17
- ref = $bindable(null),
18
- value = $bindable(),
19
- onValueChange,
20
- placeholder = $bindable(),
21
- onPlaceholderChange,
22
- id,
23
- name,
24
- range = false,
25
- prevMonthIcon = 'lucide:chevron-left',
26
- nextMonthIcon = 'lucide:chevron-right',
27
- prevYearIcon = 'lucide:chevrons-left',
28
- nextYearIcon = 'lucide:chevrons-right',
29
- monthControls = true,
30
- yearControls = true,
31
- weekNumbers = false,
32
- preventDeselect = false,
33
- minValue,
34
- maxValue,
35
- disabled = false,
36
- pagedNavigation = false,
37
- weekStartsOn = 0,
38
- weekdayFormat = 'short',
39
- isDateDisabled,
40
- isDateUnavailable,
41
- isDateHighlightable,
42
- fixedWeeks = true,
43
- numberOfMonths = 1,
44
- calendarLabel,
45
- locale = 'en',
46
- readonly = false,
47
- disableDaysOutsideMonth = false,
48
- color = config.defaultVariants.color ?? 'primary',
49
- size = config.defaultVariants.size ?? 'md',
50
- variant = config.defaultVariants.variant ?? 'solid',
51
- ui,
52
- class: className,
53
- heading: headingSlot,
54
- day: daySlot,
55
- weekDay: weekDaySlot,
56
- ...restProps
57
- }: Props = $props()
58
-
59
- function firstDateOf(val: unknown): DateValue | undefined {
60
- if (!val) return undefined
61
- if (Array.isArray(val)) return val[0] as DateValue | undefined
62
- if (typeof val === 'object' && 'start' in val) {
63
- return (val as { start?: DateValue }).start
64
- }
65
- return val as DateValue
66
- }
67
-
68
- if (placeholder === undefined) {
69
- placeholder = firstDateOf(value) ?? today(getLocalTimeZone())
70
- }
71
-
72
- const formFieldContext = useFormField()
73
- const emit = useFormFieldEmit()
74
-
75
- const hasError = $derived(
76
- formFieldContext?.error !== undefined && formFieldContext?.error !== false
77
- )
78
- const resolvedColor = $derived(hasError ? 'error' : color)
79
- const resolvedSize = $derived(size ?? formFieldContext?.size)
80
- const resolvedId = $derived(id ?? formFieldContext?.ariaId)
81
- const resolvedName = $derived(name ?? formFieldContext?.name)
82
- const ariaDescribedBy = $derived(
83
- !formFieldContext
84
- ? undefined
85
- : hasError
86
- ? `${formFieldContext.ariaId}-error`
87
- : `${formFieldContext.ariaId}-description ${formFieldContext.ariaId}-help`
88
- )
89
-
90
- // Only Cell and Day differ between Calendar & RangeCalendar
91
- const CalCell = $derived(range ? RangeCalendar.Cell : Calendar.Cell)
92
- const CalDay = $derived(range ? RangeCalendar.Day : Calendar.Day)
93
-
94
- const variantSlots = $derived(
95
- calendarVariants({ color: resolvedColor, size: resolvedSize, variant, weekNumbers })
96
- )
97
- const classes = $derived({
98
- root: variantSlots.root({ class: [config.slots.root, className, ui?.root] }),
99
- header: variantSlots.header({ class: [config.slots.header, ui?.header] }),
100
- body: variantSlots.body({ class: [config.slots.body, ui?.body] }),
101
- heading: variantSlots.heading({ class: [config.slots.heading, ui?.heading] }),
102
- navButton: variantSlots.navButton({ class: [config.slots.navButton, ui?.navButton] }),
103
- navButtonIcon: variantSlots.navButtonIcon({
104
- class: [config.slots.navButtonIcon, ui?.navButtonIcon]
105
- }),
106
- grid: variantSlots.grid({ class: [config.slots.grid, ui?.grid] }),
107
- gridWeekDaysRow: variantSlots.gridWeekDaysRow({
108
- class: [config.slots.gridWeekDaysRow, ui?.gridWeekDaysRow]
109
- }),
110
- gridBody: variantSlots.gridBody({ class: [config.slots.gridBody, ui?.gridBody] }),
111
- gridRow: variantSlots.gridRow({ class: [config.slots.gridRow, ui?.gridRow] }),
112
- headCell: variantSlots.headCell({ class: [config.slots.headCell, ui?.headCell] }),
113
- headCellWeek: variantSlots.headCellWeek({
114
- class: [config.slots.headCellWeek, ui?.headCellWeek]
115
- }),
116
- cell: variantSlots.cell({ class: [config.slots.cell, ui?.cell] }),
117
- cellTrigger: variantSlots.cellTrigger({
118
- class: [config.slots.cellTrigger, ui?.cellTrigger]
119
- }),
120
- cellWeek: variantSlots.cellWeek({ class: [config.slots.cellWeek, ui?.cellWeek] })
121
- })
122
-
123
- function paginateYear(date: DateValue, sign: -1 | 1): DateValue {
124
- return sign === -1 ? date.subtract({ years: 1 }) : date.add({ years: 1 })
125
- }
126
-
127
- const commonProps = $derived({
128
- id: resolvedId,
129
- placeholder,
130
- onPlaceholderChange: (val: DateValue) => {
131
- placeholder = val
132
- onPlaceholderChange?.(val)
133
- },
134
- preventDeselect,
135
- minValue,
136
- maxValue,
137
- disabled,
138
- pagedNavigation,
139
- weekStartsOn,
140
- weekdayFormat,
141
- isDateDisabled,
142
- isDateUnavailable,
143
- fixedWeeks,
144
- numberOfMonths,
145
- calendarLabel,
146
- locale,
147
- readonly,
148
- disableDaysOutsideMonth,
149
- 'aria-describedby': ariaDescribedBy,
150
- 'aria-invalid': hasError ? true : undefined,
151
- 'data-name': resolvedName,
152
- onfocusin: () => emit.onFocus(),
153
- onfocusout: () => emit.onBlur()
154
- })
155
-
156
- function handleValueChange(val: unknown) {
157
- ;(onValueChange as ((value: unknown) => void) | undefined)?.(val)
158
- emit.onChange()
159
- }
4
+ <script lang="ts">import { getLocalTimeZone, today } from "@internationalized/date";
5
+ import { Calendar, RangeCalendar } from "bits-ui";
6
+ import { getComponentConfig } from "../config.js";
7
+ import { useFormField, useFormFieldEmit } from "../hooks/useFormField.svelte.js";
8
+ import Icon from "../Icon/Icon.svelte";
9
+ import { calendarDefaults, calendarVariants } from "./calendar.variants.js";
10
+ const config = getComponentConfig("calendar", calendarDefaults);
11
+ let { ref = $bindable(null), value = $bindable(), onValueChange, placeholder = $bindable(), onPlaceholderChange, id, name, range = false, prevMonthIcon = "lucide:chevron-left", nextMonthIcon = "lucide:chevron-right", prevYearIcon = "lucide:chevrons-left", nextYearIcon = "lucide:chevrons-right", monthControls = true, yearControls = true, weekNumbers = false, preventDeselect = false, minValue, maxValue, disabled = false, pagedNavigation = false, weekStartsOn = 0, weekdayFormat = "short", isDateDisabled, isDateUnavailable, isDateHighlightable, fixedWeeks = true, numberOfMonths = 1, calendarLabel, locale = "en", readonly = false, disableDaysOutsideMonth = false, color = config.defaultVariants.color ?? "primary", size = config.defaultVariants.size ?? "md", variant = config.defaultVariants.variant ?? "solid", ui, class: className, heading: headingSlot, day: daySlot, weekDay: weekDaySlot, ...restProps } = $props();
12
+ function firstDateOf(val) {
13
+ if (!val) return undefined;
14
+ if (Array.isArray(val)) return val[0];
15
+ if (typeof val === "object" && "start" in val) {
16
+ return val.start;
17
+ }
18
+ return val;
19
+ }
20
+ if (placeholder === undefined) {
21
+ placeholder = firstDateOf(value) ?? today(getLocalTimeZone());
22
+ }
23
+ const formFieldContext = useFormField();
24
+ const emit = useFormFieldEmit();
25
+ const hasError = $derived(formFieldContext?.error !== undefined && formFieldContext?.error !== false);
26
+ const resolvedColor = $derived(hasError ? "error" : color);
27
+ const resolvedSize = $derived(size ?? formFieldContext?.size);
28
+ const resolvedId = $derived(id ?? formFieldContext?.ariaId);
29
+ const resolvedName = $derived(name ?? formFieldContext?.name);
30
+ const ariaDescribedBy = $derived(!formFieldContext ? undefined : hasError ? `${formFieldContext.ariaId}-error` : `${formFieldContext.ariaId}-description ${formFieldContext.ariaId}-help`);
31
+ // Only Cell and Day differ between Calendar & RangeCalendar
32
+ const CalCell = $derived(range ? RangeCalendar.Cell : Calendar.Cell);
33
+ const CalDay = $derived(range ? RangeCalendar.Day : Calendar.Day);
34
+ const variantSlots = $derived(calendarVariants({
35
+ color: resolvedColor,
36
+ size: resolvedSize,
37
+ variant,
38
+ weekNumbers
39
+ }));
40
+ const classes = $derived({
41
+ root: variantSlots.root({ class: [
42
+ config.slots.root,
43
+ className,
44
+ ui?.root
45
+ ] }),
46
+ header: variantSlots.header({ class: [config.slots.header, ui?.header] }),
47
+ body: variantSlots.body({ class: [config.slots.body, ui?.body] }),
48
+ heading: variantSlots.heading({ class: [config.slots.heading, ui?.heading] }),
49
+ navButton: variantSlots.navButton({ class: [config.slots.navButton, ui?.navButton] }),
50
+ navButtonIcon: variantSlots.navButtonIcon({ class: [config.slots.navButtonIcon, ui?.navButtonIcon] }),
51
+ grid: variantSlots.grid({ class: [config.slots.grid, ui?.grid] }),
52
+ gridWeekDaysRow: variantSlots.gridWeekDaysRow({ class: [config.slots.gridWeekDaysRow, ui?.gridWeekDaysRow] }),
53
+ gridBody: variantSlots.gridBody({ class: [config.slots.gridBody, ui?.gridBody] }),
54
+ gridRow: variantSlots.gridRow({ class: [config.slots.gridRow, ui?.gridRow] }),
55
+ headCell: variantSlots.headCell({ class: [config.slots.headCell, ui?.headCell] }),
56
+ headCellWeek: variantSlots.headCellWeek({ class: [config.slots.headCellWeek, ui?.headCellWeek] }),
57
+ cell: variantSlots.cell({ class: [config.slots.cell, ui?.cell] }),
58
+ cellTrigger: variantSlots.cellTrigger({ class: [config.slots.cellTrigger, ui?.cellTrigger] }),
59
+ cellWeek: variantSlots.cellWeek({ class: [config.slots.cellWeek, ui?.cellWeek] })
60
+ });
61
+ function paginateYear(date, sign) {
62
+ return sign === -1 ? date.subtract({ years: 1 }) : date.add({ years: 1 });
63
+ }
64
+ const commonProps = $derived({
65
+ id: resolvedId,
66
+ placeholder,
67
+ onPlaceholderChange: (val) => {
68
+ placeholder = val;
69
+ onPlaceholderChange?.(val);
70
+ },
71
+ preventDeselect,
72
+ minValue,
73
+ maxValue,
74
+ disabled,
75
+ pagedNavigation,
76
+ weekStartsOn,
77
+ weekdayFormat,
78
+ isDateDisabled,
79
+ isDateUnavailable,
80
+ fixedWeeks,
81
+ numberOfMonths,
82
+ calendarLabel,
83
+ locale,
84
+ readonly,
85
+ disableDaysOutsideMonth,
86
+ "aria-describedby": ariaDescribedBy,
87
+ "aria-invalid": hasError ? true : undefined,
88
+ "data-name": resolvedName,
89
+ onfocusin: () => emit.onFocus(),
90
+ onfocusout: () => emit.onBlur()
91
+ });
92
+ function handleValueChange(val) {
93
+ ;
94
+ onValueChange?.(val);
95
+ emit.onChange();
96
+ }
160
97
  </script>
161
98
 
162
99
  {#snippet calendarContent(months: Month<DateValue>[], weekdays: string[])}
@@ -1,6 +1,6 @@
1
1
  import type { CalendarProps } from './calendar.types.js';
2
2
  export type Props = CalendarProps;
3
3
  import { Calendar } from 'bits-ui';
4
- declare const Calendar: import("svelte").Component<CalendarProps, {}, "value" | "ref" | "placeholder">;
4
+ declare const Calendar: import("svelte").Component<CalendarProps, {}, "ref" | "placeholder" | "value">;
5
5
  type Calendar = ReturnType<typeof Calendar>;
6
6
  export default Calendar;
@@ -1,36 +1,23 @@
1
- <script lang="ts" module>
2
- import type { CardProps } from './card.types.js'
3
-
4
- export type Props = CardProps
1
+ <script lang="ts" module>export {};
5
2
  </script>
6
3
 
7
- <script lang="ts">
8
- import { getComponentConfig } from '../config.js'
9
- import { cardDefaults, cardVariants } from './card.variants.js'
10
-
11
- const config = getComponentConfig('card', cardDefaults)
12
-
13
- let {
14
- ref = $bindable(null),
15
- as = 'div',
16
- ui,
17
- variant = config.defaultVariants.variant,
18
- class: className,
19
- header,
20
- children,
21
- footer,
22
- ...restProps
23
- }: Props = $props()
24
-
25
- const classes = $derived.by(() => {
26
- const slots = cardVariants({ variant })
27
- return {
28
- root: slots.root({ class: [config.slots.root, className, ui?.root] }),
29
- header: slots.header({ class: [config.slots.header, ui?.header] }),
30
- body: slots.body({ class: [config.slots.body, ui?.body] }),
31
- footer: slots.footer({ class: [config.slots.footer, ui?.footer] })
32
- }
33
- })
4
+ <script lang="ts">import { getComponentConfig } from "../config.js";
5
+ import { cardDefaults, cardVariants } from "./card.variants.js";
6
+ const config = getComponentConfig("card", cardDefaults);
7
+ let { ref = $bindable(null), as = "div", ui, variant = config.defaultVariants.variant, class: className, header, children, footer, ...restProps } = $props();
8
+ const classes = $derived.by(() => {
9
+ const slots = cardVariants({ variant });
10
+ return {
11
+ root: slots.root({ class: [
12
+ config.slots.root,
13
+ className,
14
+ ui?.root
15
+ ] }),
16
+ header: slots.header({ class: [config.slots.header, ui?.header] }),
17
+ body: slots.body({ class: [config.slots.body, ui?.body] }),
18
+ footer: slots.footer({ class: [config.slots.footer, ui?.footer] })
19
+ };
20
+ });
34
21
  </script>
35
22
 
36
23
  <svelte:element this={as} bind:this={ref} class={classes.root} {...restProps}>
@@ -1,178 +1,123 @@
1
- <script lang="ts" module>
2
- import type { CarouselAutoplayOptions, CarouselProps } from './carousel.types.js'
3
-
4
- export type Props<T = unknown> = CarouselProps<T>
1
+ <script lang="ts" module>export {};
5
2
  </script>
6
3
 
7
- <script lang="ts" generics="T = unknown">
8
- import type { EmblaCarouselType, EmblaOptionsType, EmblaPluginType } from 'embla-carousel'
9
- import Autoplay from 'embla-carousel-autoplay'
10
- import ClassNames from 'embla-carousel-class-names'
11
- import Fade from 'embla-carousel-fade'
12
- import useEmblaCarousel from 'embla-carousel-svelte'
13
- import { untrack } from 'svelte'
14
- import Button from '../Button/Button.svelte'
15
- import { getComponentConfig } from '../config.js'
16
- import { carouselDefaults, carouselVariants } from './carousel.variants.js'
17
-
18
- const config = getComponentConfig('carousel', carouselDefaults)
19
-
20
- let {
21
- ref = $bindable(null),
22
- api = $bindable<EmblaCarouselType | undefined>(),
23
- items,
24
- index = $bindable(0),
25
- onIndexChange,
26
- onSettle,
27
- slidesToShow = 1,
28
- loop = false,
29
- align = 'start',
30
- orientation = 'horizontal',
31
- draggable = true,
32
- dragFree = false,
33
- slidesToScroll = 1,
34
- autoplay = false,
35
- fade = false,
36
- classNames = false,
37
- breakpoints,
38
- plugins: extraPlugins,
39
- options: optionsOverride,
40
- arrows = true,
41
- dots = true,
42
- prevIcon,
43
- nextIcon,
44
- color = config.defaultVariants.color,
45
- size = config.defaultVariants.size,
46
- variant = config.defaultVariants.variant,
47
- class: className,
48
- ui,
49
- slide: slideSnippet,
50
- dot: dotSnippet,
51
- prevSlot,
52
- nextSlot,
53
- children
54
- }: Props<T> = $props()
55
-
56
- let selectedIndex = $state(0)
57
- let scrollSnaps = $state<number[]>([])
58
- let canScrollPrev = $state(false)
59
- let canScrollNext = $state(false)
60
-
61
- const resolvedPrevIcon = $derived(
62
- prevIcon ?? (orientation === 'vertical' ? 'lucide:chevron-up' : 'lucide:chevron-left')
63
- )
64
- const resolvedNextIcon = $derived(
65
- nextIcon ?? (orientation === 'vertical' ? 'lucide:chevron-down' : 'lucide:chevron-right')
66
- )
67
-
68
- function buildAutoplay(opts: CarouselAutoplayOptions) {
69
- return Autoplay({
70
- delay: opts.delay ?? 4000,
71
- defaultInteraction: opts.defaultInteraction ?? true,
72
- stopOnLastSnap: opts.stopOnLastSnap ?? false,
73
- rootNode: opts.rootNode ?? null
74
- })
75
- }
76
-
77
- const plugins = $derived.by<EmblaPluginType[]>(() => {
78
- const list: EmblaPluginType[] = []
79
- if (autoplay) list.push(buildAutoplay(typeof autoplay === 'object' ? autoplay : {}))
80
- if (fade) list.push(Fade())
81
- if (classNames) list.push(ClassNames())
82
- if (extraPlugins) list.push(...extraPlugins)
83
- return list
84
- })
85
-
86
- const emblaOptions = $derived.by<EmblaOptionsType>(() => ({
87
- loop,
88
- align,
89
- axis: orientation === 'vertical' ? 'y' : 'x',
90
- draggable,
91
- dragFree,
92
- slidesToScroll,
93
- breakpoints,
94
- ...optionsOverride
95
- }))
96
-
97
- const dotIndices = $derived(scrollSnaps.map((_, i) => i))
98
-
99
- function classListHas(cls: unknown, re: RegExp): boolean {
100
- if (typeof cls === 'string') return re.test(cls)
101
- if (Array.isArray(cls)) return cls.some((c) => classListHas(c, re))
102
- return false
103
- }
104
-
105
- const userOverridesBasis = $derived(classListHas(ui?.slide, /\bbasis-/))
106
- const containerStyle = $derived(
107
- orientation === 'vertical'
108
- ? 'display: flex; flex-direction: column; touch-action: pan-x;'
109
- : 'display: flex; flex-direction: row; touch-action: pan-y;'
110
- )
111
- const slideStyle = $derived.by(() => {
112
- if (userOverridesBasis) return undefined
113
- const minDim = orientation === 'vertical' ? 'min-height' : 'min-width'
114
- return `flex: 0 0 calc(100% / ${slidesToShow}); ${minDim}: 0;`
115
- })
116
-
117
- const variantSlots = $derived(carouselVariants({ orientation, size, color, variant }))
118
- const classes = $derived({
119
- root: variantSlots.root({ class: [config.slots.root, className, ui?.root] }),
120
- viewport: variantSlots.viewport({ class: [config.slots.viewport, ui?.viewport] }),
121
- container: variantSlots.container({ class: [config.slots.container, ui?.container] }),
122
- slide: variantSlots.slide({ class: [config.slots.slide, ui?.slide] }),
123
- arrow: variantSlots.arrow({ class: [config.slots.arrow, ui?.arrow] }),
124
- arrowPrev: variantSlots.arrowPrev({ class: [config.slots.arrowPrev, ui?.arrowPrev] }),
125
- arrowNext: variantSlots.arrowNext({ class: [config.slots.arrowNext, ui?.arrowNext] }),
126
- dots: variantSlots.dots({ class: [config.slots.dots, ui?.dots] }),
127
- dot: variantSlots.dot({ class: [config.slots.dot, ui?.dot] })
128
- })
129
-
130
- function syncFromApi(embla: EmblaCarouselType) {
131
- const newIndex = embla.selectedSnap()
132
- selectedIndex = newIndex
133
- scrollSnaps = embla.snapList()
134
- canScrollPrev = embla.canGoToPrev()
135
- canScrollNext = embla.canGoToNext()
136
- if (newIndex !== index) {
137
- index = newIndex
138
- onIndexChange?.(newIndex)
139
- }
140
- }
141
-
142
- function handleEmblaInit(event: CustomEvent<EmblaCarouselType>) {
143
- const embla = event.detail
144
- api = embla
145
- syncFromApi(embla)
146
- embla.on('select', () => syncFromApi(embla))
147
- embla.on('reinit', () => syncFromApi(embla))
148
- if (onSettle) embla.on('settle', () => onSettle(embla))
149
- }
150
-
151
- $effect(() => {
152
- if (!api) return
153
- const desired = index
154
- if (desired !== untrack(() => selectedIndex)) {
155
- api.goTo(desired)
156
- }
157
- })
158
-
159
- function scrollPrev() {
160
- if (!api) return
161
- api.goToPrev()
162
- syncFromApi(api)
163
- }
164
-
165
- function scrollNext() {
166
- if (!api) return
167
- api.goToNext()
168
- syncFromApi(api)
169
- }
170
-
171
- function scrollTo(i: number) {
172
- if (!api) return
173
- api.goTo(i)
174
- syncFromApi(api)
175
- }
4
+ <script lang="ts" generics="T = unknown">import Autoplay from "embla-carousel-autoplay";
5
+ import ClassNames from "embla-carousel-class-names";
6
+ import Fade from "embla-carousel-fade";
7
+ import useEmblaCarousel from "embla-carousel-svelte";
8
+ import { untrack } from "svelte";
9
+ import Button from "../Button/Button.svelte";
10
+ import { getComponentConfig } from "../config.js";
11
+ import { carouselDefaults, carouselVariants } from "./carousel.variants.js";
12
+ const config = getComponentConfig("carousel", carouselDefaults);
13
+ let { ref = $bindable(null), api = $bindable(), items, index = $bindable(0), onIndexChange, onSettle, slidesToShow = 1, loop = false, align = "start", orientation = "horizontal", draggable = true, dragFree = false, slidesToScroll = 1, autoplay = false, fade = false, classNames = false, breakpoints, plugins: extraPlugins, options: optionsOverride, arrows = true, dots = true, prevIcon, nextIcon, color = config.defaultVariants.color, size = config.defaultVariants.size, variant = config.defaultVariants.variant, class: className, ui, slide: slideSnippet, dot: dotSnippet, prevSlot, nextSlot, children } = $props();
14
+ let selectedIndex = $state(0);
15
+ let scrollSnaps = $state([]);
16
+ let canScrollPrev = $state(false);
17
+ let canScrollNext = $state(false);
18
+ const resolvedPrevIcon = $derived(prevIcon ?? (orientation === "vertical" ? "lucide:chevron-up" : "lucide:chevron-left"));
19
+ const resolvedNextIcon = $derived(nextIcon ?? (orientation === "vertical" ? "lucide:chevron-down" : "lucide:chevron-right"));
20
+ function buildAutoplay(opts) {
21
+ return Autoplay({
22
+ delay: opts.delay ?? 4e3,
23
+ defaultInteraction: opts.defaultInteraction ?? true,
24
+ stopOnLastSnap: opts.stopOnLastSnap ?? false,
25
+ rootNode: opts.rootNode ?? null
26
+ });
27
+ }
28
+ const plugins = $derived.by(() => {
29
+ const list = [];
30
+ if (autoplay) list.push(buildAutoplay(typeof autoplay === "object" ? autoplay : {}));
31
+ if (fade) list.push(Fade());
32
+ if (classNames) list.push(ClassNames());
33
+ if (extraPlugins) list.push(...extraPlugins);
34
+ return list;
35
+ });
36
+ const emblaOptions = $derived.by(() => ({
37
+ loop,
38
+ align,
39
+ axis: orientation === "vertical" ? "y" : "x",
40
+ draggable,
41
+ dragFree,
42
+ slidesToScroll,
43
+ breakpoints,
44
+ ...optionsOverride
45
+ }));
46
+ const dotIndices = $derived(scrollSnaps.map((_, i) => i));
47
+ function classListHas(cls, re) {
48
+ if (typeof cls === "string") return re.test(cls);
49
+ if (Array.isArray(cls)) return cls.some((c) => classListHas(c, re));
50
+ return false;
51
+ }
52
+ const userOverridesBasis = $derived(classListHas(ui?.slide, /\bbasis-/));
53
+ const containerStyle = $derived(orientation === "vertical" ? "display: flex; flex-direction: column; touch-action: pan-x;" : "display: flex; flex-direction: row; touch-action: pan-y;");
54
+ const slideStyle = $derived.by(() => {
55
+ if (userOverridesBasis) return undefined;
56
+ const minDim = orientation === "vertical" ? "min-height" : "min-width";
57
+ return `flex: 0 0 calc(100% / ${slidesToShow}); ${minDim}: 0;`;
58
+ });
59
+ const variantSlots = $derived(carouselVariants({
60
+ orientation,
61
+ size,
62
+ color,
63
+ variant
64
+ }));
65
+ const classes = $derived({
66
+ root: variantSlots.root({ class: [
67
+ config.slots.root,
68
+ className,
69
+ ui?.root
70
+ ] }),
71
+ viewport: variantSlots.viewport({ class: [config.slots.viewport, ui?.viewport] }),
72
+ container: variantSlots.container({ class: [config.slots.container, ui?.container] }),
73
+ slide: variantSlots.slide({ class: [config.slots.slide, ui?.slide] }),
74
+ arrow: variantSlots.arrow({ class: [config.slots.arrow, ui?.arrow] }),
75
+ arrowPrev: variantSlots.arrowPrev({ class: [config.slots.arrowPrev, ui?.arrowPrev] }),
76
+ arrowNext: variantSlots.arrowNext({ class: [config.slots.arrowNext, ui?.arrowNext] }),
77
+ dots: variantSlots.dots({ class: [config.slots.dots, ui?.dots] }),
78
+ dot: variantSlots.dot({ class: [config.slots.dot, ui?.dot] })
79
+ });
80
+ function syncFromApi(embla) {
81
+ const newIndex = embla.selectedSnap();
82
+ selectedIndex = newIndex;
83
+ scrollSnaps = embla.snapList();
84
+ canScrollPrev = embla.canGoToPrev();
85
+ canScrollNext = embla.canGoToNext();
86
+ if (newIndex !== index) {
87
+ index = newIndex;
88
+ onIndexChange?.(newIndex);
89
+ }
90
+ }
91
+ function handleEmblaInit(event) {
92
+ const embla = event.detail;
93
+ api = embla;
94
+ syncFromApi(embla);
95
+ embla.on("select", () => syncFromApi(embla));
96
+ embla.on("reinit", () => syncFromApi(embla));
97
+ if (onSettle) embla.on("settle", () => onSettle(embla));
98
+ }
99
+ $effect(() => {
100
+ if (!api) return;
101
+ const desired = index;
102
+ if (desired !== untrack(() => selectedIndex)) {
103
+ api.goTo(desired);
104
+ }
105
+ });
106
+ function scrollPrev() {
107
+ if (!api) return;
108
+ api.goToPrev();
109
+ syncFromApi(api);
110
+ }
111
+ function scrollNext() {
112
+ if (!api) return;
113
+ api.goToNext();
114
+ syncFromApi(api);
115
+ }
116
+ function scrollTo(i) {
117
+ if (!api) return;
118
+ api.goTo(i);
119
+ syncFromApi(api);
120
+ }
176
121
  </script>
177
122
 
178
123
  {#snippet defaultPrev()}