flowbite-svelte 1.19.0 → 1.20.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.
Files changed (89) hide show
  1. package/dist/accordion/AccordionItem.svelte +15 -1
  2. package/dist/alert/Alert.svelte +15 -2
  3. package/dist/badge/Badge.svelte +19 -2
  4. package/dist/banner/Banner.svelte +16 -1
  5. package/dist/bottom-navigation/BottomNavItem.svelte +7 -1
  6. package/dist/breadcrumb/BreadcrumbItem.svelte +3 -1
  7. package/dist/carousel/Carousel.svelte +35 -4
  8. package/dist/datepicker/Datepicker.svelte +69 -6
  9. package/dist/device-mockups/Android.svelte +5 -1
  10. package/dist/device-mockups/DefaultMockup.svelte +5 -1
  11. package/dist/device-mockups/Ios.svelte +5 -1
  12. package/dist/device-mockups/Laptop.svelte +5 -1
  13. package/dist/device-mockups/Smartwatch.svelte +5 -1
  14. package/dist/device-mockups/Tablet.svelte +5 -1
  15. package/dist/dialog/Dialog.svelte +38 -7
  16. package/dist/drawer/Drawer.svelte +29 -2
  17. package/dist/forms/button-toggle/ButtonToggle.svelte +9 -1
  18. package/dist/forms/button-toggle/ButtonToggleGroup.svelte +14 -1
  19. package/dist/forms/button-toggle/CheckIcon.svelte +13 -1
  20. package/dist/forms/checkbox/Checkbox.svelte +18 -1
  21. package/dist/forms/fileupload/Fileupload.svelte +14 -1
  22. package/dist/forms/floating-label/FloatingLabelInput.svelte +48 -5
  23. package/dist/forms/input-addon/InputAddon.svelte +12 -1
  24. package/dist/forms/input-field/Input.svelte +60 -9
  25. package/dist/forms/phoneinput/PhoneInput.svelte +14 -2
  26. package/dist/forms/phoneinput/PhoneInput.svelte.d.ts +1 -1
  27. package/dist/forms/radio/Radio.svelte +14 -1
  28. package/dist/forms/search/Search.svelte +16 -1
  29. package/dist/forms/select/MultiSelect.svelte +10 -1
  30. package/dist/forms/select/Select.svelte +20 -1
  31. package/dist/forms/tags/Tags.svelte +35 -11
  32. package/dist/forms/textarea/Textarea.svelte +27 -2
  33. package/dist/forms/textarea/theme.js +3 -1
  34. package/dist/forms/timepicker/Timepicker.svelte +143 -13
  35. package/dist/index.d.ts +1 -0
  36. package/dist/index.js +1 -0
  37. package/dist/kanban/KanbanBoard.svelte +98 -0
  38. package/dist/kanban/KanbanBoard.svelte.d.ts +4 -0
  39. package/dist/kanban/KanbanCard.svelte +58 -0
  40. package/dist/kanban/KanbanCard.svelte.d.ts +16 -0
  41. package/dist/kanban/index.d.ts +3 -0
  42. package/dist/kanban/index.js +3 -0
  43. package/dist/kanban/theme.d.ts +108 -0
  44. package/dist/kanban/theme.js +43 -0
  45. package/dist/mega-menu/MegaMenu.svelte +1 -8
  46. package/dist/modal/Modal.svelte +30 -2
  47. package/dist/navbar/NavHamburger.svelte +1 -1
  48. package/dist/navbar/NavLi.svelte +3 -1
  49. package/dist/navbar/NavUl.svelte +14 -1
  50. package/dist/pagination/theme.js +4 -1
  51. package/dist/popover/Popover.svelte +13 -1
  52. package/dist/progress/Progressbar.svelte +14 -1
  53. package/dist/progress/Progressradial.svelte +28 -2
  54. package/dist/rating/AdvancedRating.svelte +5 -1
  55. package/dist/rating/CustomIcon.svelte +13 -1
  56. package/dist/rating/Heart.svelte +19 -2
  57. package/dist/rating/Review.svelte +6 -3
  58. package/dist/rating/Review.svelte.d.ts +0 -1
  59. package/dist/rating/Star.svelte +12 -1
  60. package/dist/rating/Thumbup.svelte +19 -2
  61. package/dist/sidebar/Sidebar.svelte +30 -2
  62. package/dist/sidebar/SidebarButton.svelte +5 -1
  63. package/dist/sidebar/SidebarDropdownWrapper.svelte +18 -1
  64. package/dist/skeleton/CardPlaceholder.svelte +8 -2
  65. package/dist/skeleton/ImagePlaceholder.svelte +3 -1
  66. package/dist/skeleton/TestimonialPlaceholder.svelte +5 -1
  67. package/dist/skeleton/VideoPlaceholder.svelte +3 -1
  68. package/dist/speed-dial/SpeedDial.svelte +13 -1
  69. package/dist/speed-dial/SpeedDialButton.svelte +12 -1
  70. package/dist/spinner/Spinner.svelte +8 -2
  71. package/dist/step-indicator/StepIndicator.svelte +14 -2
  72. package/dist/stepper/DetailedStepper.svelte +1 -1
  73. package/dist/stepper/ProgressStepper.svelte +3 -1
  74. package/dist/stepper/TimelineStepper.svelte +3 -1
  75. package/dist/stepper/VerticalStepper.svelte +1 -1
  76. package/dist/table/TableSearch.svelte +26 -2
  77. package/dist/theme/themeUtils.js +3 -1
  78. package/dist/theme/themes.d.ts +1 -0
  79. package/dist/theme/themes.js +1 -0
  80. package/dist/timeline/GroupItem.svelte +10 -2
  81. package/dist/timeline/TimelineItem.svelte +24 -2
  82. package/dist/toast/Toast.svelte +17 -2
  83. package/dist/tooltip/Tooltip.svelte +12 -4
  84. package/dist/types.d.ts +27 -1
  85. package/dist/typography/paragraph/P.svelte +14 -1
  86. package/dist/utils/CloseButton.svelte +10 -2
  87. package/dist/utils/Popper.svelte +38 -2
  88. package/dist/virtuallist/VirtualList.svelte +8 -1
  89. package/package.json +12 -4
