fluid-ui-svelte 0.3.0 → 0.3.2

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.
@@ -11,7 +11,7 @@
11
11
  children,
12
12
  ...rest
13
13
  }: {
14
- onclick: (event: Event, buttonState: { inProgress: boolean }) => Promise<void>;
14
+ onclick: (event: Event, buttonState: { inProgress: boolean }) => Promise<unknown>;
15
15
  class?: string;
16
16
  overrideDefaultStyling?: boolean;
17
17
  loadingPlaceholder?: Snippet;
@@ -3,7 +3,7 @@ import { type Snippet } from 'svelte';
3
3
  type $$ComponentProps = {
4
4
  onclick: (event: Event, buttonState: {
5
5
  inProgress: boolean;
6
- }) => Promise<void>;
6
+ }) => Promise<unknown>;
7
7
  class?: string;
8
8
  overrideDefaultStyling?: boolean;
9
9
  loadingPlaceholder?: Snippet;
@@ -1,9 +1,8 @@
1
1
  <script lang="ts">
2
- import Container from '../base/Container.svelte';
3
- import type { Snippet } from 'svelte';
4
- import { slide, type TransitionConfig } from 'svelte/transition';
5
- import Button from '../base/Button.svelte';
2
+ import { Container, Button } from '../base/index.js';
6
3
  import { mergeClasses } from '../utilities/mergeClasses.js';
4
+ import { slide, type TransitionConfig } from 'svelte/transition';
5
+ import type { Snippet } from 'svelte';
7
6
 
