flowbite-svelte 1.10.10 → 1.10.11

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.
@@ -9,7 +9,21 @@
9
9
 
10
10
  let { children, header, arrowup, arrowdown, open = $bindable(false), activeClass, inactiveClass, transitionType = slide, transitionParams, class: className, classes, headerClass, contentClass }: AccordionItemProps = $props();
11
11
 
12
- themeDeprecated("AccordionItem", { headerClass, contentClass, activeClass, inactiveClass });
12
+ themeDeprecated(
13
+ "AccordionItem",
14
+ {
15
+ headerClass,
16
+ contentClass,
17
+ activeClass,
18
+ inactiveClass
19
+ },
20
+ {
21
+ headerClass: "button",
22
+ contentClass: "content",
23
+ activeClass: "active",
24
+ inactiveClass: "inactive"
25
+ }
26
+ );
13
27
 
14
28
  let styling: typeof classes = $derived(classes ?? { button: headerClass, content: contentClass, active: activeClass, inactive: inactiveClass });
15
29
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  let { children, icon, badgeStatus = $bindable(true), color = "primary", large = false, dismissable = false, class: className, classes, border, href, target, rounded, transition = fade, params, aClass, onclose, ...restProps }: BadgeProps = $props();
9
9
 
10
- themeDeprecated("Badge", { aClass });
10
+ themeDeprecated("Badge", { aClass }, { aClass: "linkClass" });
11
11
 
12
12
  let styling = $derived(classes ?? { linkClass: aClass });
13
13
 
@@ -7,7 +7,8 @@
7
7
 
8
8
  let { children, header, open = $bindable(true), dismissable = true, color = "gray", type, class: className, classes, innerClass, transition = fade, params, closeClass, ...restProps }: BannerProps = $props();
9
9
 
10
- themeDeprecated("Banner", { innerClass, closeClass });
10
+ themeDeprecated("Banner", { innerClass, closeClass }, { innerClass: "insideDiv", closeClass: "dismissable" });
11
+
11
12
  let styling = $derived(classes ?? { insideDiv: innerClass, dismissable: closeClass });
12
13
 
13
14
  // Theme context
@@ -8,7 +8,7 @@
8
8
 
9
9
  let { children, header, position = "fixed", navType = "default", class: className, classes, outerClass, innerClass, activeClass, activeUrl = "", ...restProps }: BottomNavProps = $props();
10
10
 
11
- themeDeprecated("BottomNav", { innerClass, outerClass });
11
+ themeDeprecated("BottomNav", { innerClass, outerClass }, { innerClass: "inner", outerClass: "class" });
12
12
  let styling = $derived(classes ?? { inner: innerClass });
13
13
 
14
14
  // Theme context
@@ -6,7 +6,8 @@
6
6
 
7
7
  let { children, class: className, classes, outerClass, innerClass, ...restProps }: BottomNavHeaderProps = $props();
8
8
 
9
- themeDeprecated("BottomNavHeader", { innerClass, outerClass });
9
+ themeDeprecated("BottomNavHeader", { innerClass, outerClass }, { innerClass: "inner", outerClass: "class" });
10
+
10
11
  let styling = $derived(classes ?? { innerDiv: innerClass });
11
12
 
12
13
  // Theme context
@@ -8,7 +8,7 @@
8
8
 
9
9
  let { children, btnName, appBtnPosition = "middle", activeClass, class: className, classes, btnClass, spanClass, active: manualActive, ...restProps }: BottomNavItemProps = $props();
10
10
 
11
- themeDeprecated("BottomNavItem", { spanClass, btnClass });
11
+ themeDeprecated("BottomNavItem", { spanClass, btnClass }, { spanClass: "span", btnClass: "class" });
12
12
  let styling = $derived(classes ?? { span: spanClass });
13
13
 
14
14
  // Theme context
@@ -6,7 +6,7 @@
6
6
 
7
7
  let { children, solid = false, class: className, classes, olClass, ariaLabel = "Breadcrumb", ...restProps }: BreadcrumbProps = $props();
8
8
 
9
- themeDeprecated("Breadcrumb", { olClass });
9
+ themeDeprecated("Breadcrumb", { olClass }, { olClass: "list" });
10
10
  let styling = $derived(classes ?? { list: olClass });
11
11
 
12
12
  const theme = getTheme("breadcrumb");
@@ -6,7 +6,8 @@
6
6
 
7
7
  let { children, color = "gray", horizontal = false, shadow = "md", reverse = false, img, size = "sm", class: className, classes, imgClass, ...restProps }: CardProps = $props();
8
8
 
9
- themeDeprecated("Card", { imgClass });
9
+ themeDeprecated("Card", { imgClass }, { imgClass: "image" });
10
+
10
11
  let styling = $derived(classes ?? { image: imgClass });
