@cloudparker/moldex.js 0.0.124 → 4.1.1

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 (69) hide show
  1. package/dist/types.d.ts +6 -0
  2. package/dist/types.js +7 -0
  3. package/dist/views/core/button/components/button/button.svelte +135 -83
  4. package/dist/views/core/button/components/button-back/button-back.svelte +28 -15
  5. package/dist/views/core/button/components/button-close/button-close.svelte +4 -2
  6. package/dist/views/core/button/components/button-close-icon/button-close-icon.svelte +29 -15
  7. package/dist/views/core/button/components/button-dropdown/button-dropdown.svelte +96 -72
  8. package/dist/views/core/button/components/button-dropdown/button-dropdown.svelte.d.ts +1 -1
  9. package/dist/views/core/button/components/button-list-item/button-list-item.svelte +98 -52
  10. package/dist/views/core/button/components/button-menu/button-menu.svelte +79 -43
  11. package/dist/views/core/button/components/button-ok/button-ok.svelte +4 -2
  12. package/dist/views/core/button/components/button-search/button-search.svelte +45 -21
  13. package/dist/views/core/button/components/switch/switch.svelte +50 -37
  14. package/dist/views/core/common/components/content-area/content-area.svelte +40 -27
  15. package/dist/views/core/common/components/loading/loading.svelte +9 -2
  16. package/dist/views/core/common/components/virtual-scrolling/virtual-scrolling-list.svelte +37 -20
  17. package/dist/views/core/dialog/components/cropper-dialog/cropper-dialog.svelte +52 -36
  18. package/dist/views/core/dialog/components/dialog/dialog.svelte +298 -177
  19. package/dist/views/core/dialog/components/loading-dialog/loading-dialog.svelte +30 -18
  20. package/dist/views/core/dialog/components/msg-dialog/msg-dialog.svelte +17 -7
  21. package/dist/views/core/dialog/components/number-field-dialog/number-field-dialog.svelte +41 -26
  22. package/dist/views/core/dialog/components/picker-dialog/picker-dialog.svelte +150 -105
  23. package/dist/views/core/dialog/components/text-field-dialog/text-field-dialog.svelte +40 -25
  24. package/dist/views/core/dialog/components/textarea-field-dialog/textarea-field-dialog.svelte +40 -25
  25. package/dist/views/core/drawer/components/drawer/drawer.svelte +58 -36
  26. package/dist/views/core/icon/components/icon/icon.svelte +24 -12
  27. package/dist/views/core/icon/components/icon-circle/icon-circle.svelte +10 -2
  28. package/dist/views/core/input/components/checkbox-field/checkbox-field.svelte +44 -25
  29. package/dist/views/core/input/components/color-field/color-field.svelte +81 -69
  30. package/dist/views/core/input/components/combobox-field/combobox-field.svelte +359 -269
  31. package/dist/views/core/input/components/date-field/date-field.svelte +39 -30
  32. package/dist/views/core/input/components/datetime-field/datetime-field.svelte +18 -12
  33. package/dist/views/core/input/components/email-field/email-field.svelte +17 -12
  34. package/dist/views/core/input/components/file-field/file-field.svelte +78 -64
  35. package/dist/views/core/input/components/input-field/input-field.svelte +267 -164
  36. package/dist/views/core/input/components/label/label.svelte +24 -10
  37. package/dist/views/core/input/components/number-field/number-field.svelte +18 -12
  38. package/dist/views/core/input/components/password-field/password-field.svelte +70 -57
  39. package/dist/views/core/input/components/phone-field/phone-field.svelte +155 -104
  40. package/dist/views/core/input/components/radio-field/radio-field.svelte +83 -52
  41. package/dist/views/core/input/components/range-field/range-field.svelte +67 -44
  42. package/dist/views/core/input/components/search-field/search-field.svelte +62 -45
  43. package/dist/views/core/input/components/text-field/text-field.svelte +21 -16
  44. package/dist/views/core/input/components/textarea-field/textarea-field.svelte +17 -12
  45. package/dist/views/core/input/components/time-field/time-field.svelte +17 -12
  46. package/dist/views/core/navbar/components/navbar/navbar.svelte +76 -38
  47. package/dist/views/core/no-data/components/no-data/no-data.svelte +36 -19
  48. package/dist/views/core/pagination/components/pagination/pagination.svelte +90 -66
  49. package/dist/views/core/progressbar/components/progressbar/progressbar.svelte +36 -22
  50. package/dist/views/core/ruler/components/vertical-ruler/verticcal-ruler.svelte +5 -1
  51. package/dist/views/core/screen-detector/components/screen-detector.svelte +13 -9
  52. package/dist/views/core/sidebar/components/sidebar.svelte +36 -23
  53. package/dist/views/core/spinner/components/spinner/spinner.svelte +6 -1
  54. package/dist/views/core/text/components/text-await/text-await.svelte +9 -1
  55. package/dist/views/core/text/components/text-copy/text-copy.svelte +27 -16
  56. package/dist/views/core/text/components/text-currency/text-currency.svelte +13 -2
  57. package/dist/views/core/text/components/text-date/text-date.svelte +32 -20
  58. package/dist/views/core/text/components/text-email/text-email.svelte +12 -3
  59. package/dist/views/core/text/components/text-html/text-html.svelte +2 -1
  60. package/dist/views/core/text/components/text-phone/text-phone.svelte +12 -3
  61. package/dist/views/core/toast/components/toast/toast.svelte +43 -20
  62. package/dist/views/extra/fields/country-combobox-field.svelte +23 -15
  63. package/dist/views/extra/loaders/country-loader.svelte +33 -15
  64. package/dist/views/extra/texts/text-country-state.svelte +36 -28
  65. package/dist/views/extra/texts/text-country.svelte +16 -8
  66. package/package.json +3 -12
  67. package/readme.md +57 -2
  68. package/dist/tailwind.css +0 -1
  69. package/dist/theme.css +0 -27