@@ -13,7 +13,32 @@
13
13
  import { parse, isValid, isBefore, isAfter } from "date-fns";
14
14
  import { getTheme } from "../../theme/themeUtils";
15
15
 
16
- let { id = "time", endId = "end-time", value = $bindable("00:00"), endValue = $bindable("00:00"), min = "", max = "", required = true, disabled = false, inputColor, buttonColor = "primary", Icon, iconClass = "h-5 w-5 text-gray-500 dark:text-gray-400", type = "default", optionLabel = "Options", options = [], size = "md", divClass, inputClass, selectClass, timerangeLabel = "Choose time range", timerangeButtonLabel = "Save time", timeIntervals = [], columns = 2, onselect }: TimepickerProps = $props();
16
+ let {
17
+ id = "time",
18
+ endId = "end-time",
19
+ value = $bindable("00:00"),
20
+ endValue = $bindable("00:00"),
21
+ min = "",
22
+ max = "",
23
+ required = true,
24
+ disabled = false,
25
+ inputColor,
26
+ buttonColor = "primary",
27
+ Icon,
28
+ iconClass = "h-5 w-5 text-gray-500 dark:text-gray-400",
29
+ type = "default",
30
+ optionLabel = "Options",
31
+ options = [],
32
+ size = "md",
33
+ divClass,
34
+ inputClass,
35
+ selectClass,
36
+ timerangeLabel = "Choose time range",
37
+ timerangeButtonLabel = "Save time",
38
+ timeIntervals = [],
39
+ columns = 2,
40
+ onselect
41
+ }: TimepickerProps = $props();
17
42
 
18
43
  const theme = getTheme("timepicker");
19
44
 
@@ -22,7 +47,6 @@
22
47
 
23
48
  // State
24
49
  let selectedOption = $state("");
25
- let dropdownOpen = $state(false);
26
50
  let showTimerange = $state(false);
27
51
 
28
52
  // Helper functions using date-fns
@@ -117,7 +141,6 @@
117
141
  }
118
142
 
119
143
  function handleDropdownSelect(option: TimePickerOption): void {
120
- dropdownOpen = false;
121
144
  selectedOption = option.value;
122
145
  notifyChange();
123
146
  }
@@ -133,7 +156,6 @@
133
156
  }
134
157
 
135
158
  function applyTimerange(): void {
136
- dropdownOpen = false;
137
159
  notifyChange();
138
160
  }
139
161
 
