forked from themesberg/flowbite-svelte
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathButtonToggle.svelte
More file actions
98 lines (85 loc) · 3.31 KB
/
ButtonToggle.svelte
File metadata and controls
98 lines (85 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<script lang="ts">
import CheckIcon from "./CheckIcon.svelte";
import { buttonToggle } from "./theme";
import type { VariantProps } from "tailwind-variants";
import clsx from "clsx";
import type { ButtonToggleProps } from "$lib";
import { getTheme, warnThemeDeprecation } from "$lib/theme/themeUtils";
import { getButtonToggleContext } from "$lib/context";
import { untrack } from "svelte";
let { value, selected = false, children, iconSlot, color, class: className, iconClass, txtClass, contentClass, classes, ...restProps }: ButtonToggleProps = $props();
warnThemeDeprecation(
"ButtonToggle",
untrack(() => ({ iconClass, txtClass, contentClass })),
{ iconClass: "icon", txtClass: "text", contentClass: "content" }
);
// button(className), content, text, icon
const styling = $derived(classes ?? { icon: iconClass, text: txtClass, content: contentClass });
const theme = $derived(getTheme("buttonToggle"));
// Get context - it will be undefined if used outside ButtonToggleGroup
const ctx = getButtonToggleContext();
// Extract context values with fallbacks
const { toggleSelected, isSelected, multiSelect, size, roundedSize, ctxIconClass, ctxBtnClass } = {
toggleSelected: ctx?.toggleSelected ?? (() => {}),
isSelected: ctx?.isSelected ?? (() => false),
multiSelect: ctx?.multiSelect ?? false,
size: ctx?.size,
roundedSize: ctx?.roundedSize,
ctxIconClass: ctx?.ctxIconClass,
ctxBtnClass: ctx?.ctxBtnClass
};
// Use context color if available, otherwise use prop color, otherwise default to "primary"
const actualColor = $derived((ctx?.color ?? color ?? "primary") as VariantProps<typeof buttonToggle>["color"]);
const actualIconClass = ctxIconClass;
// Filter size to only valid buttonToggle sizes (no 'xs')
const actualSize = (size === "xs" ? "sm" : size) as VariantProps<typeof buttonToggle>["size"];
// roundedSize is already validated by type system
const actualRoundedSize = roundedSize as VariantProps<typeof buttonToggle>["roundedSize"];
function handleClick() {
toggleSelected(value);
}
const { button, content, text, icon } = $derived(buttonToggle({ selected, color: actualColor, size: actualSize }));
$effect(() => {
selected = isSelected(value);
});
</script>
<button
type="button"
class={button({ selected, color: actualColor, size: actualSize, roundedSize: actualRoundedSize, class: clsx(theme?.button, ctxBtnClass, className) })}
data-selected={selected}
onclick={handleClick}
role={multiSelect ? "checkbox" : "radio"}
aria-checked={selected}
{...restProps}
>
<div class={content({ class: clsx(theme?.content, styling.content) })}>
{#if selected}
{#if iconSlot}
{@render iconSlot()}
{:else}
<CheckIcon class={icon({ class: clsx(theme?.icon ?? actualIconClass, styling.icon) })} />
{/if}
{/if}
<span class={text({ selected, class: clsx(theme?.text, styling.text) })}>
{@render children()}
</span>
</div>
</button>
<!--
@component
[Go to docs](https://flowbite-svelte.com/)
## Type
[ButtonToggleProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#L441)
## Props
@prop value
@prop selected = false
@prop children
@prop iconSlot
@prop color
@prop class: className
@prop iconClass
@prop txtClass
@prop contentClass
@prop classes
@prop ...restProps
-->