@@ -1,56 +1,102 @@
1
- <script module lang="ts"></script>
1
+ <script module lang="ts">
2
+ export type ButtonListItemProps = {
3
+ appearance?: ButtonAppearance;
4
+ size?: ButtonSize;
5
+ index?: number;
6
+ id?: string;
7
+ className?: string;
8
+ checkboxIconPath?: string;
9
+ uncheckboxIconPath?: string;
10
+ checkboxIconClassName?: string;
11
+ uncheckboxIconClassName?: string;
12
+ hasIcon?: boolean;
13
+ iconClassName?: string;
14
+ hasImg?: boolean;
15
+ imgClassName?: string;
16
+ hasArrow?: boolean;
17
+ arrowIconPath?: string;
18
+ arrowClassName?: string;
19
+ title?: string;
20
+ subtitle?: string;
21
+ titleClassName?: string;
22
+ subtitleClassName?: string;
23
+ url?: string;
24
+ disabled?: boolean;
25
+ iconPath?: string;
26
+ isCircularIcon?: boolean;
27
+ circularIconClassName?: string;
28
+ imgSrc?: string;
29
+ hasCheckbox?: boolean;
30
+ checkboxClassName?: string;
31
+ isChecked?: boolean;
32
+ hasMenu?: boolean;
33
+ menus?: Menu[] | string[];
34
+ menuIconPath?: string;
35
+ menuIconClassName?: string;
36
+ menuButtonClassName?: string;
37
+ menuButtonLabel?: string;
38
+ hasDivider?: boolean;
39
+ dividerClassName?: string;
40
+ onMenu?: (ev: Event, menu: Menu | string) => void;
41
+ onClick?: (ev: MouseEvent) => void;
42
+ children?: Snippet;
43
+ };
44
+ </script>
45
+
46
+ <script lang="ts">
47
+ import {
48
+ Icon,
49
+ mdiCheckCircle,
50
+ mdiCheckCircleOutline,
51
+ mdiChevronRight
52
+ } from '../../../icon';
53
+ import type { Snippet } from 'svelte';
54
+ import Button, { type ButtonAppearance, type ButtonSize } from '../button/button.svelte';
55
+ import type { Menu } from '../button-menu/button-menu.svelte';
56
+ import ButtonMenu from '../button-menu/button-menu.svelte';
57
+ import IconCircle from '../../../icon/components/icon-circle/icon-circle.svelte';
2
58
 
