flowbite-svelte 1.28.3 → 1.29.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/command-palette/CommandPalette.svelte +1 -1
- package/dist/command-palette/CommandPalette.svelte.d.ts +1 -1
- package/dist/kanban/KanbanCard.svelte +1 -1
- package/dist/kanban/KanbanCard.svelte.d.ts +1 -1
- package/dist/scroll-spy/ScrollSpy.svelte +1 -1
- package/dist/scroll-spy/ScrollSpy.svelte.d.ts +1 -1
- package/dist/split-pane/Divider.svelte +1 -1
- package/dist/split-pane/Divider.svelte.d.ts +1 -1
- package/dist/split-pane/Pane.svelte +1 -1
- package/dist/split-pane/Pane.svelte.d.ts +1 -1
- package/dist/split-pane/SplitPane.svelte +1 -1
- package/dist/split-pane/SplitPane.svelte.d.ts +1 -1
- package/dist/stepper/BreadcrumbStepper.svelte +118 -33
- package/dist/stepper/BreadcrumbStepper.svelte.d.ts +6 -3
- package/dist/stepper/CheckmarkIcon.svelte +92 -0
- package/dist/stepper/CheckmarkIcon.svelte.d.ts +18 -0
- package/dist/stepper/DetailedStepper.svelte +133 -27
- package/dist/stepper/DetailedStepper.svelte.d.ts +7 -4
- package/dist/stepper/DoubleArrowIcon.svelte +34 -0
- package/dist/stepper/DoubleArrowIcon.svelte.d.ts +15 -0
- package/dist/stepper/ProfileCardIcon.svelte +25 -0
- package/dist/stepper/ProfileCardIcon.svelte.d.ts +15 -0
- package/dist/stepper/ProgressStepper.svelte +135 -34
- package/dist/stepper/ProgressStepper.svelte.d.ts +7 -4
- package/dist/stepper/Stepper.svelte +87 -33
- package/dist/stepper/Stepper.svelte.d.ts +6 -3
- package/dist/stepper/TimelineStepper.svelte +95 -35
- package/dist/stepper/TimelineStepper.svelte.d.ts +6 -3
- package/dist/stepper/VerticalStepper.svelte +91 -29
- package/dist/stepper/VerticalStepper.svelte.d.ts +6 -3
- package/dist/stepper/index.d.ts +3 -0
- package/dist/stepper/index.js +3 -0
- package/dist/stepper/theme.d.ts +6 -18
- package/dist/stepper/theme.js +18 -23
- package/dist/table/Table.svelte +1 -1
- package/dist/table/Table.svelte.d.ts +1 -1
- package/dist/table/TableBody.svelte +1 -1
- package/dist/table/TableBody.svelte.d.ts +1 -1
- package/dist/table/TableBodyCell.svelte +1 -1
- package/dist/table/TableBodyCell.svelte.d.ts +1 -1
- package/dist/table/TableBodyRow.svelte +1 -1
- package/dist/table/TableBodyRow.svelte.d.ts +1 -1
- package/dist/table/TableHead.svelte +1 -1
- package/dist/table/TableHead.svelte.d.ts +1 -1
- package/dist/table/TableHeadCell.svelte +1 -1
- package/dist/table/TableHeadCell.svelte.d.ts +1 -1
- package/dist/table/TableSearch.svelte +1 -1
- package/dist/table/TableSearch.svelte.d.ts +1 -1
- package/dist/tabs/TabItem.svelte +1 -1
- package/dist/tabs/TabItem.svelte.d.ts +1 -1
- package/dist/tabs/Tabs.svelte +1 -1
- package/dist/tabs/Tabs.svelte.d.ts +1 -1
- package/dist/timeline/Activity.svelte +1 -1
- package/dist/timeline/Activity.svelte.d.ts +1 -1
- package/dist/timeline/ActivityItem.svelte +1 -1
- package/dist/timeline/ActivityItem.svelte.d.ts +1 -1
- package/dist/timeline/Group.svelte +1 -1
- package/dist/timeline/Group.svelte.d.ts +1 -1
- package/dist/timeline/GroupItem.svelte +1 -1
- package/dist/timeline/GroupItem.svelte.d.ts +1 -1
- package/dist/timeline/Timeline.svelte +1 -1
- package/dist/timeline/Timeline.svelte.d.ts +1 -1
- package/dist/timeline/TimelineItem.svelte +1 -1
- package/dist/timeline/TimelineItem.svelte.d.ts +1 -1
- package/dist/toast/Toast.svelte +1 -1
- package/dist/toast/Toast.svelte.d.ts +1 -1
- package/dist/toast/ToastContainer.svelte +1 -1
- package/dist/toast/ToastContainer.svelte.d.ts +1 -1
- package/dist/tooltip/Tooltip.svelte +1 -1
- package/dist/tooltip/Tooltip.svelte.d.ts +1 -1
- package/dist/types.d.ts +52 -14
- package/dist/typography/a/A.svelte +1 -1
- package/dist/typography/a/A.svelte.d.ts +1 -1
- package/dist/typography/blockquote/Blockquote.svelte +1 -1
- package/dist/typography/blockquote/Blockquote.svelte.d.ts +1 -1
- package/dist/typography/descriptionlist/DescriptionList.svelte +1 -1
- package/dist/typography/descriptionlist/DescriptionList.svelte.d.ts +1 -1
- package/dist/typography/heading/Heading.svelte +1 -1
- package/dist/typography/heading/Heading.svelte.d.ts +1 -1
- package/dist/typography/img/Img.svelte +1 -1
- package/dist/typography/img/Img.svelte.d.ts +1 -1
- package/dist/typography/layout/Layout.svelte +1 -1
- package/dist/typography/layout/Layout.svelte.d.ts +1 -1
- package/dist/typography/list/Li.svelte +1 -1
- package/dist/typography/list/Li.svelte.d.ts +1 -1
- package/dist/typography/list/List.svelte +1 -1
- package/dist/typography/list/List.svelte.d.ts +1 -1
- package/dist/typography/list/theme.js +1 -1
- package/dist/typography/mark/Mark.svelte +1 -1
- package/dist/typography/mark/Mark.svelte.d.ts +1 -1
- package/dist/typography/paragraph/P.svelte +1 -1
- package/dist/typography/paragraph/P.svelte.d.ts +1 -1
- package/dist/typography/secondary/Secondary.svelte +1 -1
- package/dist/typography/secondary/Secondary.svelte.d.ts +1 -1
- package/dist/typography/span/Span.svelte +1 -1
- package/dist/typography/span/Span.svelte.d.ts +1 -1
- package/dist/utils/Arrow.svelte +1 -1
- package/dist/utils/Arrow.svelte.d.ts +1 -1
- package/dist/utils/Popper.svelte +1 -1
- package/dist/utils/Popper.svelte.d.ts +1 -1
- package/dist/video/Video.svelte +1 -1
- package/dist/video/Video.svelte.d.ts +1 -1
- package/package.json +15 -3
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { SVGAttributes } from "svelte/elements";
|
|
3
|
+
|
|
4
|
+
interface Props extends SVGAttributes<SVGSVGElement> {
|
|
5
|
+
class?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let { class: className, ...restProps }: Props = $props();
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<svg
|
|
12
|
+
class={className || "ms-2 h-3 w-3 sm:ms-4 rtl:rotate-180"}
|
|
13
|
+
aria-hidden="true"
|
|
14
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
15
|
+
fill="none"
|
|
16
|
+
viewBox="0 0 12 10"
|
|
17
|
+
stroke="currentColor"
|
|
18
|
+
stroke-linecap="round"
|
|
19
|
+
stroke-linejoin="round"
|
|
20
|
+
stroke-width="2"
|
|
21
|
+
{...restProps}
|
|
22
|
+
>
|
|
23
|
+
<path d="m7 9 4-4-4-4M1 9l4-4-4-4" />
|
|
24
|
+
</svg>
|
|
25
|
+
|
|
26
|
+
<!--
|
|
27
|
+
@component
|
|
28
|
+
[Go to docs](https://flowbite-svelte.com/)
|
|
29
|
+
## Type
|
|
30
|
+
Props
|
|
31
|
+
## Props
|
|
32
|
+
@prop class: className
|
|
33
|
+
@prop ...restProps
|
|
34
|
+
-->
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SVGAttributes } from "svelte/elements";
|
|
2
|
+
interface Props extends SVGAttributes<SVGSVGElement> {
|
|
3
|
+
class?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* [Go to docs](https://flowbite-svelte.com/)
|
|
7
|
+
* ## Type
|
|
8
|
+
* Props
|
|
9
|
+
* ## Props
|
|
10
|
+
* @prop class: className
|
|
11
|
+
* @prop ...restProps
|
|
12
|
+
*/
|
|
13
|
+
declare const DoubleArrowIcon: import("svelte").Component<Props, {}, "">;
|
|
14
|
+
type DoubleArrowIcon = ReturnType<typeof DoubleArrowIcon>;
|
|
15
|
+
export default DoubleArrowIcon;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { SVGAttributes } from "svelte/elements";
|
|
3
|
+
|
|
4
|
+
interface Props extends SVGAttributes<SVGSVGElement> {
|
|
5
|
+
class?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let { class: className, ...restProps }: Props = $props();
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<svg class={className || "h-3.5 w-3.5 text-gray-500 dark:text-gray-400"} aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 16" {...restProps}>
|
|
12
|
+
<path
|
|
13
|
+
d="M18 0H2a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2ZM6.5 3a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5ZM3.014 13.021l.157-.625A3.427 3.427 0 0 1 6.5 9.571a3.426 3.426 0 0 1 3.322 2.805l.159.622-6.967.023ZM16 12h-3a1 1 0 0 1 0-2h3a1 1 0 0 1 0 2Zm0-3h-3a1 1 0 1 1 0-2h3a1 1 0 1 1 0 2Zm0-3h-3a1 1 0 1 1 0-2h3a1 1 0 1 1 0 2Z"
|
|
14
|
+
/>
|
|
15
|
+
</svg>
|
|
16
|
+
|
|
17
|
+
<!--
|
|
18
|
+
@component
|
|
19
|
+
[Go to docs](https://flowbite-svelte.com/)
|
|
20
|
+
## Type
|
|
21
|
+
Props
|
|
22
|
+
## Props
|
|
23
|
+
@prop class: className
|
|
24
|
+
@prop ...restProps
|
|
25
|
+
-->
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SVGAttributes } from "svelte/elements";
|
|
2
|
+
interface Props extends SVGAttributes<SVGSVGElement> {
|
|
3
|
+
class?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* [Go to docs](https://flowbite-svelte.com/)
|
|
7
|
+
* ## Type
|
|
8
|
+
* Props
|
|
9
|
+
* ## Props
|
|
10
|
+
* @prop class: className
|
|
11
|
+
* @prop ...restProps
|
|
12
|
+
*/
|
|
13
|
+
declare const ProfileCardIcon: import("svelte").Component<Props, {}, "">;
|
|
14
|
+
type ProfileCardIcon = ReturnType<typeof ProfileCardIcon>;
|
|
15
|
+
export default ProfileCardIcon;
|
|
@@ -1,64 +1,165 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { setContext } from "svelte";
|
|
3
|
+
import CheckmarkIcon from "./CheckmarkIcon.svelte";
|
|
3
4
|
import { progressStepper } from "./theme";
|
|
4
5
|
import type { ProgressStepperProps } from "../types";
|
|
5
6
|
import clsx from "clsx";
|
|
6
7
|
import { getTheme } from "../theme/themeUtils";
|
|
8
|
+
import { Tween } from "svelte/motion";
|
|
9
|
+
import { cubicOut } from "svelte/easing";
|
|
7
10
|
|
|
8
|
-
let {
|
|
11
|
+
let { steps = [], class: className, classes, current = $bindable(0), clickable = true, showCheckmarkForCompleted = true, onStepClick, ...restProps }: ProgressStepperProps = $props();
|
|
12
|
+
|
|
13
|
+
// Ensure current is within valid bounds
|
|
14
|
+
$effect(() => {
|
|
15
|
+
if (current < 0) current = 0;
|
|
16
|
+
if (current > steps.length && steps.length > 0) current = steps.length;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Animated progress with Tween
|
|
20
|
+
const animatedProgress = new Tween(0, {
|
|
21
|
+
duration: 100,
|
|
22
|
+
easing: cubicOut
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Update animated progress when current changes
|
|
26
|
+
$effect(() => {
|
|
27
|
+
if (steps.length <= 1 || current === 0) {
|
|
28
|
+
animatedProgress.target = 0;
|
|
29
|
+
} else {
|
|
30
|
+
const progressPercent = ((current - 1) / (steps.length - 1)) * 100;
|
|
31
|
+
animatedProgress.target = progressPercent;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
9
34
|
|
|
10
35
|
const theme = getTheme("progressStepper");
|
|
11
36
|
|
|
12
37
|
setContext("stepperType", "progress");
|
|
13
38
|
|
|
14
|
-
const { base, item, circle } = $derived(progressStepper());
|
|
39
|
+
const { base, item, circle, line, progressLine } = $derived(progressStepper());
|
|
40
|
+
|
|
41
|
+
// Handle step click
|
|
42
|
+
function handleStepClick(stepIndex: number) {
|
|
43
|
+
if (clickable && stepIndex < steps.length) {
|
|
44
|
+
const last = current;
|
|
45
|
+
// Convert 0-based array index to 1-based current value
|
|
46
|
+
current = stepIndex + 1;
|
|
47
|
+
|
|
48
|
+
// Call custom onStepClick if provided
|
|
49
|
+
if (onStepClick) {
|
|
50
|
+
onStepClick({ current, last });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Determine step status - reactive to current changes
|
|
56
|
+
// current = 0: no items highlighted (all pending)
|
|
57
|
+
// current = 1: first item is current
|
|
58
|
+
// current = 2: first is completed, second is current
|
|
59
|
+
function getStepStatus(stepIndex: number): "completed" | "current" | "pending" {
|
|
60
|
+
if (current === 0) {
|
|
61
|
+
return "pending";
|
|
62
|
+
}
|
|
63
|
+
if (stepIndex < current - 1) {
|
|
64
|
+
return "completed";
|
|
65
|
+
} else if (stepIndex === current - 1) {
|
|
66
|
+
return "current";
|
|
67
|
+
} else {
|
|
68
|
+
return "pending";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Calculate line positions and progress
|
|
73
|
+
// Lines should start from center of first circle and end at center of last circle
|
|
74
|
+
const lineStart = $derived(steps.length <= 1 ? "0" : `${(1 / steps.length) * 50}%`);
|
|
75
|
+
|
|
76
|
+
const lineWidth = $derived(steps.length <= 1 ? "0" : `${100 - (1 / steps.length) * 100}%`);
|
|
77
|
+
|
|
78
|
+
// Calculate progress width using animated value
|
|
79
|
+
const progressWidth = $derived(steps.length <= 1 || lineWidth === "0" ? "0" : `${(animatedProgress.current / 100) * parseFloat(lineWidth)}%`);
|
|
15
80
|
</script>
|
|
16
81
|
|
|
17
|
-
<ol class={base({ class: clsx(theme?.base, className) })} {...
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
82
|
+
<ol class={base({ class: clsx(theme?.base, className) })} {...restProps}>
|
|
83
|
+
<!-- Background line (gray) - from center of first to center of last circle -->
|
|
84
|
+
<div class={line({ class: clsx(theme?.line, classes?.line) })} style="left: {lineStart}; width: {lineWidth}" aria-hidden="true"></div>
|
|
85
|
+
|
|
86
|
+
<!-- Progress line (colored, overlays the background) -->
|
|
87
|
+
<div class={progressLine({ class: clsx(theme?.progressLine, classes?.progressLine) })} style="left: {lineStart}; width: {progressWidth}" aria-hidden="true"></div>
|
|
88
|
+
|
|
89
|
+
{#each steps as step, index (step.id)}
|
|
90
|
+
{@const status = step.status ?? getStepStatus(index)}
|
|
91
|
+
<li
|
|
92
|
+
class={item({
|
|
93
|
+
status,
|
|
94
|
+
class: clsx(theme?.item, classes?.item)
|
|
95
|
+
})}
|
|
96
|
+
>
|
|
97
|
+
{#if clickable}
|
|
98
|
+
<button
|
|
99
|
+
type="button"
|
|
100
|
+
class={circle({ status, class: clsx(theme?.circle, classes?.circle, "cursor-pointer transition-all hover:brightness-110") })}
|
|
101
|
+
onclick={() => handleStepClick(index)}
|
|
102
|
+
aria-current={status === "current" ? "step" : undefined}
|
|
103
|
+
>
|
|
104
|
+
{#if status === "completed" && showCheckmarkForCompleted}
|
|
105
|
+
<!-- Checkmark for completed steps -->
|
|
106
|
+
<CheckmarkIcon variant="tick" />
|
|
107
|
+
{:else if step.icon}
|
|
108
|
+
<!-- Show icon if provided -->
|
|
109
|
+
<step.icon class={clsx(step.iconClass) || "h-5 w-5 lg:h-6 lg:w-6"} />
|
|
110
|
+
{:else}
|
|
111
|
+
<!-- Show number for steps without icon -->
|
|
112
|
+
<span class="text-sm font-semibold">{step.id}</span>
|
|
113
|
+
{/if}
|
|
114
|
+
</button>
|
|
115
|
+
{:else}
|
|
116
|
+
<span class={circle({ status, class: clsx(theme?.circle, classes?.circle) })} aria-current={status === "current" ? "step" : undefined}>
|
|
117
|
+
{#if status === "completed" && showCheckmarkForCompleted}
|
|
118
|
+
<!-- Checkmark for completed steps -->
|
|
119
|
+
<CheckmarkIcon variant="tick" />
|
|
38
120
|
{:else if step.icon}
|
|
121
|
+
<!-- Show icon if provided -->
|
|
39
122
|
<step.icon class={clsx(step.iconClass) || "h-5 w-5 lg:h-6 lg:w-6"} />
|
|
40
123
|
{:else}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
d="M18 0H2a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2ZM6.5 3a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5ZM3.014 13.021l.157-.625A3.427 3.427 0 0 1 6.5 9.571a3.426 3.426 0 0 1 3.322 2.805l.159.622-6.967.023ZM16 12h-3a1 1 0 0 1 0-2h3a1 1 0 0 1 0 2Zm0-3h-3a1 1 0 1 1 0-2h3a1 1 0 1 1 0 2Zm0-3h-3a1 1 0 1 1 0-2h3a1 1 0 1 1 0 2Z"
|
|
44
|
-
/>
|
|
45
|
-
</svg>
|
|
124
|
+
<!-- Show number for steps without icon -->
|
|
125
|
+
<span class="text-sm font-semibold">{step.id}</span>
|
|
46
126
|
{/if}
|
|
47
127
|
</span>
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
{/
|
|
128
|
+
{/if}
|
|
129
|
+
</li>
|
|
130
|
+
{/each}
|
|
51
131
|
</ol>
|
|
52
132
|
|
|
133
|
+
<!--
|
|
134
|
+
## Features
|
|
135
|
+
- **Clickable navigation**: Click or press Enter/Space on steps to navigate
|
|
136
|
+
- **Auto status**: Automatically determines completed/current/pending status based on current index
|
|
137
|
+
- **Numbers by default**: Shows step numbers (from step.id) when no icon is provided
|
|
138
|
+
- **Custom icons**: Icons replace numbers when provided
|
|
139
|
+
- **Checkmarks**: Completed steps show checkmarks (can be disabled with showCheckmarkForCompleted={false})
|
|
140
|
+
- **Progress line**: A colored overlay line shows progress up to the current step
|
|
141
|
+
- **Accessible**: Keyboard navigation with proper ARIA attributes
|
|
142
|
+
|
|
143
|
+
## Note
|
|
144
|
+
The `current` prop is 1-based:
|
|
145
|
+
- current=0 means no step is active (all pending)
|
|
146
|
+
- current=1 means first step is active
|
|
147
|
+
- current=2 means first step is completed, second step is active
|
|
148
|
+
- etc.
|
|
149
|
+
-->
|
|
150
|
+
|
|
53
151
|
<!--
|
|
54
152
|
@component
|
|
55
153
|
[Go to docs](https://flowbite-svelte.com/)
|
|
56
154
|
## Type
|
|
57
|
-
[ProgressStepperProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#
|
|
155
|
+
[ProgressStepperProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#L1614)
|
|
58
156
|
## Props
|
|
59
|
-
@prop children
|
|
60
157
|
@prop steps = []
|
|
61
158
|
@prop class: className
|
|
62
159
|
@prop classes
|
|
63
|
-
@prop
|
|
160
|
+
@prop current = $bindable(0)
|
|
161
|
+
@prop clickable = true
|
|
162
|
+
@prop showCheckmarkForCompleted = true
|
|
163
|
+
@prop onStepClick
|
|
164
|
+
@prop ...restProps
|
|
64
165
|
-->
|
|
@@ -2,14 +2,17 @@ import type { ProgressStepperProps } from "../types";
|
|
|
2
2
|
/**
|
|
3
3
|
* [Go to docs](https://flowbite-svelte.com/)
|
|
4
4
|
* ## Type
|
|
5
|
-
* [ProgressStepperProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#
|
|
5
|
+
* [ProgressStepperProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#L1614)
|
|
6
6
|
* ## Props
|
|
7
|
-
* @prop children
|
|
8
7
|
* @prop steps = []
|
|
9
8
|
* @prop class: className
|
|
10
9
|
* @prop classes
|
|
11
|
-
* @prop
|
|
10
|
+
* @prop current = $bindable(0)
|
|
11
|
+
* @prop clickable = true
|
|
12
|
+
* @prop showCheckmarkForCompleted = true
|
|
13
|
+
* @prop onStepClick
|
|
14
|
+
* @prop ...restProps
|
|
12
15
|
*/
|
|
13
|
-
declare const ProgressStepper: import("svelte").Component<ProgressStepperProps, {}, "">;
|
|
16
|
+
declare const ProgressStepper: import("svelte").Component<ProgressStepperProps, {}, "current">;
|
|
14
17
|
type ProgressStepper = ReturnType<typeof ProgressStepper>;
|
|
15
18
|
export default ProgressStepper;
|
|
@@ -1,68 +1,122 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { setContext } from "svelte";
|
|
3
|
+
import type { StepStatus, Step } from "../types";
|
|
4
|
+
import CheckmarkIcon from "./CheckmarkIcon.svelte";
|
|
3
5
|
import { stepper } from "./theme";
|
|
4
6
|
import type { StepperProps } from "../types";
|
|
5
7
|
import clsx from "clsx";
|
|
6
8
|
import { getTheme } from "../theme/themeUtils";
|
|
7
9
|
|
|
8
|
-
let {
|
|
10
|
+
let { steps = [], class: className, classes, current = $bindable(1), clickable = true, showCheckmarkForCompleted = true, onStepClick, ...restProps }: StepperProps = $props();
|
|
11
|
+
|
|
12
|
+
// Ensure current is within valid bounds
|
|
13
|
+
$effect(() => {
|
|
14
|
+
if (current < 0) current = 0;
|
|
15
|
+
if (current > steps.length && steps.length > 0) current = steps.length;
|
|
16
|
+
});
|
|
9
17
|
|
|
10
18
|
const theme = getTheme("stepper");
|
|
11
19
|
|
|
12
20
|
setContext("stepperType", "stepper");
|
|
13
21
|
|
|
14
22
|
const { base, item, content } = $derived(stepper());
|
|
23
|
+
|
|
24
|
+
// Handle step click
|
|
25
|
+
function handleStepClick(stepIndex: number) {
|
|
26
|
+
if (clickable && stepIndex < steps.length) {
|
|
27
|
+
const last = current;
|
|
28
|
+
// Convert 0-based array index to 1-based current value
|
|
29
|
+
current = stepIndex + 1;
|
|
30
|
+
|
|
31
|
+
// Call custom onStepClick if provided
|
|
32
|
+
if (onStepClick) {
|
|
33
|
+
onStepClick({ current, last });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Determine step status - reactive to current changes
|
|
39
|
+
// current = 0: no items highlighted (all pending)
|
|
40
|
+
// current = 1: first item is current
|
|
41
|
+
// current = 2: first is completed, second is current
|
|
42
|
+
function getStepStatus(stepIndex: number): "completed" | "current" | "pending" {
|
|
43
|
+
if (current === 0) {
|
|
44
|
+
return "pending";
|
|
45
|
+
}
|
|
46
|
+
if (stepIndex < current - 1) {
|
|
47
|
+
return "completed";
|
|
48
|
+
} else if (stepIndex === current - 1) {
|
|
49
|
+
return "current";
|
|
50
|
+
} else {
|
|
51
|
+
return "pending";
|
|
52
|
+
}
|
|
53
|
+
}
|
|
15
54
|
</script>
|
|
16
55
|
|
|
56
|
+
{#snippet stepContent(step: Step, status: StepStatus, index: number)}
|
|
57
|
+
{#if status === "completed" && showCheckmarkForCompleted}
|
|
58
|
+
<CheckmarkIcon />
|
|
59
|
+
{:else if step.icon}
|
|
60
|
+
<step.icon class={clsx(step.iconClass) || "me-2.5 h-3.5 w-3.5 sm:h-4 sm:w-4"} />
|
|
61
|
+
{:else}
|
|
62
|
+
<span class="me-2">{step.id || index + 1}</span>
|
|
63
|
+
{/if}
|
|
64
|
+
{step.label}
|
|
65
|
+
{#if step.description}
|
|
66
|
+
<span class={clsx(step.descriptionClass) || "hidden sm:ms-2 sm:inline-flex"}>{step.description}</span>
|
|
67
|
+
{/if}
|
|
68
|
+
{/snippet}
|
|
69
|
+
|
|
17
70
|
<ol {...restProps} class={base({ class: clsx(theme?.base, className) })}>
|
|
18
|
-
{#
|
|
19
|
-
{@
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
71
|
+
{#each steps as step, index (step.id ?? index)}
|
|
72
|
+
{@const status = step.status ?? getStepStatus(index)}
|
|
73
|
+
<li
|
|
74
|
+
class={item({
|
|
75
|
+
status,
|
|
76
|
+
isLast: index === steps.length - 1,
|
|
77
|
+
class: clsx(theme?.item, classes?.item)
|
|
78
|
+
})}
|
|
79
|
+
>
|
|
80
|
+
{#if clickable}
|
|
81
|
+
<button
|
|
82
|
+
type="button"
|
|
83
|
+
class={content({
|
|
84
|
+
status,
|
|
85
|
+
isLast: index === steps.length - 1,
|
|
86
|
+
class: clsx(theme?.content, classes?.content, "w-full cursor-pointer text-left transition-opacity hover:opacity-75")
|
|
87
|
+
})}
|
|
88
|
+
onclick={() => handleStepClick(index)}
|
|
89
|
+
aria-current={status === "current" ? "step" : undefined}
|
|
90
|
+
>
|
|
91
|
+
{@render stepContent(step, status, index)}
|
|
92
|
+
</button>
|
|
93
|
+
{:else}
|
|
29
94
|
<span
|
|
30
95
|
class={content({
|
|
31
|
-
status
|
|
96
|
+
status,
|
|
32
97
|
isLast: index === steps.length - 1,
|
|
33
98
|
class: clsx(theme?.content, classes?.content)
|
|
34
99
|
})}
|
|
35
100
|
>
|
|
36
|
-
{
|
|
37
|
-
{#if step.icon}
|
|
38
|
-
<step.icon class={clsx(step.iconClass) || "me-2.5 h-3.5 w-3.5 sm:h-4 sm:w-4"} />
|
|
39
|
-
{:else}
|
|
40
|
-
<svg class="me-2.5 h-3.5 w-3.5 sm:h-4 sm:w-4" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
|
|
41
|
-
<path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 8.207-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L9 10.586l3.293-3.293a1 1 0 0 1 1.414 1.414Z" />
|
|
42
|
-
</svg>
|
|
43
|
-
{/if}
|
|
44
|
-
{:else}
|
|
45
|
-
<span class="me-2">{step.id || index + 1}</span>
|
|
46
|
-
{/if}
|
|
47
|
-
{step.label}
|
|
48
|
-
{#if step.description}
|
|
49
|
-
<span class={clsx(step.descriptionClass) || "hidden sm:ms-2 sm:inline-flex"}>{step.description}</span>
|
|
50
|
-
{/if}
|
|
101
|
+
{@render stepContent(step, status, index)}
|
|
51
102
|
</span>
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
{/
|
|
103
|
+
{/if}
|
|
104
|
+
</li>
|
|
105
|
+
{/each}
|
|
55
106
|
</ol>
|
|
56
107
|
|
|
57
108
|
<!--
|
|
58
109
|
@component
|
|
59
110
|
[Go to docs](https://flowbite-svelte.com/)
|
|
60
111
|
## Type
|
|
61
|
-
[StepperProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#
|
|
112
|
+
[StepperProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#L1598)
|
|
62
113
|
## Props
|
|
63
|
-
@prop children
|
|
64
114
|
@prop steps = []
|
|
65
115
|
@prop class: className
|
|
66
116
|
@prop classes
|
|
117
|
+
@prop current = $bindable(1)
|
|
118
|
+
@prop clickable = true
|
|
119
|
+
@prop showCheckmarkForCompleted = true
|
|
120
|
+
@prop onStepClick
|
|
67
121
|
@prop ...restProps
|
|
68
122
|
-->
|
|
@@ -2,14 +2,17 @@ import type { StepperProps } from "../types";
|
|
|
2
2
|
/**
|
|
3
3
|
* [Go to docs](https://flowbite-svelte.com/)
|
|
4
4
|
* ## Type
|
|
5
|
-
* [StepperProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#
|
|
5
|
+
* [StepperProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#L1598)
|
|
6
6
|
* ## Props
|
|
7
|
-
* @prop children
|
|
8
7
|
* @prop steps = []
|
|
9
8
|
* @prop class: className
|
|
10
9
|
* @prop classes
|
|
10
|
+
* @prop current = $bindable(1)
|
|
11
|
+
* @prop clickable = true
|
|
12
|
+
* @prop showCheckmarkForCompleted = true
|
|
13
|
+
* @prop onStepClick
|
|
11
14
|
* @prop ...restProps
|
|
12
15
|
*/
|
|
13
|
-
declare const Stepper: import("svelte").Component<StepperProps, {}, "">;
|
|
16
|
+
declare const Stepper: import("svelte").Component<StepperProps, {}, "current">;
|
|
14
17
|
type Stepper = ReturnType<typeof Stepper>;
|
|
15
18
|
export default Stepper;
|
|
@@ -1,65 +1,125 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { setContext } from "svelte";
|
|
3
|
+
import type { StepStatus, TimelineStep } from "../types";
|
|
4
|
+
import CheckmarkIcon from "./CheckmarkIcon.svelte";
|
|
5
|
+
import ProfileCardIcon from "./ProfileCardIcon.svelte";
|
|
3
6
|
import { timelineStepper } from "./theme";
|
|
4
7
|
import type { TimelineStepperProps } from "../types";
|
|
5
8
|
import clsx from "clsx";
|
|
6
9
|
import { getTheme } from "../theme/themeUtils";
|
|
7
10
|
|
|
8
|
-
let {
|
|
11
|
+
let { steps = [], class: className, classes, contentClass, current = $bindable(1), clickable = true, showCheckmarkForCompleted = true, onStepClick, ...restProps }: TimelineStepperProps = $props();
|
|
12
|
+
|
|
13
|
+
// Ensure current is within valid bounds
|
|
14
|
+
$effect(() => {
|
|
15
|
+
if (current < 0) current = 0;
|
|
16
|
+
if (current > steps.length && steps.length > 0) current = steps.length;
|
|
17
|
+
});
|
|
9
18
|
|
|
10
19
|
const theme = getTheme("timelineStepper");
|
|
11
20
|
|
|
12
21
|
setContext("stepperType", "timeline");
|
|
13
22
|
|
|
14
23
|
const { base, item, circle } = $derived(timelineStepper());
|
|
24
|
+
|
|
25
|
+
// Handle step click
|
|
26
|
+
function handleStepClick(stepIndex: number) {
|
|
27
|
+
if (clickable && stepIndex < steps.length) {
|
|
28
|
+
const last = current;
|
|
29
|
+
// Convert 0-based array index to 1-based current value
|
|
30
|
+
current = stepIndex + 1;
|
|
31
|
+
|
|
32
|
+
// Call custom onStepClick if provided
|
|
33
|
+
if (onStepClick) {
|
|
34
|
+
onStepClick({ current, last });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Determine step status - reactive to current changes
|
|
40
|
+
function getStepStatus(stepIndex: number): "completed" | "current" | "pending" {
|
|
41
|
+
if (current === 0) {
|
|
42
|
+
return "pending";
|
|
43
|
+
}
|
|
44
|
+
if (stepIndex < current - 1) {
|
|
45
|
+
return "completed";
|
|
46
|
+
} else if (stepIndex === current - 1) {
|
|
47
|
+
return "current";
|
|
48
|
+
} else {
|
|
49
|
+
return "pending";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
15
52
|
</script>
|
|
16
53
|
|
|
54
|
+
{#snippet stepIcon(status: StepStatus, step: TimelineStep)}
|
|
55
|
+
{#if status === "completed" && showCheckmarkForCompleted}
|
|
56
|
+
<CheckmarkIcon class="h-3.5 w-3.5 text-green-500 dark:text-green-400" />
|
|
57
|
+
{:else if step.icon}
|
|
58
|
+
<step.icon class={clsx(step.iconClass) || "h-3.5 w-3.5"} />
|
|
59
|
+
{:else}
|
|
60
|
+
<ProfileCardIcon />
|
|
61
|
+
{/if}
|
|
62
|
+
{/snippet}
|
|
63
|
+
|
|
17
64
|
<ol class={base({ class: clsx(theme?.base, className) })} {...restProps}>
|
|
18
|
-
{#
|
|
19
|
-
{@
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
<path
|
|
37
|
-
d="M18 0H2a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2ZM6.5 3a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5ZM3.014 13.021l.157-.625A3.427 3.427 0 0 1 6.5 9.571a3.426 3.426 0 0 1 3.322 2.805l.159.622-6.967.023ZM16 12h-3a1 1 0 0 1 0-2h3a1 1 0 0 1 0 2Zm0-3h-3a1 1 0 1 1 0-2h3a1 1 0 1 1 0 2Zm0-3h-3a1 1 0 1 1 0-2h3a1 1 0 1 1 0 2Z"
|
|
38
|
-
/>
|
|
39
|
-
</svg>
|
|
40
|
-
{/if}
|
|
65
|
+
{#each steps as step, index (step.id)}
|
|
66
|
+
{@const status = step.status ?? getStepStatus(index)}
|
|
67
|
+
<li class={item({ isLast: index === steps.length - 1, class: clsx(theme?.item, classes?.item) })}>
|
|
68
|
+
{#if clickable}
|
|
69
|
+
<button
|
|
70
|
+
type="button"
|
|
71
|
+
class="absolute -start-4 flex h-8 w-8 cursor-pointer items-center justify-center rounded-full ring-4 ring-white transition-opacity hover:opacity-75 dark:ring-gray-900 {circle({
|
|
72
|
+
status,
|
|
73
|
+
class: clsx(theme?.circle, classes?.circle)
|
|
74
|
+
})}"
|
|
75
|
+
onclick={() => handleStepClick(index)}
|
|
76
|
+
aria-current={status === "current" ? "step" : undefined}
|
|
77
|
+
>
|
|
78
|
+
{@render stepIcon(status, step)}
|
|
79
|
+
</button>
|
|
80
|
+
{:else}
|
|
81
|
+
<span class={circle({ status, class: clsx(theme?.circle, classes?.circle) })} aria-current={status === "current" ? "step" : undefined}>
|
|
82
|
+
{@render stepIcon(status, step)}
|
|
41
83
|
</span>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
{
|
|
47
|
-
|
|
48
|
-
</
|
|
49
|
-
|
|
50
|
-
{/
|
|
84
|
+
{/if}
|
|
85
|
+
<div class={clsx(contentClass)}>
|
|
86
|
+
<h3 class="leading-tight font-medium">{step.label}</h3>
|
|
87
|
+
{#if step.description}
|
|
88
|
+
<p class="text-sm">{step.description}</p>
|
|
89
|
+
{/if}
|
|
90
|
+
</div>
|
|
91
|
+
</li>
|
|
92
|
+
{/each}
|
|
51
93
|
</ol>
|
|
52
94
|
|
|
95
|
+
<!--
|
|
96
|
+
## Features
|
|
97
|
+
- **Clickable navigation**: Click or press Enter/Space on steps to navigate
|
|
98
|
+
- **Auto status**: Automatically determines completed/current/pending status based on current index
|
|
99
|
+
- **Custom icons**: Support for custom icons on completed steps
|
|
100
|
+
- **Accessible**: Keyboard navigation with proper ARIA attributes
|
|
101
|
+
|
|
102
|
+
## Note
|
|
103
|
+
The `current` prop is 1-based:
|
|
104
|
+
- current=0 means no step is active (all pending)
|
|
105
|
+
- current=1 means first step is active
|
|
106
|
+
- current=2 means first step is completed, second step is active
|
|
107
|
+
- etc.
|
|
108
|
+
-->
|
|
109
|
+
|
|
53
110
|
<!--
|
|
54
111
|
@component
|
|
55
112
|
[Go to docs](https://flowbite-svelte.com/)
|
|
56
113
|
## Type
|
|
57
|
-
[TimelineStepperProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#
|
|
114
|
+
[TimelineStepperProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#L1687)
|
|
58
115
|
## Props
|
|
59
|
-
@prop children
|
|
60
116
|
@prop steps = []
|
|
61
117
|
@prop class: className
|
|
62
118
|
@prop classes
|
|
63
119
|
@prop contentClass
|
|
120
|
+
@prop current = $bindable(1)
|
|
121
|
+
@prop clickable = true
|
|
122
|
+
@prop showCheckmarkForCompleted = true
|
|
123
|
+
@prop onStepClick
|
|
64
124
|
@prop ...restProps
|
|
65
125
|
-->
|