11
12
 
12
13
  const theme = getTheme("card");
@@ -130,16 +130,15 @@
130
130
  inputElement?.setCustomValidity("");
131
131
 
132
132
  if (range) {
133
- const parts = inputValue.split(" - "); // Split the string by " - "
133
+ const parts = inputValue.split(" - ");
134
134
  if (parts.length === 2) {
135
135
  const parsedFrom = tryParseDate(parts[0]);
136
136
  const parsedTo = tryParseDate(parts[1]);
137
137
 
138
138
  if (parsedFrom && isValid(parsedFrom) && isDateAvailable(parsedFrom) && parsedTo && isValid(parsedTo) && isDateAvailable(parsedTo)) {
139
- rangeFrom = parsedFrom;
140
- rangeTo = parsedTo;
139
+ [rangeFrom, rangeTo] = parsedFrom > parsedTo ? [parsedTo, parsedFrom] : [parsedFrom, parsedTo];
141
140
  onselect?.({ from: rangeFrom, to: rangeTo });
142
- return; // Successfully parsed range
141
+ return;
143
142
  } else {
144
143
  inputElement?.setCustomValidity(`Please enter date range in format: ${getDateFormatPattern()} - ${getDateFormatPattern()}`);
145
144
  return;
@@ -147,7 +146,6 @@
147
146
  }
148
147
  }
149
148
 
150
- // Original single date parsing logic
151
149
  const parsedDate = tryParseDate(inputValue);
152
150
 
153
151
  if (!parsedDate || !isValid(parsedDate)) {
@@ -213,12 +211,9 @@
213
211
 
214
212
  function getDateFormatPattern(): string {
215
213
  const actualLocale = locale === "default" ? navigator.language : locale;
216
-
217
- // Create a test date and format it to understand the pattern
218
214
  const testDate = new Date(2025, 0, 15); // January 15, 2025
219
215
  const formatted = testDate.toLocaleDateString(actualLocale, dateFormat || { year: "numeric", month: "numeric", day: "numeric" });
220
216
 
221
- // Analyze the formatted string to determine the pattern
222
217
  if (formatted.includes(".")) {
223
218
  // German/European format with dots
224
219
  if (formatted.startsWith("15.")) {
@@ -234,7 +229,7 @@
234
229
  } else if (formatted.startsWith("15/")) {
235
230
  return "d/M/yyyy"; // UK format
236
231
  }
237
- // Additional check with different test date
232
+
238
233
  const testDate2 = new Date(2025, 11, 3); // December 3, 2025
239
234
  const formatted2 = testDate2.toLocaleDateString(actualLocale, dateFormat || { year: "numeric", month: "numeric", day: "numeric" });
240
235
  if (formatted2.startsWith("3/") || formatted2.startsWith("03/")) {
@@ -272,7 +267,7 @@
272
267
  }
273
268
  }
274
269
 
275
- // MODIFIED: Use locale for formatting (not translationLocale)
270
+ // Use locale for formatting (not translationLocale)
276
271
  const formatDate = (date?: Date): string => date?.toLocaleDateString(locale, dateFormat) ?? "";
277
272
  const isSameDate = (date1?: Date, date2?: Date): boolean => (date1 && date2 ? isSameDay(date1, date2) : false);
278
273
  const isToday = (day: Date): boolean => isSameDate(day, new Date());
@@ -326,7 +321,7 @@
326
321
  currentMonth = new Date(focusedDate.getFullYear(), focusedDate.getMonth(), 1);
327
322
  }
328
323
 
329
- // MODIFIED: Use translationLocale for aria-label
324
+ // Use translationLocale for aria-label
330
325
  setTimeout(() => {
331
326
  const focusedButton = calendarRef?.querySelector(`button[aria-label="${focusedDate!.toLocaleDateString(translationLocale, { weekday: "long", year: "numeric", month: "long", day: "numeric" })}"]`) as HTMLButtonElement | null;
332
327
  focusedButton?.focus();
@@ -335,10 +330,9 @@
335
330
 
336
331
  function handleInputKeydown(event: KeyboardEvent) {
337
332
  if (event.key === "Enter") {
338
- event.preventDefault(); // Prevent default form submission or other Enter key behaviors
339
- handleInputChangeWithDateFns(); // Call the function to parse and apply the date
333
+ event.preventDefault();
334
+ handleInputChangeWithDateFns();
340
335
  if (autohide && !inline) {
341
- // Optionally close the datepicker after applying
342
336
  isOpen = false;
343
337
  }
344
338
  } else if (event.key === " ") {
@@ -6,7 +6,8 @@
6
6
 
7
7
  let { children, class: className, classes, divClass, div2Class, div3Class, div4Class, div5Class, div6Class, div7Class, ...restProps }: AndroidProps = $props();
8
8
 
9
- themeDeprecated("Android", { divClass, div2Class, div3Class, div4Class, div5Class, div6Class, div7Class });
9
+ themeDeprecated("Android", { divClass, div2Class, div3Class, div4Class, div5Class, div6Class, div7Class }, { divClass: "class", div2Class: "top", div3Class: "leftTop", div4Class: "leftMid", div5Class: "leftBot", div6Class: "right", div7Class: "slot" });
10
+
10
11
  let styling = $derived(
11
12
  classes ?? {
12
13
  top: div2Class,
@@ -6,7 +6,7 @@
6
6
 
7
7
  let { children, class: className, classes, divClass, div2Class, div3Class, div4Class, div5Class, div6Class, ...restProps }: DefaultMockupProps = $props();
8
8
 
9
- themeDeprecated("DefaultMockup", { divClass, div2Class, div3Class, div4Class, div5Class, div6Class });
9
+ themeDeprecated("DefaultMockup", { divClass, div2Class, div3Class, div4Class, div5Class, div6Class }, { divClass: "class", div2Class: "top", div3Class: "leftTop", div4Class: "leftBot", div5Class: "right", div6Class: "slot" });
10
10
  let styling = $derived(
11
11
  classes ?? {
12
12
  top: div2Class,
@@ -6,7 +6,7 @@
6
6
 
7
7
  let { children, class: className, classes, divClass, div2Class, div3Class, div4Class, ...restProps }: DesktopProps = $props();
8
8
 
9
- themeDeprecated("DesktopMockup", { divClass, div2Class, div3Class, div4Class });
9
+ themeDeprecated("DesktopMockup", { divClass, div2Class, div3Class, div4Class }, { divClass: "class", div2Class: "inner", div3Class: "bot", div4Class: "botUnder" });
10
10
  let styling = $derived(
11
11
  classes ?? {
12
12
  inner: div2Class,
@@ -6,7 +6,7 @@
6
6
 
7
7
  let { children, class: className, classes, divClass, div2Class, div3Class, div4Class, div5Class, div6Class, ...restProps }: IosProps = $props();
8
8
 
9
- themeDeprecated("Ios", { divClass, div2Class, div3Class, div4Class, div5Class, div6Class });
9
+ themeDeprecated("Ios", { divClass, div2Class, div3Class, div4Class, div5Class, div6Class }, { divClass: "class", div2Class: "top", div3Class: "lefttop", div4Class: "leftBot", div5Class: "right", div6Class: "slot" });
10
10
  let styling = $derived(
11
11
  classes ?? {
12
12
  top: div2Class,
@@ -6,7 +6,7 @@
6
6
 
7
7
  let { children, class: className, classes, divClass, div2Class, div3Class, div4Class, ...restProps }: LaptopProps = $props();
8
8
 
9
- themeDeprecated("Laptop", { divClass, div2Class, div3Class, div4Class });
9
+ themeDeprecated("Laptop", { divClass, div2Class, div3Class, div4Class }, { divClass: "class", div2Class: "top", div3Class: "lefttop", div4Class: "leftBot", div5Class: "right", div6Class: "slot" });
10
10
  let styling = $derived(
11
11
  classes ?? {
12
12
  inner: div2Class,
@@ -6,7 +6,7 @@
6
6
 
7
7
  let { children, class: className, classes, divClass, div2Class, div3Class, div4Class, div5Class, div6Class, ...restProps }: SmartwatchProps = $props();
8
8
 
9
- themeDeprecated("Smartwatch", { divClass, div2Class, div3Class, div4Class, div5Class, div6Class });
9
+ themeDeprecated("Smartwatch", { divClass, div2Class, div3Class, div4Class, div5Class, div6Class }, { divClass: "class", div2Class: "top", div3Class: "rightTop", div4Class: "rightBot", div5Class: "bot", div6Class: "slot" });
10
10
  let styling = $derived(
11
11
  classes ?? {
12
12
  top: div2Class,
@@ -6,7 +6,7 @@
6
6
 
7
7
  let { children, class: className, classes, divClass, div2Class, div3Class, div4Class, div5Class, div6Class, ...restProps }: TabletProps = $props();
8
8
 
9
- themeDeprecated("TabletMockup", { divClass, div2Class, div3Class, div4Class, div5Class, div6Class });
9
+ themeDeprecated("TabletMockup", { divClass, div2Class, div3Class, div4Class, div5Class, div6Class }, { divClass: "class", div2Class: "leftTop", div3Class: "leftMid", div4Class: "leftBot", div5Class: "right", div6Class: "slot" });
10
10
  let styling = $derived(
11
11
  classes ?? {
12
12
  leftTop: div2Class,
@@ -11,5 +11,5 @@ export type Classes<T extends {
11
11
  [K in keyof Slots<T>]: ClassValue;
12
12
  }>;
13
13
  };
14
- export declare function themeDeprecated(component: string, names: Record<string, unknown>): void;
14
+ export declare function themeDeprecated(component: string, names: Record<string, unknown>, replacements?: Record<string, unknown>): void;
15
15
  export {};
@@ -1,14 +1,46 @@
1
1
  import {} from "..";
2
2
  import { getContext } from "svelte";
3
+ import { dev } from "$app/environment";
4
+ // add PUBLIC_SHOW_HINT=true to .env to show migration hints in the console during the playwright tests
5
+ import { PUBLIC_SHOW_HINT } from "$env/static/public";
3
6
  export function getTheme(componentKey) {
4
7
  const theme = getContext("theme");
5
8
  return theme?.[componentKey];
6
9
  }
7
- export function themeDeprecated(component, names) {
8
- const nonEmptyNames = Object.keys(names)
9
- .filter((name) => names[name])
10
- .map((name) => `"${name}"`);
10
+ export function themeDeprecated(component, names, replacements) {
11
+ const showHint = dev || PUBLIC_SHOW_HINT === "true";
12
+ if (!showHint)
13
+ return;
14
+ const nonEmptyNames = Object.keys(names).filter((name) => names[name]);
11
15
  if (nonEmptyNames.length === 0)
12
16
  return;
13
- console.warn(`The following "${component}" props are deprecated: ${nonEmptyNames.join(", ")}.\nPlease update your code to use the new "classes" property.`);
17
+ let migrationHint = "";
18
+ const usesClass = nonEmptyNames.some((name) => replacements?.[name] === "class");
19
+ const propText = usesClass ? `"classes" or "class"` : `"classes"`;
20
+ if (replacements) {
21
+ const classProps = [];
22
+ const classesObjectEntries = [];
23
+ for (const name of nonEmptyNames) {
24
+ const newKey = replacements[name];
25
+ const value = names[name];
26
+ if (!newKey || !value)
27
+ continue;
28
+ if (newKey === "class") {
29
+ classProps.push(`class="${value}"`);
30
+ }
31
+ else {
32
+ classesObjectEntries.push(`${newKey}: "${value}"`);
33
+ }
34
+ }
35
+ const hintLines = [];
36
+ if (classProps.length > 0)
37
+ hintLines.push(...classProps);
38
+ if (classesObjectEntries.length > 0) {
39
+ hintLines.push(`classes={{ ${classesObjectEntries.join(", ")} }}`);
40
+ }
41
+ if (hintLines.length > 0) {
42
+ migrationHint = `\nMigration example: ${hintLines.join(" ")}`;
43
+ }
44
+ }
45
+ console.warn(`The following "${component}" props are deprecated: ${nonEmptyNames.map((n) => `"${n}"`).join(", ")}.` + ` Please update your code to use the new ${propText} prop.${migrationHint}`);
14
46
  }
package/dist/types.d.ts CHANGED
@@ -393,7 +393,6 @@ export interface DatepickerProps extends DatepickerVariants, Omit<HTMLAttributes
393
393
  placeholder?: string;
394
394
  disabled?: boolean;
395
395
  required?: boolean;
396
- inputClass?: ClassValue;
397
396
  color?: ButtonProps["color"];
398
397
  inline?: boolean;
399
398
  autohide?: boolean;
@@ -402,9 +401,10 @@ export interface DatepickerProps extends DatepickerVariants, Omit<HTMLAttributes
402
401
  onselect?: (x: DateOrRange) => void;
403
402
  onclear?: () => void;
404
403
  onapply?: (x: DateOrRange) => void;
405
- btnClass?: ClassValue;
406
404
  inputmode?: HTMLInputAttributes["inputmode"];
407
405
  monthColor?: ButtonProps["color"];
406
+ btnClass?: ClassValue;
407
+ inputClass?: ClassValue;
408
408
  monthBtnSelected?: ClassValue;
409
409
  monthBtn?: ClassValue;
410
410
  translationLocale?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flowbite-svelte",
3
- "version": "1.10.10",
3
+ "version": "1.10.11",
4
4
  "description": "Flowbite components for Svelte",
5
5
  "main": "dist/index.js",
6
6
  "author": {
@@ -811,7 +811,7 @@
811
811
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
812
812
  "lint": "prettier --check . && eslint .",
813
813
  "format": "prettier --write .",
814
- "test:e2e": "playwright test",
814
+ "test:e2e": "PUBLIC_SHOW_HINT=true playwright test",
815
815
  "test:unit": "vitest",
816
816
  "gen:exports": "svelte-lib-helpers exports",
817
817
  "gen:docspropvalue": "svelte-lib-helpers docspropvalue themesberg/flowbite-svelte",