3
- <script lang="ts">import {
4
- Icon,
5
- mdiCheckCircle,
6
- mdiCheckCircleOutline,
7
- mdiChevronRight
8
- } from "../../../icon";
9
- import Button, {} from "../button/button.svelte";
10
- import ButtonMenu from "../button-menu/button-menu.svelte";
11
- import IconCircle from "../../../icon/components/icon-circle/icon-circle.svelte";
12
- let {
13
- appearance,
14
- size,
15
- index,
16
- id = "",
17
- className,
18
- checkboxIconPath = mdiCheckCircle,
19
- uncheckboxIconPath = mdiCheckCircleOutline,
20
- checkboxIconClassName = "",
21
- uncheckboxIconClassName = "",
22
- hasIcon = false,
23
- iconClassName = "",
24
- hasImg = false,
25
- imgClassName = "",
26
- iconPath,
27
- isCircularIcon,
28
- circularIconClassName = "",
29
- imgSrc,
30
- hasArrow = false,
31
- arrowIconPath = mdiChevronRight,
32
- arrowClassName = "",
33
- title = "",
34
- subtitle = "",
35
- titleClassName = "",
36
- subtitleClassName = "",
37
- disabled = false,
38
- hasCheckbox,
39
- checkboxClassName = "",
40
- isChecked = false,
41
- hasMenu,
42
- menus,
43
- menuIconPath,
44
- menuIconClassName,
45
- menuButtonClassName,
46
- menuButtonLabel,
47
- hasDivider,
48
- dividerClassName,
49
- onMenu,
50
- onClick = (ev) => {
51
- },
52
- children
53
- } = $props();
59
+ let {
60
+ appearance,
61
+ size,
62
+ index,
63
+ id = '',
64
+ className,
65
+ checkboxIconPath = mdiCheckCircle,
66
+ uncheckboxIconPath = mdiCheckCircleOutline,
67
+ checkboxIconClassName = '',
68
+ uncheckboxIconClassName = '',
69
+ hasIcon = false,
70
+ iconClassName = '',
71
+ hasImg = false,
72
+ imgClassName = '',
73
+ iconPath,
74
+ isCircularIcon,
75
+ circularIconClassName = '',
76
+ imgSrc,
77
+ hasArrow = false,
78
+ arrowIconPath = mdiChevronRight,
79
+ arrowClassName = '',
80
+ title = '',
81
+ subtitle = '',
82
+ titleClassName = '',
83
+ subtitleClassName = '',
84
+ disabled = false,
85
+ hasCheckbox,
86
+ checkboxClassName = '',
87
+ isChecked = false,
88
+ hasMenu,
89
+ menus,
90
+ menuIconPath,
91
+ menuIconClassName,
92
+ menuButtonClassName,
93
+ menuButtonLabel,
94
+ hasDivider,
95
+ dividerClassName,
96
+ onMenu,
97
+ onClick = (ev: MouseEvent) => {},
98
+ children
99
+ }: ButtonListItemProps = $props();
54
100
  </script>
55
101
 