8
7
  const {
9
8
  variation = '',
@@ -14,7 +13,7 @@
14
13
  transitionDuration = 250
15
14
  }: {
16
15
  variation?: string;
17
- componentId: string;
16
+ componentId?: string;
18
17
  header: Snippet<[options: { isExpanded: boolean }]>;
19
18
  body: Snippet;
20
19
  transitionFunction?: (node: Element, params?: any) => TransitionConfig;
@@ -1,8 +1,8 @@
1
- import type { Snippet } from 'svelte';
2
1
  import { type TransitionConfig } from 'svelte/transition';
2
+ import type { Snippet } from 'svelte';
3
3
  type $$ComponentProps = {
4
4
  variation?: string;
5
- componentId: string;
5
+ componentId?: string;
6
6
  header: Snippet<[options: {
7
7
  isExpanded: boolean;
8
8
  }]>;
@@ -1,7 +1,5 @@
1
1
  <script lang="ts">
2
- import Container from '../base/Container.svelte';
3
- import Button from '../base/Button.svelte';
4
- import Text from '../base/Text.svelte';
2
+ import { Container, Button, Text } from '../base/index.js';
5
3
  import {
6
4
  applyDate,
7
5
  generateCalendarCellStyles,
@@ -11,23 +9,24 @@
11
9
 
12
10
  let {
13
11
  variant = '',
12
+ componentId,
14
13
  currentDate = new Date().toISOString(),
15
14
  startDate = $bindable(),
16
15
  endDate = $bindable(),
16
+ weekDays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
17
+ calendarDays = generateDaysOfTheMonthFromDate(new Date().toISOString()),
17
18
  hideRollingDays = false
18
19
  }: {
19
20
  variant?: string;
21
+ componentId?: string;
20
22
  currentDate?: string;
21
23
  startDate?: string;
22
24
  endDate?: string;
25
+ weekDays?: Array<string>;
26
+ calendarDays?: Array<string>;
23
27
  hideRollingDays?: boolean;
24
28
  } = $props();
25
29
 
26
- const componentState = $state({
27
- weekDays: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
28
- calendarDays: generateDaysOfTheMonthFromDate(new Date().toISOString())
29
- });
30
-
31
30
  function dateSelectionHandler(selectedDate: string) {
32
31
  const result = applyDate({ startDate, endDate: endDate }, selectedDate);
33
32
  startDate = result.startDate;
@@ -35,20 +34,20 @@
35
34
  }
36
35
 
37
36
  $effect(() => {
38
- componentState.calendarDays = generateDaysOfTheMonthFromDate(currentDate);
37
+ calendarDays = generateDaysOfTheMonthFromDate(currentDate);
39
38
  });
40
39
  </script>
41
40
 
42
- <Container class={mergeClasses('fluid-calendar-wrapper', variant)}>
41
+ <Container id={componentId} class={mergeClasses('fluid-calendar-wrapper', variant)}>
43
42
  <Container class={mergeClasses('fluid-calendar-header', variant)}>
44
43
  <Text>{new Date(currentDate).toLocaleString('default', { month: 'long' })}</Text>
45
44
  </Container>
46
45
  <Container class={mergeClasses('fluid-calendar-body', variant)}>
47
- {#each componentState.weekDays as day}
46
+ {#each weekDays as day}
48
47
  <Text>{day}</Text>
49
48
  {/each}
50
49
 
51
- {#each componentState.calendarDays as cellDay}
50
+ {#each calendarDays as cellDay}
52
51
  <Button
53
52
  onclick={async () => dateSelectionHandler(cellDay)}
54
53
  class={mergeClasses(
@@ -1,8 +1,11 @@
1
1
  type $$ComponentProps = {
2
2
  variant?: string;
3
+ componentId?: string;
3
4
  currentDate?: string;
4
5
  startDate?: string;
5
6
  endDate?: string;
7
+ weekDays?: Array<string>;
8
+ calendarDays?: Array<string>;
6
9
  hideRollingDays?: boolean;
7
10
  };
8
11
  declare const Calendar: import("svelte").Component<$$ComponentProps, {}, "startDate" | "endDate">;
@@ -0,0 +1,114 @@
1
+ <script lang="ts" generics="T">
2
+ import { Container } from '../base/index.js';
3
+ import { mergeClasses } from '../utilities/mergeClasses.js';
4
+ import { scrollToIndex, getSwipeDirection } from '../utilities/carousel.js';
5
+ import type { Snippet } from 'svelte';
6
+
7
+ let {
8
+ componentId = crypto.randomUUID(),
9
+ variant = '',
10
+ orientation = 'horizontal',
11
+ activeIndex = $bindable(0),
12
+ autoplay = false,
13
+ autoplayDuration = 1000,
14
+ items,
15
+ itemTemplate
16
+ }: {
17
+ componentId?: string;
18
+ variant?: string;
19
+ orientation?: 'horizontal' | 'vertical';
20
+ activeIndex?: number;
21
+ autoplay?: boolean;
22
+ autoplayDuration?: number;
23
+ items: Array<T>;
24
+ itemTemplate: Snippet<[{ item: T; index: number }]>;
25
+ } = $props();
26
+
27
+ let touchStartX = 0;
28
+ let touchStartY = 0;
29
+
30
+ function handleTouchStart(e: TouchEvent) {
31
+ e.stopPropagation();
32
+ e.preventDefault();
33
+ touchStartX = e.changedTouches[0].screenX;
34
+ touchStartY = e.changedTouches[0].screenY;
35
+ }
36
+
37
+ function handleTouchMove(e: TouchEvent) {
38
+ if (!touchStartX || !touchStartY) return;
39
+
40
+ const touchCurrentX = e.changedTouches[0].screenX;
41
+ const touchCurrentY = e.changedTouches[0].screenY;
42
+
43
+ const diffX = Math.abs(touchCurrentX - touchStartX);
44
+ const diffY = Math.abs(touchCurrentY - touchStartY);
45
+
46
+ // If horizontal carousel and horizontal swipe is dominant
47
+ if (orientation === 'horizontal') {
48
+ if (diffX > diffY && diffX > 5) {
49
+ e.preventDefault();
50
+ e.stopPropagation();
51
+ }
52
+ } else {
53
+ // Vertical carousel
54
+ if (diffY > diffX && diffY > 5) {
55
+ e.preventDefault();
56
+ e.stopPropagation();
57
+ }
58
+ }
59
+ }
60
+
61
+ function handleTouchEnd(e: TouchEvent) {
62
+ e.stopPropagation();
63
+ e.preventDefault();
64
+ const touchEndX = e.changedTouches[0].screenX;
65
+ const touchEndY = e.changedTouches[0].screenY;
66
+
67
+ const direction = getSwipeDirection(
68
+ touchStartX,
69
+ touchStartY,
70
+ touchEndX,
71
+ touchEndY,
72
+ 50,
73
+ orientation
74
+ );
75
+
76
+ if (direction === 'next') {
77
+ activeIndex = Math.min(activeIndex + 1, items.length - 1);
78
+ } else if (direction === 'prev') {
79
+ activeIndex = Math.max(activeIndex - 1, 0);
80
+ }
81
+ }
82
+
83
+ $effect(() => {
84
+ if (autoplay && items.length > 0) {
85
+ const interval = setInterval(() => {
86
+ activeIndex = (activeIndex + 1) % items.length;
87
+ }, autoplayDuration);
88
+ return () => clearInterval(interval);
89
+ }
90
+ });
91
+
92
+ $effect(() => {
93
+ if (componentId && items.length > 1) {
94
+ scrollToIndex(componentId, activeIndex, items.length, orientation);
95
+ }
96
+ });
97
+ </script>
98
+
99
+ <Container
100
+ id={componentId}
101
+ ontouchstart={handleTouchStart}
102
+ ontouchmove={handleTouchMove}
103
+ ontouchend={handleTouchEnd}
104
+ class={mergeClasses(
105
+ `fluid-carousel-container ${orientation === 'vertical' ? 'h-full snap-y flex-col overflow-y-auto' : 'flex snap-x overflow-x-auto'}`,
106
+ variant
107
+ )}
108
+ >
109
+ {#each items as item, index}
110
+ <Container class={mergeClasses('fluid-carousel-item', variant)} overrideDefaultStyling>
111
+ {@render itemTemplate({ item, index })}
112
+ </Container>
113
+ {/each}
114
+ </Container>
@@ -1,26 +1,37 @@
1
- export default Carousel;
2
- type Carousel = SvelteComponent<{
3
- [x: string]: never;
4
- }, {
5
- [evt: string]: CustomEvent<any>;
6
- }, {}> & {
7
- $$bindings?: string | undefined;
8
- };
9
- declare const Carousel: $$__sveltets_2_IsomorphicComponent<{
10
- [x: string]: never;
11
- }, {
12
- [evt: string]: CustomEvent<any>;
13
- }, {}, {}, string>;
14
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
15
- new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
16
- $$bindings?: Bindings;
17
- } & Exports;
18
- (internal: unknown, props: {
19
- $$events?: Events;
20
- $$slots?: Slots;
21
- }): Exports & {
22
- $set?: any;
23
- $on?: any;
1
+ import type { Snippet } from 'svelte';
2
+ declare function $$render<T>(): {
3
+ props: {
4
+ componentId?: string;
5
+ variant?: string;
6
+ orientation?: "horizontal" | "vertical";
7
+ activeIndex?: number;
8
+ autoplay?: boolean;
9
+ autoplayDuration?: number;
10
+ items: Array<T>;
11
+ itemTemplate: Snippet<[{
12
+ item: T;
13
+ index: number;
14
+ }]>;
24
15
  };
25
- z_$$bindings?: Bindings;
16
+ exports: {};
17
+ bindings: "activeIndex";
18
+ slots: {};
19
+ events: {};
20
+ };
21
+ declare class __sveltets_Render<T> {
22
+ props(): ReturnType<typeof $$render<T>>['props'];
23
+ events(): ReturnType<typeof $$render<T>>['events'];
24
+ slots(): ReturnType<typeof $$render<T>>['slots'];
25
+ bindings(): "activeIndex";
26
+ exports(): {};
26
27
  }
28
+ interface $$IsomorphicComponent {
29
+ new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
30
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
31
+ } & ReturnType<__sveltets_Render<T>['exports']>;
32
+ <T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
33
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
34
+ }
35
+ declare const Carousel: $$IsomorphicComponent;
36
+ type Carousel<T> = InstanceType<typeof Carousel<T>>;
37
+ export default Carousel;
@@ -5,18 +5,24 @@
5
5
  const {
6
6
  variation,
7
7
  code = '',
8
- language = ''
8
+ language = '',
9
+ showLineNumbers = true
9
10
  }: {
10
11
  variation?: string;
11
12
  code?: string;
12
13
  language?: string;
14
+ showLineNumbers?: boolean;
13
15
  } = $props();
14
16
  </script>
15
17
 
16
18
  <Container class="fluid-code-block-container">
17
19
  {#each code.split('\n') as line, index}
18
20
  <Container class="fluid-code-block-row">
19
- <Container class="fluid-code-block-index"><Text class="select-none">{index}</Text></Container>
21
+ {#if showLineNumbers}
22
+ <Container class="fluid-code-block-index"
23
+ ><Text class="select-none">{index}</Text></Container
24
+ >
25
+ {/if}
20
26
  <Container class="fluid-code-block-content">
21
27
  <Text type="pre">
22
28
  <Text type="code" class={'language-' + language}>{line}</Text>
@@ -2,6 +2,7 @@ type $$ComponentProps = {
2
2
  variation?: string;
3
3
  code?: string;
4
4
  language?: string;
5
+ showLineNumbers?: boolean;
5
6
  };
6
7
  declare const CodeBlock: import("svelte").Component<$$ComponentProps, {}, "">;
7
8
  type CodeBlock = ReturnType<typeof CodeBlock>;
@@ -0,0 +1,88 @@
1
+ <script lang="ts">
2
+ import { Container } from '../base/index.js';
3
+ import { mergeClasses } from '../utilities/mergeClasses.js';
4
+ import { fade, fly, type TransitionConfig } from 'svelte/transition';
5
+ import type { Snippet } from 'svelte';
6
+
7
+ let {
8
+ variation = '',
9
+ componentId,
10
+ isOpen = $bindable(false),
11
+ position = 'left',
12
+ closeOnBackdropClick = true,
13
+ scrollLock = true,
14
+ transitionFn = (node: Element, params?: any) => {
15
+ return {};
16
+ },
17
+ transitionParams = {},
18
+ backdropTransitionFn = (node: Element, params?: any) => {
19
+ return {};
20
+ },
21
+ backdropTransitionParams,
22
+ children
23
+ }: {
24
+ isOpen?: boolean;
25
+ position?: 'left' | 'right' | 'top' | 'bottom';
26
+ closeOnBackdropClick?: boolean;
27
+ scrollLock?: boolean;
28
+ variation?: string;
29
+ componentId?: string;
30
+ transitionFn?: (node: Element, params?: any) => TransitionConfig;
31
+ transitionParams?: TransitionConfig & { x?: number; y?: number };
32
+ backdropTransitionFn?: (node: Element, params?: any) => TransitionConfig;
33
+ backdropTransitionParams?: TransitionConfig & { x?: number; y?: number };
34
+ children: Snippet;
35
+ } = $props();
36
+
37
+ // Programmatic anchoring mapping to avoid repetitive CSS classes
38
+ const positionClasses: Record<string, string> = {
39
+ left: 'left-0 top-0 bottom-0 h-full border-r',
40
+ right: 'right-0 top-0 bottom-0 h-full border-l',
41
+ top: 'top-0 right-0 left-0 w-full border-b',
42
+ bottom: 'bottom-0 right-0 left-0 w-full border-t'
43
+ };
44
+
45
+ const handleKeyDown = (event: KeyboardEvent) => {
46
+ if (event.key === 'Escape' && isOpen) {
47
+ isOpen = false;
48
+ }
49
+ };
50
+
51
+ $effect(() => {
52
+ if (isOpen) {
53
+ const originalStyle = window.getComputedStyle(document.body).overflow;
54
+ if (scrollLock) document.body.style.overflow = 'hidden';
55
+ window.addEventListener('keydown', handleKeyDown);
56
+
57
+ return () => {
58
+ if (scrollLock) document.body.style.overflow = originalStyle;
59
+ window.removeEventListener('keydown', handleKeyDown);
60
+ };
61
+ }
62
+ });
63
+ </script>
64
+
65
+ {#if isOpen}
66
+ <Container
67
+ id={componentId}
68
+ class={mergeClasses(variation, 'fluid-drawer-container')}
69
+ transitionFn={backdropTransitionFn}
70
+ transitionParams={backdropTransitionParams}
71
+ onclick={async () => {
72
+ if (closeOnBackdropClick) isOpen = false;
73
+ }}
74
+ overrideDefaultStyling
75
+ >
76
+ <Container
77
+ role="dialog"
78
+ aria-modal="true"
79
+ onclick={(event) => event.stopPropagation()}
80
+ class={mergeClasses(variation, `fluid-drawer-panel ${positionClasses[position]}`)}
81
+ {transitionFn}
82
+ {transitionParams}
83
+ overrideDefaultStyling
84
+ >
85
+ {@render children()}
86
+ </Container>
87
+ </Container>
88
+ {/if}
@@ -0,0 +1,24 @@
1
+ import { type TransitionConfig } from 'svelte/transition';
2
+ import type { Snippet } from 'svelte';
3
+ type $$ComponentProps = {
4
+ isOpen?: boolean;
5
+ position?: 'left' | 'right' | 'top' | 'bottom';
6
+ closeOnBackdropClick?: boolean;
7
+ scrollLock?: boolean;
8
+ variation?: string;
9
+ componentId?: string;
10
+ transitionFn?: (node: Element, params?: any) => TransitionConfig;
11
+ transitionParams?: TransitionConfig & {
12
+ x?: number;
13
+ y?: number;
14
+ };
15
+ backdropTransitionFn?: (node: Element, params?: any) => TransitionConfig;
16
+ backdropTransitionParams?: TransitionConfig & {
17
+ x?: number;
18
+ y?: number;
19
+ };
20
+ children: Snippet;
21
+ };
22
+ declare const Drawer: import("svelte").Component<$$ComponentProps, {}, "isOpen">;
23
+ type Drawer = ReturnType<typeof Drawer>;
24
+ export default Drawer;
@@ -1,65 +0,0 @@
1
- <script lang="ts">
2
- import Container from '../base/Container.svelte';
3
- import { onMount } from 'svelte';
4
- import { Text } from '../base/index.js';
5
- import {
6
- draw,
7
- generateCropAreaState,
8
- handleMouseDown,
9
- handleMouseMove,
10
- handleMouseUp
11
- } from '../utilities/imageCrop.js';
12
- const {
13
- imageFile,
14
- cropAreaShape = 'rectangle'
15
- }: { imageFile: File; cropAreaShape?: 'rectangle' | 'circle' } = $props();
16
-
17
- let canvasElement: HTMLCanvasElement;
18
- let image: HTMLImageElement | undefined = $state();
19
-
20
- const cropAreaState = $state(generateCropAreaState(cropAreaShape));
21
-
22
- onMount(() => {
23
- const fileReader = new FileReader();
24
- fileReader.readAsDataURL(imageFile);
25
- fileReader.onload = () => {
26
- const loadedImage = new Image();
27
- loadedImage.src = fileReader.result as string;
28
- loadedImage.onload = () => {
29
- // Set the reactive image state once it's fully loaded
30
- image = loadedImage;
31
- };
32
- };
33
- });
34
-
35
- $effect(() => {
36
- // Only run if the canvas and image are ready
37
- if (canvasElement && image) {
38
- // This block performs the ONE-TIME setup when the image first loads.
39
- if (canvasElement.width !== image.naturalWidth) {
40
- canvasElement.width = image.naturalWidth;
41
- canvasElement.height = image.naturalHeight;
42
- cropAreaState.cropArea.width = canvasElement.width / 2;
43
- cropAreaState.cropArea.height = canvasElement.height / 2;
44
- cropAreaState.cropArea.x = (canvasElement.width - cropAreaState.cropArea.width) / 2;
45
- cropAreaState.cropArea.y = (canvasElement.height - cropAreaState.cropArea.height) / 2;
46
- }
47
-
48
- // This will now run on the initial setup AND any time cropAreaState changes.
49
- draw(canvasElement, image, cropAreaState);
50
- }
51
- });
52
- </script>
53
-
54
- <Container>
55
- <Text>Canvas to Draw On</Text>
56
- <canvas
57
- class="size-full"
58
- bind:this={canvasElement}
59
- onpointerdown={(event) => handleMouseDown(event, cropAreaState, canvasElement)}
60
- onpointermove={(event) => handleMouseMove(event, cropAreaState, canvasElement)}
61
- onpointerup={() => handleMouseUp(cropAreaState)}
62
- onpointercancel={() => handleMouseUp(cropAreaState)}
63
- onpointerleave={() => handleMouseUp(cropAreaState)}
64
- ></canvas>
65
- </Container>
@@ -1,7 +1,26 @@
1
- type $$ComponentProps = {
2
- imageFile: File;
3
- cropAreaShape?: 'rectangle' | 'circle';
4
- };
5
- declare const ImageCrop: import("svelte").Component<$$ComponentProps, {}, "">;
6
- type ImageCrop = ReturnType<typeof ImageCrop>;
7
1
  export default ImageCrop;
2
+ type ImageCrop = SvelteComponent<{
3
+ [x: string]: never;
4
+ }, {
5
+ [evt: string]: CustomEvent<any>;
6
+ }, {}> & {
7
+ $$bindings?: string | undefined;
8
+ };
9
+ declare const ImageCrop: $$__sveltets_2_IsomorphicComponent<{
10
+ [x: string]: never;
11
+ }, {
12
+ [evt: string]: CustomEvent<any>;
13
+ }, {}, {}, string>;
14
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
15
+ new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
16
+ $$bindings?: Bindings;
17
+ } & Exports;
18
+ (internal: unknown, props: {
19
+ $$events?: Events;
20
+ $$slots?: Slots;
21
+ }): Exports & {
22
+ $set?: any;
23
+ $on?: any;
24
+ };
25
+ z_$$bindings?: Bindings;
26
+ }
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
+ import { Container } from '../base/index.js';
2
3
  import type { HTMLAttributes } from 'svelte/elements';
3
4
  import type { Snippet } from 'svelte';
4
- import Container from '../base/Container.svelte';
5
5
 
6
6
  const {
7
7
  title = '',
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
- import type { HTMLAttributes } from 'svelte/elements';
3
2
  import { Button } from '../base/index.js';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
4
 
5
5
  let {
6
6
  onswitch,
@@ -1,6 +1,8 @@
1
1
  export { default as Accordion } from './Accordion.svelte';
2
2
  export { default as Calendar } from './Calendar.svelte';
3
+ export { default as Carousel } from './Carousel.svelte';
3
4
  export { default as CodeBlock } from './CodeBlock.svelte';
5
+ export { default as Drawer } from './Drawer.svelte';
4
6
  export { default as ImageCrop } from './ImageCrop.svelte';
5
7
  export { default as Page } from './Page.svelte';
6
8
  export { default as Switch } from './Switch.svelte';
@@ -1,6 +1,8 @@
1
1
  export { default as Accordion } from './Accordion.svelte';
2
2
  export { default as Calendar } from './Calendar.svelte';
3
+ export { default as Carousel } from './Carousel.svelte';
3
4
  export { default as CodeBlock } from './CodeBlock.svelte';
5
+ export { default as Drawer } from './Drawer.svelte';
4
6
  export { default as ImageCrop } from './ImageCrop.svelte';
5
7
  export { default as Page } from './Page.svelte';
6
8
  export { default as Switch } from './Switch.svelte';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ // TODO
@@ -0,0 +1,2 @@
1
+ export declare function scrollToIndex(componentId: string, activeIndex: number, totalItems: number, orientation?: 'horizontal' | 'vertical'): void;
2
+ export declare function getSwipeDirection(touchStartX: number, touchStartY: number, touchEndX: number, touchEndY: number, threshold?: number, orientation?: 'horizontal' | 'vertical'): 'next' | 'prev' | null;
@@ -0,0 +1,27 @@
1
+ export function scrollToIndex(componentId, activeIndex, totalItems, orientation = 'horizontal') {
2
+ const element = document.getElementById(componentId);
3
+ if (!element || totalItems <= 0)
4
+ return;
5
+ const scrollWidth = orientation === 'horizontal' ? element.scrollWidth : element.scrollHeight;
6
+ const itemWidth = scrollWidth / totalItems;
7
+ const targetPosition = activeIndex * itemWidth;
8
+ element.scrollTo({
9
+ left: orientation === 'horizontal' ? targetPosition : 0,
10
+ top: orientation === 'vertical' ? targetPosition : 0
11
+ });
12
+ }
13
+ export function getSwipeDirection(touchStartX, touchStartY, touchEndX, touchEndY, threshold = 50, orientation = 'horizontal') {
14
+ const diffX = touchStartX - touchEndX;
15
+ const diffY = touchStartY - touchEndY;
16
+ if (orientation === 'horizontal') {
17
+ if (Math.abs(diffX) > threshold) {
18
+ return diffX > 0 ? 'next' : 'prev';
19
+ }
20
+ }
21
+ else {
22
+ if (Math.abs(diffY) > threshold) {
23
+ return diffY > 0 ? 'next' : 'prev';
24
+ }
25
+ }
26
+ return null;
27
+ }
@@ -0,0 +1,15 @@
1
+ export declare const codeBlockContents: {
2
+ gettingStartedAppCss: string;
3
+ gettingStartedUsage: string;
4
+ drawerBasicUsage: string;
5
+ drawerPositions: string;
6
+ drawerAnimated: string;
7
+ drawerFlyAnimation: string;
8
+ calendarSingle: string;
9
+ calendarDual: string;
10
+ calendarSixMonth: string;
11
+ calendarRange: string;
12
+ calendarMulti: string;
13
+ carouselSlide: string;
14
+ carouselFade: string;
15
+ };
@@ -0,0 +1,298 @@
1
+ // Parsing errors happen in code editor when imports and script tags used inside code block component's contents.
2
+ // To prevent this we import usage examples from here.
3
+ const gettingStartedAppCss = `// src/routes/+layout.svelte
4
+ import '../app.css';`;
5
+ const gettingStartedUsage = `<script>
6
+ // Import a base element for custom implementation
7
+ import { Button } from 'fluid-ui-svelte/base';
8
+
9
+ // Import a pre-built component
10
+ import { Accordion } from 'fluid-ui-svelte/components';
11
+ </script>
12
+
13
+ <Button onclick={handleClick}>Submit</Button>
14
+
15
+ <Accordion>
16
+ <!-- Accordion content -->
17
+ </Accordion>`;
18
+ const drawerBasicUsage = `<script>
19
+ import { Drawer } from 'fluid-ui-svelte/components';
20
+ import { Button, Text } from 'fluid-ui-svelte/base';
21
+
22
+ let isBasicDrawerOpen = $state(false);
23
+ </script>
24
+
25
+ <Button onclick={async () => isBasicDrawerOpen = true}>Open Drawer</Button>
26
+
27
+ <Drawer bind:isOpen={isBasicDrawerOpen} position="left">
28
+ <div class="flex flex-col gap-4">
29
+ <Text type="h2">Drawer Content</Text>
30
+ <Text>This is some content inside the drawer.</Text>
31
+ <Button onclick={async () => isBasicDrawerOpen = false}>Close</Button>
32
+ </div>
33
+ </Drawer>`;
34
+ const drawerPositions = `<script>
35
+ import { Drawer } from 'fluid-ui-svelte/components';
36
+ let left = $state(false);
37
+ let right = $state(false);
38
+ let top = $state(false);
39
+ let bottom = $state(false);
40
+ </script>
41
+
42
+ <Button onclick={async () => left = true}>Left</Button>
43
+ <Button onclick={async () => right = true}>Right</Button>
44
+ <Button onclick={async () => top = true}>Top</Button>
45
+ <Button onclick={async () => bottom = true}>Bottom</Button>
46
+
47
+ <Drawer bind:isOpen={left} position="left">Left Drawer</Drawer>
48
+ <Drawer bind:isOpen={right} position="right">Right Drawer</Drawer>
49
+ <Drawer bind:isOpen={top} position="top">Top Drawer</Drawer>
50
+ <Drawer bind:isOpen={bottom} position="bottom">Bottom Drawer</Drawer>`;
51
+ const drawerAnimated = `<script>
52
+ import { Drawer } from 'fluid-ui-svelte/components';
53
+ import { fly, fade } from 'svelte/transition';
54
+
55
+ let isAnimatedDrawerOpen = $state(false);
56
+ </script>
57
+
58
+ <Button onclick={async () => isAnimatedDrawerOpen = true}>Open Animated</Button>
59
+
60
+ <Drawer
61
+ bind:isOpen={isAnimatedDrawerOpen}
62
+ position="right"
63
+ transitionFn={fly}
64
+ transitionParams={{ x: 500, duration: 500 }}
65
+ backdropTransitionFn={fade}
66
+ >
67
+ Animated Content
68
+ </Drawer>`;
69
+ const drawerFlyAnimation = `<script>
70
+ import { Drawer } from 'fluid-ui-svelte/components';
71
+ import { fly } from 'svelte/transition';
72
+
73
+ let isFlyDrawerOpen = $state(false);
74
+ </script>
75
+
76
+ <Button onclick={async () => isFlyDrawerOpen = true}>Open Fly Drawer</Button>
77
+
78
+ <Drawer
79
+ bind:isOpen={isFlyDrawerOpen}
80
+ position="bottom"
81
+ transitionFn={fly}
82
+ transitionParams={{ y: 200, duration: 800 }}
83
+ >
84
+ Fly Content
85
+ </Drawer>`;
86
+ const calendarSingle = `<script>
87
+ import { Calendar } from 'fluid-ui-svelte/components';
88
+ import { Button, Container } from 'fluid-ui-svelte/base';
89
+
90
+ let currentDate = $state(new Date().toISOString());
91
+
92
+ const changeMonth = (increment: number) => {
93
+ const date = new Date(currentDate);
94
+ date.setMonth(date.getMonth() + increment);
95
+ currentDate = date.toISOString();
96
+ };
97
+ </script>
98
+
99
+ <Container class="flex flex-col gap-4">
100
+ <Container class="flex gap-2">
101
+ <Button onclick={() => changeMonth(-1)}>Prev</Button>
102
+ <Button onclick={() => changeMonth(1)}>Next</Button>
103
+ </Container>
104
+ <Calendar bind:currentDate componentId="calendar-single" />
105
+ </Container>`;
106
+ const calendarDual = `<script>
107
+ import { Calendar } from 'fluid-ui-svelte/components';
108
+ import { Button, Container } from 'fluid-ui-svelte/base';
109
+
110
+ let baseDate = $state(new Date().toISOString());
111
+
112
+ // Helper to get next month relative to base
113
+ const getOffsetDate = (offset: number) => {
114
+ const d = new Date(baseDate);
115
+ d.setMonth(d.getMonth() + offset);
116
+ return d.toISOString();
117
+ };
118
+
119
+ const changeMonth = (increment: number) => {
120
+ const d = new Date(baseDate);
121
+ d.setMonth(d.getMonth() + increment);
122
+ baseDate = d.toISOString();
123
+ };
124
+ </script>
125
+
126
+ <Container class="flex flex-col gap-4">
127
+ <Container class="flex gap-2">
128
+ <Button onclick={() => changeMonth(-1)}>Prev</Button>
129
+ <Button onclick={() => changeMonth(1)}>Next</Button>
130
+ </Container>
131
+ <Container class="flex gap-8 flex-wrap">
132
+ <Calendar currentDate={baseDate} componentId="cal-1" />
133
+ <Calendar currentDate={getOffsetDate(1)} componentId="cal-2" />
134
+ </Container>
135
+ </Container>`;
136
+ const calendarSixMonth = `<script>
137
+ import { Calendar } from 'fluid-ui-svelte/components';
138
+ import { Button, Container } from 'fluid-ui-svelte/base';
139
+
140
+ let baseDate = $state(new Date().toISOString());
141
+
142
+ const getOffsetDate = (offset: number) => {
143
+ const d = new Date(baseDate);
144
+ d.setMonth(d.getMonth() + offset);
145
+ return d.toISOString();
146
+ };
147
+
148
+ const changeMonth = (increment: number) => {
149
+ const d = new Date(baseDate);
150
+ d.setMonth(d.getMonth() + increment);
151
+ baseDate = d.toISOString();
152
+ };
153
+ </script>
154
+
155
+ <Container class="flex flex-col gap-4">
156
+ <Container class="flex gap-2">
157
+ <Button onclick={() => changeMonth(-1)}>Prev</Button>
158
+ <Button onclick={() => changeMonth(1)}>Next</Button>
159
+ </Container>
160
+ <Container class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
161
+ {#each Array(6) as _, i}
162
+ <Calendar currentDate={getOffsetDate(i)} componentId="cal-{i}" />
163
+ {/each}
164
+ </Container>
165
+ </Container>`;
166
+ const calendarRange = `<script>
167
+ import { Calendar } from 'fluid-ui-svelte/components';
168
+ import { Button, Container, Text } from 'fluid-ui-svelte/base';
169
+
170
+ let baseDate = $state(new Date().toISOString());
171
+ let startDate = $state<string>();
172
+ let endDate = $state<string>();
173
+
174
+ const getOffsetDate = (offset: number) => {
175
+ const d = new Date(baseDate);
176
+ d.setMonth(d.getMonth() + offset);
177
+ return d.toISOString();
178
+ };
179
+
180
+ const changeMonth = (inc: number) => {
181
+ const d = new Date(baseDate);
182
+ d.setMonth(d.getMonth() + inc);
183
+ baseDate = d.toISOString();
184
+ };
185
+ </script>
186
+
187
+ <Container class="flex flex-col gap-4">
188
+ <Container class="flex justify-between items-center">
189
+ <Container class="flex gap-2">
190
+ <Button onclick={() => changeMonth(-1)}>Prev</Button>
191
+ <Button onclick={() => changeMonth(1)}>Next</Button>
192
+ </Container>
193
+ <Text class="text-sm font-mono">
194
+ {startDate || '...'} to {endDate || '...'}
195
+ </Text>
196
+ </Container>
197
+
198
+ <Container class="flex gap-8 flex-wrap">
199
+ <Calendar
200
+ currentDate={baseDate}
201
+ bind:startDate
202
+ bind:endDate
203
+ componentId="cal-range-1"
204
+ />
205
+ <Calendar
206
+ currentDate={getOffsetDate(1)}
207
+ bind:startDate
208
+ bind:endDate
209
+ componentId="cal-range-2"
210
+ />
211
+ </Container>
212
+ </Container>`;
213
+ const calendarMulti = `<script>
214
+ import { Calendar } from 'fluid-ui-svelte/components';
215
+ import { Button, Container } from 'fluid-ui-svelte/base';
216
+
217
+ const multiCalendarState = $state({
218
+ currentDate: new Date().toISOString(),
219
+ startDate: '',
220
+ endDate: ''
221
+ });
222
+
223
+ const changeMonthMulti = (inc: number) => {
224
+ const d = new Date(multiCalendarState.currentDate);
225
+ d.setMonth(d.getMonth() + inc);
226
+ multiCalendarState.currentDate = d.toISOString();
227
+ };
228
+ </script>
229
+
230
+ <Container class="flex flex-col gap-4">
231
+ <Container class="flex gap-2">
232
+ <Button onclick={() => changeMonthMulti(-1)}>Prev</Button>
233
+ <Button onclick={() => changeMonthMulti(1)}>Next</Button>
234
+ </Container>
235
+
236
+ <Container class="flex gap-8 flex-wrap">
237
+ <Calendar
238
+ bind:currentDate={multiCalendarState.currentDate}
239
+ bind:startDate={multiCalendarState.startDate}
240
+ bind:endDate={multiCalendarState.endDate}
241
+ />
242
+ <Calendar
243
+ currentDate={new Date(new Date(multiCalendarState.currentDate).setMonth(new Date(multiCalendarState.currentDate).getMonth() + 1)).toISOString()}
244
+ bind:startDate={multiCalendarState.startDate}
245
+ bind:endDate={multiCalendarState.endDate}
246
+ />
247
+ </Container>
248
+ </Container>`;
249
+ const carouselSlide = `<script>
250
+ import { Carousel } from 'fluid-ui-svelte/components';
251
+ import { Image } from 'fluid-ui-svelte/base';
252
+
253
+ const items = [
254
+ { src: 'https://via.placeholder.com/800x400?text=Slide+1', alt: 'Slide 1' },
255
+ { src: 'https://via.placeholder.com/800x400?text=Slide+2', alt: 'Slide 2' },
256
+ { src: 'https://via.placeholder.com/800x400?text=Slide+3', alt: 'Slide 3' }
257
+ ];
258
+ </script>
259
+
260
+ <Carousel {items} type="slide" loop>
261
+ {#snippet children(item)}
262
+ <Image src={item.src} alt={item.alt} class="w-full h-64 object-cover" />
263
+ {/snippet}
264
+ </Carousel>`;
265
+ const carouselFade = `<script>
266
+ import { Carousel } from 'fluid-ui-svelte/components';
267
+ import { Text } from 'fluid-ui-svelte/base';
268
+
269
+ const quotes = [
270
+ { text: "Innovation is key.", author: "Tech CEO" },
271
+ { text: "Design is intelligence made visible.", author: "Designer" },
272
+ { text: "Simplicity is the ultimate sophistication.", author: "Da Vinci" }
273
+ ];
274
+ </script>
275
+
276
+ <Carousel {items: quotes} type="fade" autoplay autoplayInterval={4000}>
277
+ {#snippet children(quote)}
278
+ <div class="h-64 flex flex-col items-center justify-center bg-neutral-100 dark:bg-neutral-800 p-8 text-center">
279
+ <Text type="h3" class="text-2xl font-bold mb-4">"{quote.text}"</Text>
280
+ <Text class="text-neutral-500">- {quote.author}</Text>
281
+ </div>
282
+ {/snippet}
283
+ </Carousel>`;
284
+ export const codeBlockContents = {
285
+ gettingStartedAppCss,
286
+ gettingStartedUsage,
287
+ drawerBasicUsage,
288
+ drawerPositions,
289
+ drawerAnimated,
290
+ drawerFlyAnimation,
291
+ calendarSingle,
292
+ calendarDual,
293
+ calendarSixMonth,
294
+ calendarRange,
295
+ calendarMulti,
296
+ carouselSlide,
297
+ carouselFade
298
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluid-ui-svelte",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "author": {
5
5
  "name": "Emre Ayaz",
6
6
  "email": "ayazthemre@gmail.com"