@@ -165,7 +187,19 @@
165
187
  {#if type !== "inline-buttons"}
166
188
  <ButtonGroup {size} class={styles.buttonGroup({ class: clsx(theme?.buttonGroup, divClass) })}>
167
189
  {#if type === "default"}
168
- <Input {id} color={inputColor} type="time" {min} {max} {required} {disabled} class={styles.input({ class: clsx(styles.inputWithIcon(), theme?.input, inputClass) })} bind:value oninput={(e) => handleTimeChange(e)} onchange={(e) => handleTimeChange(e)} />
190
+ <Input
191
+ {id}
192
+ color={inputColor}
193
+ type="time"
194
+ {min}
195
+ {max}
196
+ {required}
197
+ {disabled}
198
+ class={styles.input({ class: clsx(styles.inputWithIcon(), theme?.input, inputClass) })}
199
+ bind:value
200
+ oninput={(e) => handleTimeChange(e)}
201
+ onchange={(e) => handleTimeChange(e)}
202
+ />
169
203
  <div class={styles.iconWrapper({ class: clsx(theme?.iconWrapper) })}>
170
204
  {#if Icon}
171
205
  <Icon class={iconClass} />
@@ -176,10 +210,34 @@
176
210
  {/if}
177
211
  </div>
178
212
  {:else if type === "select"}
179
- <Input {id} color={inputColor} type="time" {min} {max} {required} {disabled} class={styles.input({ class: clsx(theme?.input, inputClass) })} bind:value oninput={(e) => handleTimeChange(e)} onchange={(e) => handleTimeChange(e)} />
213
+ <Input
214
+ {id}
215
+ color={inputColor}
216
+ type="time"
217
+ {min}
218
+ {max}
219
+ {required}
220
+ {disabled}
221
+ class={styles.input({ class: clsx(theme?.input, inputClass) })}
222
+ bind:value
223
+ oninput={(e) => handleTimeChange(e)}
224
+ onchange={(e) => handleTimeChange(e)}
225
+ />
180
226
  <Select selectClass={styles.select({ class: clsx(theme?.select, selectClass) })} onchange={handleOptionSelect} items={options} value={selectedOption} />
181
227
  {:else if type === "dropdown"}
182
- <Input {id} color={inputColor} type="time" {min} {max} {required} {disabled} class={styles.input({ class: clsx(theme?.input, inputClass) })} bind:value oninput={(e) => handleTimeChange(e)} onchange={(e) => handleTimeChange(e)} />
228
+ <Input
229
+ {id}
230
+ color={inputColor}
231
+ type="time"
232
+ {min}
233
+ {max}
234
+ {required}
235
+ {disabled}
236
+ class={styles.input({ class: clsx(theme?.input, inputClass) })}
237
+ bind:value
238
+ oninput={(e) => handleTimeChange(e)}
239
+ onchange={(e) => handleTimeChange(e)}
240
+ />
183
241
  <Button color={buttonColor} class={styles.button({ class: clsx(theme?.button) })}>
184
242
  {optionLabel}
185
243
  <svg class={styles.buttonIcon({ class: clsx(theme?.buttonIcon) })} aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
@@ -195,7 +253,19 @@
195
253
  </Dropdown>
196
254
  {:else if type === "range"}
197
255
  <div class={styles.rangeInputWrapper({ class: clsx(theme?.rangeInputWrapper) })}>
198
- <Input {id} color={inputColor} type="time" {min} {max} {required} {disabled} class={styles.input({ class: clsx(theme?.rangeInput, styles.rangeInput(), inputClass) })} bind:value oninput={(e) => handleTimeChange(e)} onchange={(e) => handleTimeChange(e)} />
256
+ <Input
257
+ {id}
258
+ color={inputColor}
259
+ type="time"
260
+ {min}
261
+ {max}
262
+ {required}
263
+ {disabled}
264
+ class={styles.input({ class: clsx(theme?.rangeInput, styles.rangeInput(), inputClass) })}
265
+ bind:value
266
+ oninput={(e) => handleTimeChange(e)}
267
+ onchange={(e) => handleTimeChange(e)}
268
+ />
199
269
  <button type="button" class={styles.rangeButton({ class: clsx(theme?.rangeButton) })} onclick={() => document.getElementById(id)?.click()} aria-label="Open time picker">
200
270
  {#if Icon}
201
271
  <Icon class={iconClass} />
@@ -208,7 +278,19 @@
208
278
  </div>
209
279
  <span class={styles.rangeSeparator({ class: clsx(theme?.rangeSeparator) })}>-</span>
210
280
  <div class={styles.rangeInputWrapper({ class: clsx(theme?.rangeInputWrapper) })}>
211
- <Input id={endId} color={inputColor} type="time" {min} {max} {required} {disabled} class={styles.input({ class: clsx(styles.rangeInput(), theme?.rangeInput, inputClass) })} bind:value={endValue} oninput={(e) => handleTimeChange(e, true)} onchange={(e) => handleTimeChange(e, true)} />
281
+ <Input
282
+ id={endId}
283
+ color={inputColor}
284
+ type="time"
285
+ {min}
286
+ {max}
287
+ {required}
288
+ {disabled}
289
+ class={styles.input({ class: clsx(styles.rangeInput(), theme?.rangeInput, inputClass) })}
290
+ bind:value={endValue}
291
+ oninput={(e) => handleTimeChange(e, true)}
292
+ onchange={(e) => handleTimeChange(e, true)}
293
+ />
212
294
  <button type="button" class={styles.rangeButton({ class: clsx(theme?.rangeButton) })} onclick={() => document.getElementById(endId)?.click()} aria-label="Open end time picker">
213
295
  {#if Icon}
214
296
  <Icon class={iconClass} />
@@ -231,11 +313,35 @@
231
313
  <div class={styles.dropdownTimeRow({ class: clsx(theme?.dropdownTimeRow) })}>
232
314
  <div class={styles.dropdownTimeCol({ class: clsx(theme?.dropdownTimeCol) })}>
233
315
  <Label for={id}>Start time:</Label>
234
- <Input {id} color={inputColor} type="time" {min} {max} {required} {disabled} class={styles.dropdownTimeInput({ class: clsx(theme?.dropdownTimeInput, inputClass) })} bind:value oninput={(e) => handleTimeChange(e)} onchange={(e) => handleTimeChange(e)} />
316
+ <Input
317
+ {id}
318
+ color={inputColor}
319
+ type="time"
320
+ {min}
321
+ {max}
322
+ {required}
323
+ {disabled}
324
+ class={styles.dropdownTimeInput({ class: clsx(theme?.dropdownTimeInput, inputClass) })}
325
+ bind:value
326
+ oninput={(e) => handleTimeChange(e)}
327
+ onchange={(e) => handleTimeChange(e)}
328
+ />
235
329
  </div>
236
330
  <div class={styles.dropdownTimeCol({ class: clsx(theme?.dropdownTimeCol) })}>
237
331
  <Label for={endId}>End time:</Label>
238
- <Input id={endId} color={inputColor} type="time" {min} {max} {required} {disabled} class={styles.dropdownTimeInput({ class: clsx(theme?.dropdownTimeInput, inputClass) })} bind:value={endValue} oninput={(e) => handleTimeChange(e, true)} onchange={(e) => handleTimeChange(e, true)} />
332
+ <Input
333
+ id={endId}
334
+ color={inputColor}
335
+ type="time"
336
+ {min}
337
+ {max}
338
+ {required}
339
+ {disabled}
340
+ class={styles.dropdownTimeInput({ class: clsx(theme?.dropdownTimeInput, inputClass) })}
341
+ bind:value={endValue}
342
+ oninput={(e) => handleTimeChange(e, true)}
343
+ onchange={(e) => handleTimeChange(e, true)}
344
+ />
239
345
  </div>
240
346
  </div>
241
347
  <Button color={buttonColor} class={styles.dropdownButton({ class: clsx(theme?.dropdownButton) })} onclick={applyTimerange}>
@@ -252,11 +358,35 @@
252
358
  <div class={styles.toggleTimeRow({ class: clsx(theme?.toggleTimeRow) })}>
253
359
  <div class={styles.toggleTimeCol({ class: clsx(theme?.toggleTimeCol) })}>
254
360
  <Label for={id}>Start time:</Label>
255
- <Input {id} color={inputColor} type="time" {min} {max} {required} {disabled} class={styles.toggleTimeInput({ class: clsx(theme?.toggleTimeInput, inputClass) })} bind:value oninput={(e) => handleTimeChange(e)} onchange={(e) => handleTimeChange(e)} />
361
+ <Input
362
+ {id}
363
+ color={inputColor}
364
+ type="time"
365
+ {min}
366
+ {max}
367
+ {required}
368
+ {disabled}
369
+ class={styles.toggleTimeInput({ class: clsx(theme?.toggleTimeInput, inputClass) })}
370
+ bind:value
371
+ oninput={(e) => handleTimeChange(e)}
372
+ onchange={(e) => handleTimeChange(e)}
373
+ />
256
374
  </div>
257
375
  <div class={styles.toggleTimeCol({ class: clsx(theme?.toggleTimeCol) })}>
258
376
  <Label for={endId}>End time:</Label>
259
- <Input id={endId} color={inputColor} type="time" {min} {max} {required} {disabled} class={styles.toggleTimeInput({ class: clsx(theme?.toggleTimeInput, inputClass) })} bind:value={endValue} oninput={(e) => handleTimeChange(e, true)} onchange={(e) => handleTimeChange(e, true)} />
377
+ <Input
378
+ id={endId}
379
+ color={inputColor}
380
+ type="time"
381
+ {min}
382
+ {max}
383
+ {required}
384
+ {disabled}
385
+ class={styles.toggleTimeInput({ class: clsx(theme?.toggleTimeInput, inputClass) })}
386
+ bind:value={endValue}
387
+ oninput={(e) => handleTimeChange(e, true)}
388
+ onchange={(e) => handleTimeChange(e, true)}
389
+ />
260
390
  </div>
261
391
  </div>
262
392
  {/if}
package/dist/index.d.ts CHANGED
@@ -79,3 +79,4 @@ export * from "./video";
79
79
  export * from "./utils";
80
80
  export * from "./types";
81
81
  export * from "./virtuallist";
82
+ export * from "./kanban";
package/dist/index.js CHANGED
@@ -85,3 +85,4 @@ export * from "./utils";
85
85
  export * from "./types";
86
86
  // extend
87
87
  export * from "./virtuallist";
88
+ export * from "./kanban";
@@ -0,0 +1,98 @@
1
+ <script lang="ts">
2
+ import type { KanbanBoardProps, KanbanCardType, KanbanColumnType } from "../types";
3
+ import clsx from "clsx";
4
+ import { kanbanBoard } from "./theme";
5
+ import { getTheme } from "../theme/themeUtils";
6
+ import KanbanCard from "./KanbanCard.svelte";
7
+
8
+ let {
9
+ columns = $bindable([]),
10
+ onMove = (_card: KanbanCardType, _from: KanbanColumnType, _to: KanbanColumnType) => {},
11
+ onAddCard = (_col: KanbanColumnType) => {},
12
+ class: className,
13
+ classes,
14
+ ...restProps
15
+ }: KanbanBoardProps = $props();
16
+
17
+ const theme = getTheme("kanbanBoard");
18
+
19
+ // Changed from KanbanCard to KanbanCardType
20
+ let draggedCard = $state<KanbanCardType | null>(null);
21
+ let sourceColumnId = $state<string | number | null>(null);
22
+ let dragOverColumnId = $state<string | number | null>(null);
23
+
24
+ const styles = kanbanBoard();
25
+
26
+ // Changed parameter type from KanbanCard to KanbanCardType
27
+ function handleDragStart(card: KanbanCardType, colId: string | number) {
28
+ draggedCard = card;
29
+ sourceColumnId = colId;
30
+ }
31
+
32
+ function handleDragOver(e: DragEvent, colId: string | number) {
33
+ e.preventDefault();
34
+ dragOverColumnId = colId;
35
+ }
36
+
37
+ function handleDragLeave(e: DragEvent) {
38
+ const currentTarget = e.currentTarget as HTMLElement;
39
+ const relatedTarget = e.relatedTarget as Node | null;
40
+ if (!relatedTarget || !currentTarget.contains(relatedTarget)) {
41
+ dragOverColumnId = null;
42
+ }
43
+ }
44
+
45
+ function handleDrop(e: DragEvent, targetColId: string | number) {
46
+ e.preventDefault();
47
+ dragOverColumnId = null;
48
+
49
+ if (draggedCard === null || sourceColumnId === null) return;
50
+ if (sourceColumnId === targetColId) {
51
+ draggedCard = null;
52
+ sourceColumnId = null;
53
+ return;
54
+ }
55
+
56
+ const fromCol = columns.find((c) => c.id === sourceColumnId);
57
+ const toCol = columns.find((c) => c.id === targetColId);
58
+ if (!fromCol || !toCol) return;
59
+
60
+ fromCol.cards = fromCol.cards.filter((c) => c.id !== draggedCard!.id);
61
+ toCol.cards = [...toCol.cards, draggedCard!];
62
+
63
+ onMove(draggedCard, fromCol, toCol);
64
+
65
+ draggedCard = null;
66
+ sourceColumnId = null;
67
+ }
68
+
69
+ function handleDragEnd() {
70
+ draggedCard = null;
71
+ sourceColumnId = null;
72
+ dragOverColumnId = null;
73
+ }
74
+ </script>
75
+
76
+ <div {...restProps} class={styles.container({ class: clsx(theme?.container, className) })}>
77
+ {#each columns as col (col.id)}
78
+ <div
79
+ role="group"
80
+ aria-label={`${col.title} column drop zone`}
81
+ class={styles.column({ isDragOver: dragOverColumnId === col.id, class: clsx(theme?.column, classes?.column) })}
82
+ ondragover={(e) => handleDragOver(e, col.id)}
83
+ ondragleave={(e) => handleDragLeave(e)}
84
+ ondrop={(e) => handleDrop(e, col.id)}
85
+ style={col.color ? `border-top: 4px solid ${col.color}` : ""}
86
+ >
87
+ <h2 class={styles.columnTitle({ class: clsx(theme?.columnTitle, classes?.columnTitle) })}>{col.title}</h2>
88
+
89
+ <div class={styles.cardList({ class: clsx(theme?.cardList, classes?.cardList) })} role="list" aria-label={`${col.title} cards`}>
90
+ {#each col.cards as card (card.id)}
91
+ <KanbanCard {card} {classes} isDragging={draggedCard?.id === card.id} onDragStart={() => handleDragStart(card, col.id)} onDragEnd={handleDragEnd} />
92
+ {/each}
93
+ </div>
94
+
95
+ <button class={styles.addButton({ class: clsx(theme?.addButton, classes?.addButton) })} onclick={() => onAddCard(col)} aria-label={`Add card to ${col.title}`}>+ Add card</button>
96
+ </div>
97
+ {/each}
98
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { KanbanBoardProps } from "../types";
2
+ declare const KanbanBoard: import("svelte").Component<KanbanBoardProps, {}, "columns">;
3
+ type KanbanBoard = ReturnType<typeof KanbanBoard>;
4
+ export default KanbanBoard;
@@ -0,0 +1,58 @@
1
+ <script lang="ts">
2
+ import clsx from "clsx";
3
+ import type { KanbanCardProps } from "../types";
4
+ import { kanbanCard } from "./theme";
5
+ import { getTheme } from "../theme/themeUtils";
6
+
7
+ let { card, isDragging = false, onDragStart, onDragEnd, classes, ...restProps }: KanbanCardProps = $props();
8
+
9
+ const theme = getTheme("kanbanCard");
10
+ const styles = kanbanCard();
11
+ </script>
12
+
13
+ <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
14
+ <article
15
+ role="listitem"
16
+ draggable="true"
17
+ {...restProps}
18
+ ondragstart={(ev) => onDragStart?.(card, ev)}
19
+ ondragend={(ev) => onDragEnd?.(ev)}
20
+ tabindex="0"
21
+ aria-grabbed={isDragging}
22
+ aria-label={card.title}
23
+ class={styles.card({ isDragging, class: clsx(theme?.card, classes?.card) })}
24
+ >
25
+ <p class={styles.cardTitle({ class: clsx(theme?.cardTitle, classes?.cardTitle) })}>
26
+ {card.title}
27
+ </p>
28
+
29
+ {#if card.description}
30
+ <p class={styles.cardDescription({ class: clsx(theme?.cardDescription, classes?.cardDescription) })}>
31
+ {card.description}
32
+ </p>
33
+ {/if}
34
+
35
+ {#if card.tags?.length}
36
+ <div class={styles.cardTags({ class: clsx(theme?.cardTags, classes?.cardTags) })}>
37
+ {#each card.tags as tag, i (i)}
38
+ <span class={styles.cardTag({ class: clsx(theme?.cardTag, classes?.cardTag) })}>
39
+ {tag}
40
+ </span>
41
+ {/each}
42
+ </div>
43
+ {/if}
44
+ </article>
45
+
46
+ <!--
47
+ @component
48
+ [Go to docs](https://flowbite-svelte.com/)
49
+ ## Type
50
+ [KanbanCardProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#L2082)
51
+ ## Props
52
+ @prop card
53
+ @prop isDragging = false
54
+ @prop onDragStart
55
+ @prop onDragEnd
56
+ @prop classes
57
+ @prop ...restProps
58
+ -->
@@ -0,0 +1,16 @@
1
+ import type { KanbanCardProps } from "../types";
2
+ /**
3
+ * [Go to docs](https://flowbite-svelte.com/)
4
+ * ## Type
5
+ * [KanbanCardProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#L2082)
6
+ * ## Props
7
+ * @prop card
8
+ * @prop isDragging = false
9
+ * @prop onDragStart
10
+ * @prop onDragEnd
11
+ * @prop classes
12
+ * @prop ...restProps
13
+ */
14
+ declare const KanbanCard: import("svelte").Component<KanbanCardProps, {}, "">;
15
+ type KanbanCard = ReturnType<typeof KanbanCard>;
16
+ export default KanbanCard;
@@ -0,0 +1,3 @@
1
+ export { default as KanbanBoard } from "./KanbanBoard.svelte";
2
+ export { default as KanbanCard } from "./KanbanCard.svelte";
3
+ export { kanbanBoard } from "./theme";
@@ -0,0 +1,3 @@
1
+ export { default as KanbanBoard } from "./KanbanBoard.svelte";
2
+ export { default as KanbanCard } from "./KanbanCard.svelte";
3
+ export { kanbanBoard } from "./theme";
@@ -0,0 +1,108 @@
1
+ import { type VariantProps } from "tailwind-variants";
2
+ import type { Classes } from "../theme/themeUtils";
3
+ export type KanbanBoardVariants = VariantProps<typeof kanbanBoard> & Classes<typeof kanbanBoard>;
4
+ export type KanbanCardVariants = VariantProps<typeof kanbanCard> & Classes<typeof kanbanCard>;
5
+ export declare const kanbanBoard: import("tailwind-variants").TVReturnType<{
6
+ isDragOver: {
7
+ true: {
8
+ column: string;
9
+ };
10
+ };
11
+ isDragging: {
12
+ true: {
13
+ card: string;
14
+ };
15
+ };
16
+ }, {
17
+ container: string;
18
+ column: string;
19
+ columnTitle: string;
20
+ cardList: string;
21
+ card: string;
22
+ cardTitle: string;
23
+ cardDescription: string;
24
+ cardTags: string;
25
+ cardTag: string;
26
+ addButton: string;
27
+ }, undefined, {
28
+ isDragOver: {
29
+ true: {
30
+ column: string;
31
+ };
32
+ };
33
+ isDragging: {
34
+ true: {
35
+ card: string;
36
+ };
37
+ };
38
+ }, {
39
+ container: string;
40
+ column: string;
41
+ columnTitle: string;
42
+ cardList: string;
43
+ card: string;
44
+ cardTitle: string;
45
+ cardDescription: string;
46
+ cardTags: string;
47
+ cardTag: string;
48
+ addButton: string;
49
+ }, import("tailwind-variants").TVReturnType<{
50
+ isDragOver: {
51
+ true: {
52
+ column: string;
53
+ };
54
+ };
55
+ isDragging: {
56
+ true: {
57
+ card: string;
58
+ };
59
+ };
60
+ }, {
61
+ container: string;
62
+ column: string;
63
+ columnTitle: string;
64
+ cardList: string;
65
+ card: string;
66
+ cardTitle: string;
67
+ cardDescription: string;
68
+ cardTags: string;
69
+ cardTag: string;
70
+ addButton: string;
71
+ }, undefined, unknown, unknown, undefined>>;
72
+ export declare const kanbanCard: import("tailwind-variants").TVReturnType<{
73
+ isDragging: {
74
+ true: {
75
+ card: string;
76
+ };
77
+ };
78
+ }, {
79
+ card: string;
80
+ cardTitle: string;
81
+ cardDescription: string;
82
+ cardTags: string;
83
+ cardTag: string;
84
+ }, undefined, {
85
+ isDragging: {
86
+ true: {
87
+ card: string;
88
+ };
89
+ };
90
+ }, {
91
+ card: string;
92
+ cardTitle: string;
93
+ cardDescription: string;
94
+ cardTags: string;
95
+ cardTag: string;
96
+ }, import("tailwind-variants").TVReturnType<{
97
+ isDragging: {
98
+ true: {
99
+ card: string;
100
+ };
101
+ };
102
+ }, {
103
+ card: string;
104
+ cardTitle: string;
105
+ cardDescription: string;
106
+ cardTags: string;
107
+ cardTag: string;
108
+ }, undefined, unknown, unknown, undefined>>;
@@ -0,0 +1,43 @@
1
+ import { tv } from "tailwind-variants";
2
+ export const kanbanBoard = tv({
3
+ slots: {
4
+ container: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3 md:gap-4 p-2 md:p-4",
5
+ column: "w-full rounded-xl shadow-sm p-3 md:p-4 flex flex-col bg-surface-elevated text-surface-foreground transition-colors",
6
+ columnTitle: "text-sm md:text-base font-semibold mb-2 md:mb-3",
7
+ cardList: "flex flex-col gap-2 flex-1 min-h-[60px]",
8
+ card: "bg-surface text-surface-foreground rounded-lg p-2.5 md:p-3 shadow-sm cursor-grab active:cursor-grabbing transition-all hover:bg-surface-hover hover:shadow-md",
9
+ cardTitle: "font-medium text-sm md:text-base",
10
+ cardDescription: "text-xs md:text-sm text-muted mt-1",
11
+ cardTags: "flex flex-wrap gap-1 mt-2",
12
+ cardTag: "text-[10px] md:text-xs bg-primary/10 text-primary px-1.5 md:px-2 py-0.5 rounded-full",
13
+ addButton: "mt-2 md:mt-3 w-full bg-primary text-primary-foreground rounded-lg py-1.5 text-xs md:text-sm font-medium hover:bg-primary/90 transition-colors focus:ring-2 focus:ring-primary focus:ring-offset-2"
14
+ },
15
+ variants: {
16
+ isDragOver: {
17
+ true: {
18
+ column: "ring-2 ring-primary"
19
+ }
20
+ },
21
+ isDragging: {
22
+ true: {
23
+ card: "opacity-50"
24
+ }
25
+ }
26
+ }
27
+ });
28
+ export const kanbanCard = tv({
29
+ slots: {
30
+ card: "bg-surface text-surface-foreground rounded-lg p-2.5 md:p-3 shadow-sm cursor-grab active:cursor-grabbing transition-all hover:bg-surface-hover hover:shadow-md",
31
+ cardTitle: "font-medium text-sm md:text-base",
32
+ cardDescription: "text-xs md:text-sm text-muted mt-1",
33
+ cardTags: "flex flex-wrap gap-1 mt-2",
34
+ cardTag: "text-[10px] md:text-xs bg-primary/10 text-primary px-1.5 md:px-2 py-0.5 rounded-full"
35
+ },
36
+ variants: {
37
+ isDragging: {
38
+ true: {
39
+ card: "opacity-50"
40
+ }
41
+ }
42
+ }
43
+ });
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { megamenu } from "./theme";
3
3
  import clsx from "clsx";
4
- import type { MegaMenuProps, LinkType } from "..";
4
+ import type { MegaMenuProps } from "..";
5
5
  import Popper from "../utils/Popper.svelte";
6
6
  import { getTheme, warnThemeDeprecation } from "../theme/themeUtils";
7
7
 
@@ -10,14 +10,7 @@
10
10
  // ulClass, extraClass
11
11
  warnThemeDeprecation("MegaMenu", { ulClass, extraClass }, { ulClass: "ul", extraClass: "extra" });
12
12
  const styling = $derived(classes ?? { ul: ulClass, extra: extraClass });
13
-
14
13
  const theme = getTheme("megamenu");
15
-
16
- /* eslint-disable @typescript-eslint/no-explicit-any */
17
- interface LinkTypeLike extends LinkType {
18
- [propName: string]: any;
19
- }
20
-
21
14
  const { base, div, ul, extra: extraCls } = $derived(megamenu({ full, hasExtra: !!extra }));
22
15
  </script>
23
16
 
@@ -8,7 +8,27 @@
8
8
  import { fade } from "svelte/transition";
9
9
  import { modal as modalStyle } from "./theme";
10
10
 
11
- let { children, header, footer, title, open = $bindable(false), permanent = false, dismissable = true, closeBtnClass, headerClass, bodyClass, footerClass, size = "md", placement, class: className, classes, transitionParams, transition = fade, fullscreen = false, ...restProps }: ModalProps = $props();
11
+ let {
12
+ children,
13
+ header,
14
+ footer,
15
+ title,
16
+ open = $bindable(false),
17
+ permanent = false,
18
+ dismissable = true,
19
+ closeBtnClass,
20
+ headerClass,
21
+ bodyClass,
22
+ footerClass,
23
+ size = "md",
24
+ placement,
25
+ class: className,
26
+ classes,
27
+ transitionParams,
28
+ transition = fade,
29
+ fullscreen = false,
30
+ ...restProps
31
+ }: ModalProps = $props();
12
32
 
13
33
  // form, header, footer, body, close
14
34
  warnThemeDeprecation("Modal", { headerClass, bodyClass, footerClass, closeBtnClass }, { bodyClass: "body", headerClass: "header", footerClass: "footer", closeBtnClass: "close" });
@@ -22,7 +42,15 @@
22
42
  const { base, header: headerCls, footer: footerCls, body } = $derived(modalStyle({ placement, size }));
23
43
  </script>
24
44
 
25
- <Dialog bind:open {transition} dismissable={dismissable && !title && !permanent} transitionParams={paramsOptions} {classes} {...restProps} class={base({ fullscreen, class: clsx(theme?.base, className) })}>
45
+ <Dialog
46
+ bind:open
47
+ {transition}
48
+ dismissable={dismissable && !title && !permanent}
49
+ transitionParams={paramsOptions}
50
+ {classes}
51
+ {...restProps}
52
+ class={base({ fullscreen, class: clsx(theme?.base, className) })}
53
+ >
26
54
  {#if title || header}
27
55
  <div class={headerCls({ class: clsx(theme?.header, styling.header) })}>
28
56
  {#if title}
@@ -18,7 +18,7 @@
18
18
  const navBreakpoint = getContext<NavbarBreakpoint>("breakpoint");
19
19
  const { base, menu } = navbarHamburger({ breakpoint: navBreakpoint });
20
20
 
21
- const toggle: MouseEventHandler<HTMLButtonElement> = (ev) => {
21
+ const toggle: MouseEventHandler<HTMLButtonElement> = () => {
22
22
  navState.hidden = !navState.hidden;
23
23
  };
24
24
  </script>
@@ -13,7 +13,9 @@
13
13
  const theme = getTheme("navbarLi");
14
14
 
15
15
  let active = $derived(navState.activeUrl ? restProps.href === navState.activeUrl : false);
16
- let liClass = $derived(navbarLi({ breakpoint: navBreakpoint, hidden: navState.hidden, class: clsx(active ? (activeClass ?? navState.activeClass) : (nonActiveClass ?? navState.nonActiveClass), theme, className) }));
16
+ let liClass = $derived(
17
+ navbarLi({ breakpoint: navBreakpoint, hidden: navState.hidden, class: clsx(active ? (activeClass ?? navState.activeClass) : (nonActiveClass ?? navState.nonActiveClass), theme, className) })
18
+ );
17
19
 
18
20
  function handleClick(event: any) {
19
21
  // Close the mobile menu when a link is clicked