56
102
  {#snippet itemInternal()}
@@ -1,47 +1,83 @@
1
- <script lang="ts" module></script>
1
+ <script lang="ts" module>
2
+ export type Menu = {
3
+ _id?: string;
4
+ title?: string;
5
+ subtitle?: string;
6
+ hasIcon?: boolean;
7
+ iconPath?: string;
8
+ iconClassName?: string;
9
+ hasCheckbox?: boolean;
10
+ checkboxClassName?: string;
11
+ isChecked?: boolean;
12
+ };
13
+ </script>
14
+
15
+ <script lang="ts">
16
+ import {
17
+ mdiDotsHorizontal,
18
+ type ButtonAppearance,
19
+ type ButtonProps,
20
+ type ButtonSize
21
+ } from '../../../../..';
22
+ import ButtonDropdown, {
23
+ type ButtonDropdownProps
24
+ } from '../button-dropdown/button-dropdown.svelte';
25
+ import Icon from '../../../icon/components/icon/icon.svelte';
26
+ import type { Snippet } from 'svelte';
27
+ import ButtonListItem from '../button-list-item/button-list-item.svelte';
28
+ type Props = {
29
+ label?: string;
30
+ className?: string;
31
+ appearance?: ButtonAppearance;
32
+ size?: ButtonSize;
33
+ children?: Snippet;
34
+ iconPath?: string;
35
+ iconClassName?: string;
36
+ menus?: string[] | Menu[];
37
+ onMenu?: (ev: MouseEvent, menu: string | Menu) => void;
38
+ dropdownClassName?: string;
39
+ menuIconClassName?: string;
40
+ disabled?: boolean;
41
+ };
42
+
43
+ let {
44
+ label,
45
+ className,
46
+ appearance,
47
+ size,
48
+ children,
49
+ iconPath = mdiDotsHorizontal,
50
+ iconClassName,
51
+ menus,
52
+ onMenu,
53
+ dropdownClassName,
54
+ menuIconClassName,
55
+ disabled,
56
+ ...others
57
+ }: ButtonDropdownProps & ButtonProps & Props = $props();
58
+
59
+ let buttonDropdownRef: ButtonDropdown;
60
+
61
+ let items: Menu[] = $derived.by(() => {
62
+ if (menus && typeof menus[0] == 'string') {
63
+ let array = (menus as string[]).map((name: string) => {
64
+ return {
65
+ _id: name,
66
+ title: name
67
+ } as Menu;
68
+ });
69
+ return array;
70
+ }
71
+ return (menus || []) as Menu[];
72
+ });
2
73
 
3
- <script lang="ts">import {
4
- mdiDotsHorizontal
5
- } from "../../../../..";
6
- import ButtonDropdown, {
7
- } from "../button-dropdown/button-dropdown.svelte";
8
- import Icon from "../../../icon/components/icon/icon.svelte";
9
- import ButtonListItem from "../button-list-item/button-list-item.svelte";
10
- let {
11
- label,
12
- className,
13
- appearance,
14
- size,
15
- children,
16
- iconPath = mdiDotsHorizontal,
17
- iconClassName,
18
- menus,
19
- onMenu,
20
- dropdownClassName,
21
- menuIconClassName,
22
- disabled,
23
- ...others
24
- } = $props();
25
- let buttonDropdownRef;
26
- let items = $derived.by(() => {
27
- if (menus && typeof menus[0] == "string") {
28
- let array = menus.map((name) => {
29
- return {
30
- _id: name,
31
- title: name
32
- };
33
- });
34
- return array;
35
- }
36
- return menus || [];
37
- });
38
- function handleItemClick(ev, menuItem, index) {
39
- let menu = (menus || [])[index];
40
- if (menu) {
41
- onMenu && onMenu(ev, menu);
42
- buttonDropdownRef && buttonDropdownRef.toggleDropdown(ev);
43
- }
44
- }
74
+ function handleItemClick(ev: MouseEvent, menuItem: Menu, index: number) {
75
+ let menu = (menus || [])[index];
76
+ if (menu) {
77
+ onMenu && onMenu(ev, menu);
78
+ buttonDropdownRef && buttonDropdownRef.toggleDropdown(ev);
79
+ }
80
+ }
45
81
  </script>
46
82
 
47
83
  {#snippet dropdownView()}
@@ -1,5 +1,7 @@
1
- <script lang="ts">import Button, {} from "../button/button.svelte";
2
- let { className, ...props } = $props();
1
+ <script lang="ts">
2
+ import Button, { type ButtonProps } from '../button/button.svelte';
3
+
4
+ let { className, ...props }: ButtonProps = $props();
3
5
  </script>
4
6
 
5
7
  <Button {...props} className="bg-indigo-600 focus:bg-indigo-700 text-white p-2 px-4 {className}" />
@@ -1,24 +1,48 @@
1
- <script lang="ts">import {
2
- mdiMagnify
3
- } from "../../../../..";
4
- import ButtonDropdown from "../button-dropdown/button-dropdown.svelte";
5
- import Icon from "../../../icon/components/icon/icon.svelte";
6
- import SearchField from "../../../input/components/search-field/search-field.svelte";
7
- let {
8
- searchText = $bindable(""),
9
- searchClassName,
10
- searchAppearance,
11
- searchSize,
12
- onSearch,
13
- className,
14
- appearance,
15
- size,
16
- children,
17
- iconClassName,
18
- dropdownClassName,
19
- placeholder,
20
- ...others
21
- } = $props();
1
+ <script lang="ts">
2
+ import {
3
+ mdiMagnify,
4
+ type ButtonAppearance,
5
+ type ButtonProps,
6
+ type ButtonSize,
7
+ type InputFieldAppearance,
8
+ type InputFieldSize
9
+ } from '../../../../..';
10
+ import ButtonDropdown from '../button-dropdown/button-dropdown.svelte';
11
+ import Icon from '../../../icon/components/icon/icon.svelte';
12
+ import SearchField from '../../../input/components/search-field/search-field.svelte';
13
+ import type { Snippet } from 'svelte';
14
+ type Props = {
15
+ searchAppearance?: InputFieldAppearance;
16
+ searchClassName?: string;
17
+ searchSize?: InputFieldSize;
18
+ onSearch?: (searchText: string) => void;
19
+
20
+ className?: string;
21
+ appearance?: ButtonAppearance;
22
+ size?: ButtonSize;
23
+ children?: Snippet;
24
+ iconClassName?: string;
25
+
26
+ dropdownClassName?: string;
27
+ searchText?: string;
28
+ placeholder?: string;
29
+ };
30
+
31
+ let {
32
+ searchText = $bindable(''),
33
+ searchClassName,
34
+ searchAppearance,
35
+ searchSize,
36
+ onSearch,
37
+ className,
38
+ appearance,
39
+ size,
40
+ children,
41
+ iconClassName,
42
+ dropdownClassName,
43
+ placeholder,
44
+ ...others
45
+ }: ButtonProps & Props = $props();
22
46
  </script>
23
47
 
24
48
  {#snippet dropdownSearch()}
@@ -1,41 +1,54 @@
1
- <script module lang="ts"></script>
1
+ <script module lang="ts">
2
+ export type SwitchProps = {
3
+ id?: string;
4
+ checked?: boolean;
5
+ disabled?: boolean;
6
+ className?: string;
7
+ size?: 'sm' | 'md' | 'lg';
8
+ onChange?: (checked: boolean) => void;
9
+ };
10
+ </script>
11
+
12
+ <script lang="ts">
13
+ let {
14
+ id = '',
15
+ checked = false,
16
+ disabled = false,
17
+ className = '',
18
+ size = 'md',
19
+ onChange
20
+ }: SwitchProps = $props();
21
+
22
+ function toggle() {
23
+ if (disabled) return;
24
+ checked = !checked;
25
+ onChange?.(checked);
26
+ }
2
27
 
3
- <script lang="ts">let {
4
- id = "",
5
- checked = false,
6
- disabled = false,
7
- className = "",
8
- size = "md",
9
- onChange
10
- } = $props();
11
- function toggle() {
12
- if (disabled) return;
13
- checked = !checked;
14
- onChange?.(checked);
15
- }
16
- let sizeClass = $derived.by(() => {
17
- switch (size) {
18
- case "sm":
19
- return {
20
- wrapper: "h-4 w-8",
21
- circle: "h-3 w-3 translate-x-1",
22
- circleChecked: "translate-x-5"
23
- };
24
- case "lg":
25
- return {
26
- wrapper: "h-8 w-16",
27
- circle: "h-6 w-6 translate-x-1",
28
- circleChecked: "translate-x-8"
29
- };
30
- case "md":
31
- default:
32
- return {
33
- wrapper: "h-6 w-11",
34
- circle: "h-4 w-4 translate-x-1",
35
- circleChecked: "translate-x-6"
36
- };
37
- }
38
- });
28
+ // Size mapping
29
+ let sizeClass = $derived.by(() => {
30
+ switch (size) {
31
+ case 'sm':
32
+ return {
33
+ wrapper: 'h-4 w-8',
34
+ circle: 'h-3 w-3 translate-x-1',
35
+ circleChecked: 'translate-x-5'
36
+ };
37
+ case 'lg':
38
+ return {
39
+ wrapper: 'h-8 w-16',
40
+ circle: 'h-6 w-6 translate-x-1',
41
+ circleChecked: 'translate-x-8'
42
+ };
43
+ case 'md':
44
+ default:
45
+ return {
46
+ wrapper: 'h-6 w-11',
47
+ circle: 'h-4 w-4 translate-x-1',
48
+ circleChecked: 'translate-x-6'
49
+ };
50
+ }
51
+ });
39
52
  </script>
40
53
 
41
54
  <button
@@ -1,30 +1,43 @@
1
- <script lang="ts">let {
2
- children,
3
- className,
4
- id,
5
- responsiveBreakpoint = "md",
6
- sidebarPosition = "none"
7
- } = $props();
8
- let responsiveClassName = $derived.by(() => {
9
- if (sidebarPosition === "none") {
10
- return "";
11
- } else {
12
- switch (responsiveBreakpoint) {
13
- case "xs":
14
- return sidebarPosition === "left" ? "xs:pl-72" : "xs:pr-72";
15
- case "sm":
16
- return sidebarPosition === "left" ? "sm:pl-72" : "sm:pr-72";
17
- case "md":
18
- return sidebarPosition === "left" ? "md:pl-72" : "md:pr-72";
19
- case "lg":
20
- return sidebarPosition === "left" ? "lg:pl-72" : "lg:pr-72";
21
- case "xl":
22
- return sidebarPosition === "left" ? "xl:pl-72" : "xl:pr-72";
23
- case "2xl":
24
- return sidebarPosition === "left" ? "2xl:pl-72" : "2xl:pr-72";
25
- }
26
- }
27
- });
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ type BreakpointType = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
5
+
6
+ type PropsType = {
7
+ children?: Snippet;
8
+ className?: string;
9
+ id?: string;
10
+ responsiveBreakpoint?: BreakpointType;
11
+ sidebarPosition?: 'none' | 'left' | 'right';
12
+ };
13
+ let {
14
+ children,
15
+ className,
16
+ id,
17
+ responsiveBreakpoint = 'md',
18
+ sidebarPosition = 'none'
19
+ }: PropsType = $props();
20
+
21
+ let responsiveClassName = $derived.by(() => {
22
+ if (sidebarPosition === 'none') {
23
+ return '';
24
+ } else {
25
+ switch (responsiveBreakpoint) {
26
+ case 'xs':
27
+ return sidebarPosition === 'left' ? 'xs:pl-72' : 'xs:pr-72';
28
+ case 'sm':
29
+ return sidebarPosition === 'left' ? 'sm:pl-72' : 'sm:pr-72';
30
+ case 'md':
31
+ return sidebarPosition === 'left' ? 'md:pl-72' : 'md:pr-72';
32
+ case 'lg':
33
+ return sidebarPosition === 'left' ? 'lg:pl-72' : 'lg:pr-72';
34
+ case 'xl':
35
+ return sidebarPosition === 'left' ? 'xl:pl-72' : 'xl:pr-72';
36
+ case '2xl':
37
+ return sidebarPosition === 'left' ? '2xl:pl-72' : '2xl:pr-72';
38
+ }
39
+ }
40
+ });
28
41
  </script>
29
42
 
30
43
  <div {id} class="{responsiveClassName} {className}">
@@ -1,5 +1,12 @@
1
- <script lang="ts">import Spinner from "../../../spinner/components/spinner/spinner.svelte";
2
- let { className = "", spinnerClassName = "text-primary" } = $props();
1
+ <script lang="ts">
2
+ import Spinner from '../../../spinner/components/spinner/spinner.svelte';
3
+
4
+ type Props = {
5
+ spinnerClassName?: string;
6
+ className?: string;
7
+ };
8
+
9
+ let { className = '', spinnerClassName = 'text-primary' }: Props = $props();
3
10
  </script>
4
11
 
5
12
  <div class="flex items-center justify-center p-6 {className}">
@@ -1,23 +1,40 @@
1
- <script lang="ts">let {
2
- items = [],
3
- itemHeight,
4
- containerHeight,
5
- buffer = 2,
6
- itemSnippet,
7
- ...rest
8
- } = $props();
9
- let scrollTop = $state(0);
10
- let totalHeight = $derived.by(() => items.length * itemHeight);
11
- let visibleStart = $derived.by(() => Math.max(Math.floor(scrollTop / itemHeight) - buffer, 0));
12
- let visibleEnd = $derived.by(
13
- () => Math.min(Math.ceil((scrollTop + containerHeight) / itemHeight) + buffer, items.length)
14
- );
15
- let paddingTop = $derived.by(() => visibleStart * itemHeight);
16
- let paddingBottom = $derived.by(() => (items.length - visibleEnd) * itemHeight);
17
- let visibleItems = $derived.by(() => items.slice(visibleStart, visibleEnd));
18
- function handleScroll(event) {
19
- scrollTop = event.currentTarget.scrollTop;
20
- }
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ type Props = {
5
+ items: any[];
6
+ itemHeight: number;
7
+ containerHeight: number;
8
+ itemSnippet: Snippet<[item: any, index: number]>;
9
+ buffer?: number;
10
+ };
11
+
12
+ let {
13
+ items = [],
14
+ itemHeight,
15
+ containerHeight,
16
+ buffer = 2,
17
+ itemSnippet,
18
+ ...rest
19
+ }: Props = $props();
20
+
21
+ let scrollTop = $state(0);
22
+
23
+ let totalHeight = $derived.by(() => items.length * itemHeight);
24
+
25
+ let visibleStart = $derived.by(() => Math.max(Math.floor(scrollTop / itemHeight) - buffer, 0));
26
+ let visibleEnd = $derived.by(() =>
27
+ Math.min(Math.ceil((scrollTop + containerHeight) / itemHeight) + buffer, items.length)
28
+ );
29
+
30
+ let paddingTop = $derived.by(() => visibleStart * itemHeight);
31
+ let paddingBottom = $derived.by(() => (items.length - visibleEnd) * itemHeight);
32
+
33
+ let visibleItems = $derived.by(() => items.slice(visibleStart, visibleEnd));
34
+
35
+ function handleScroll(event: Event) {
36
+ scrollTop = (event.currentTarget as HTMLElement).scrollTop;
37
+ }
21
38
  </script>
22
39
 
23
40
  <div