@immich/ui 0.9.0 → 0.11.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 (45) hide show
  1. package/dist/common/use-child.svelte.d.ts +2 -2
  2. package/dist/common/use-child.svelte.js +3 -9
  3. package/dist/components/Alert/Alert.svelte +6 -6
  4. package/dist/components/AppShell/AppShell.svelte +2 -2
  5. package/dist/components/Avatar/Avatar.svelte +6 -6
  6. package/dist/components/Card/Card.svelte +84 -109
  7. package/dist/components/Card/Card.svelte.d.ts +4 -4
  8. package/dist/components/Card/CardBody.svelte +2 -6
  9. package/dist/components/Card/CardFooter.svelte +4 -7
  10. package/dist/components/Card/CardFooter.svelte.d.ts +1 -1
  11. package/dist/components/Card/CardHeader.svelte +3 -2
  12. package/dist/components/Card/CardHeader.svelte.d.ts +1 -0
  13. package/dist/components/CloseButton/CloseButton.svelte +16 -2
  14. package/dist/components/Code/Code.svelte +1 -1
  15. package/dist/components/Form/Checkbox.svelte +1 -1
  16. package/dist/components/Form/Field.svelte +3 -2
  17. package/dist/components/Form/Input.svelte +1 -1
  18. package/dist/components/Form/PasswordInput.svelte +3 -3
  19. package/dist/components/Heading/Heading.svelte +1 -1
  20. package/dist/components/Kbd/Kbd.svelte +33 -0
  21. package/dist/components/Kbd/Kbd.svelte.d.ts +10 -0
  22. package/dist/components/Modal/Modal.svelte +88 -0
  23. package/dist/components/Modal/Modal.svelte.d.ts +16 -0
  24. package/dist/components/Modal/ModalBody.svelte +15 -0
  25. package/dist/components/Modal/ModalBody.svelte.d.ts +5 -0
  26. package/dist/components/Modal/ModalFooter.svelte +15 -0
  27. package/dist/components/Modal/ModalFooter.svelte.d.ts +5 -0
  28. package/dist/components/Modal/ModalHeader.svelte +15 -0
  29. package/dist/components/Modal/ModalHeader.svelte.d.ts +5 -0
  30. package/dist/components/Navbar/NavbarItem.svelte +1 -1
  31. package/dist/components/SupporterBadge/SupporterBadge.svelte +3 -3
  32. package/dist/components/Switch/Switch.svelte +2 -2
  33. package/dist/components/ThemeSwitcher/ThemeSwitcher.svelte +33 -0
  34. package/dist/components/ThemeSwitcher/ThemeSwitcher.svelte.d.ts +8 -0
  35. package/dist/constants.d.ts +5 -1
  36. package/dist/constants.js +4 -0
  37. package/dist/index.d.ts +6 -0
  38. package/dist/index.js +6 -0
  39. package/dist/internal/Button.svelte +7 -7
  40. package/dist/internal/Child.svelte +10 -3
  41. package/dist/internal/Child.svelte.d.ts +1 -0
  42. package/dist/services/translation.svelte.d.ts +11 -0
  43. package/dist/services/translation.svelte.js +11 -0
  44. package/dist/types.d.ts +11 -2
  45. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
1
  import { ChildKey } from '../constants.js';
2
- import { type Snippet } from 'svelte';
2
+ import type { ChildData } from '../types.js';
3
3
  export declare const withChildrenSnippets: (key: ChildKey) => {
4
- getChildren: (key: ChildKey) => Snippet<[]> | undefined;
4
+ getChildren: (key: ChildKey) => ChildData | undefined;
5
5
  };
@@ -3,17 +3,11 @@ import { withPrefix } from '../utils.js';
3
3
  import { setContext } from 'svelte';
4
4
  import { SvelteMap } from 'svelte/reactivity';
5
5
  export const withChildrenSnippets = (key) => {
6
- const map = $state(new SvelteMap());
6
+ const map = new SvelteMap();
7
7
  setContext(withPrefix(key), {
8
- register: async (child, snippet) => {
9
- if (map.has(child)) {
10
- console.warn(`Snippet with key ${child} already exists in the context`);
11
- return;
12
- }
13
- map.set(child, snippet);
14
- },
8
+ register: (child, data) => map.set(child, data),
15
9
  });
16
10
  return {
17
- getChildren: (key) => map.get(key),
11
+ getChildren: (key) => map.get(key)?.(),
18
12
  };
19
13
  };
@@ -1,9 +1,9 @@
1
1
  <script lang="ts">
2
2
  import Card from '../Card/Card.svelte';
3
- import CardHeader from '../Card/CardHeader.svelte';
3
+ import CardBody from '../Card/CardBody.svelte';
4
+ import CloseButton from '../CloseButton/CloseButton.svelte';
4
5
  import Icon from '../Icon/Icon.svelte';
5
6
  import Text from '../Text/Text.svelte';
6
- import CloseButton from '../CloseButton/CloseButton.svelte';
7
7
  import type { Color, Size } from '../../types.js';
8
8
  import { cleanClass } from '../../utils.js';
9
9
  import {
@@ -78,9 +78,9 @@
78
78
  </script>
79
79
 
80
80
  {#if open}
81
- <Card {color} variant="subtle" class={cleanClass(className)}>
82
- <CardHeader>
83
- <div class="flex justify-between">
81
+ <Card {color} class={cleanClass(className)}>
82
+ <CardBody>
83
+ <div class="flex items-center justify-between">
84
84
  <div class={cleanClass('flex gap-2')}>
85
85
  {#if icon}
86
86
  <div>
@@ -103,6 +103,6 @@
103
103
  </div>
104
104
  {/if}
105
105
  </div>
106
- </CardHeader>
106
+ </CardBody>
107
107
  </Card>
108
108
  {/if}
@@ -20,12 +20,12 @@
20
20
  <div class={cleanClass('flex h-screen flex-col overflow-hidden', className)}>
21
21
  {#if header}
22
22
  <header class="border-b">
23
- {@render header?.()}
23
+ {@render header?.snippet()}
24
24
  </header>
25
25
  {/if}
26
26
  <div class="flex w-full grow overflow-y-auto">
27
27
  {#if sidebar}
28
- {@render sidebar()}
28
+ {@render sidebar?.snippet()}
29
29
  {/if}
30
30
  <Scrollable class="grow">
31
31
  {@render children?.()}
@@ -24,11 +24,11 @@
24
24
  base: 'flex h-full w-full select-none items-center justify-center font-medium',
25
25
  variants: {
26
26
  size: {
27
- tiny: 'w-5 h-5 text-xs',
28
- small: 'w-7 h-7 text-sm',
29
- medium: 'w-10 h-10 text-md',
30
- large: 'w-12 h-12 text-lg',
31
- giant: 'w-16 h-16 text-xl',
27
+ tiny: 'h-5 w-5 text-xs',
28
+ small: 'h-7 w-7 text-sm',
29
+ medium: 'text-md h-10 w-10',
30
+ large: 'h-12 w-12 text-lg',
31
+ giant: 'h-16 w-16 text-xl',
32
32
  },
33
33
  color: {
34
34
  primary: 'bg-primary text-light',
@@ -46,7 +46,7 @@
46
46
  });
47
47
 
48
48
  const wrapper = tv({
49
- base: 'overflow-hidden shadow-md rounded rounded-full',
49
+ base: 'overflow-hidden rounded-full shadow-md',
50
50
  });
51
51
 
52
52
  const getInitials = (name: string) => {
@@ -1,50 +1,54 @@
1
1
  <script lang="ts">
2
2
  import { withChildrenSnippets } from '../../common/use-child.svelte.js';
3
3
  import IconButton from '../IconButton/IconButton.svelte';
4
+ import Scrollable from '../Scrollable/Scrollable.svelte';
4
5
  import { ChildKey } from '../../constants.js';
5
- import type { Color, Shape } from '../../types.js';
6
+ import type { Color } from '../../types.js';
6
7
  import { cleanClass } from '../../utils.js';
7
8
  import { mdiChevronDown } from '@mdi/js';
8
9
  import { type Snippet } from 'svelte';
9
10
  import type { HTMLAttributes } from 'svelte/elements';
11
+ import { twMerge } from 'tailwind-merge';
10
12
  import { tv } from 'tailwind-variants';
11
13
 
12
14
  type Props = HTMLAttributes<HTMLDivElement> & {
13
15
  color?: Color;
14
- shape?: Shape;
15
- variant?: 'filled' | 'outline' | 'subtle';
16
+ shape?: 'round' | 'rectangle';
17
+ expanded?: boolean;
16
18
  expandable?: boolean;
17
19
  children: Snippet;
18
20
  };
19
21
 
20
22
  let {
21
- color = 'secondary',
23
+ color,
22
24
  class: className,
25
+ shape = 'round',
26
+ expanded = $bindable(true),
23
27
  expandable = false,
24
- variant,
25
28
  children,
26
29
  ...restProps
27
30
  }: Props = $props();
28
31
 
29
- const cardStyles = tv({
30
- base: 'flex flex-col rounded-2xl bg-light text-dark shadow-sm w-full overflow-hidden',
32
+ const containerStyles = tv({
33
+ base: 'w-full overflow-hidden bg-light text-dark shadow-sm',
31
34
  variants: {
32
- defaultStyle: {
35
+ shape: {
36
+ rectangle: '',
37
+ round: 'rounded-2xl',
38
+ },
39
+ border: {
33
40
  true: 'border',
34
41
  false: '',
35
- default: '',
36
42
  },
37
- outlineColor: {
38
- primary: 'border border-primary',
39
- secondary: 'border',
40
- success: 'border border-success',
41
- danger: 'border border-danger',
42
- warning: 'border border-warning',
43
- info: 'border border-info',
44
- },
45
- subtleColor: {
43
+ },
44
+ });
45
+
46
+ const cardStyles = tv({
47
+ base: 'flex h-full w-full flex-col',
48
+ variants: {
49
+ color: {
46
50
  primary: 'bg-primary/25 dark:bg-primary/25',
47
- secondary: 'bg-dark/5 dark:bg-dark/25 text-dark',
51
+ secondary: 'bg-dark/5 text-dark dark:bg-dark/25',
48
52
  success: 'bg-success/15 dark:bg-success/30',
49
53
  danger: 'bg-danger/15 dark:bg-danger/50',
50
54
  warning: 'bg-warning/25 dark:bg-warning/50',
@@ -54,132 +58,103 @@
54
58
  });
55
59
 
56
60
  const headerContainerStyles = tv({
61
+ base: 'p-4',
57
62
  variants: {
58
- bottomPadding: {
63
+ padding: {
59
64
  true: '',
60
65
  false: 'pb-0',
61
66
  },
62
- filledColor: {
63
- primary: 'bg-primary text-light rounded-t-xl',
64
- secondary: 'bg-dark text-light rounded-t-xl',
65
- success: 'bg-success text-light rounded-t-xl',
66
- danger: 'bg-danger text-light rounded-t-xl',
67
- warning: 'bg-warning text-black rounded-t-xl',
68
- info: 'bg-info text-light rounded-t-xl',
69
- },
70
- outlineColor: {
71
- primary: 'text-primary',
72
- secondary: 'text-dark',
73
- success: 'text-success',
74
- danger: 'text-danger',
75
- warning: 'text-warning',
76
- info: 'text-info',
77
- },
78
- },
79
- });
80
-
81
- const iconStyles = tv({
82
- variants: {
83
- filledColor: {
84
- primary: 'text-light',
85
- secondary: 'text-light',
86
- success: 'text-light',
87
- danger: 'text-light',
88
- warning: 'text-dark',
89
- info: 'text-light',
90
- },
91
- outlineColor: {
92
- primary: 'text-primary',
93
- secondary: 'text-dark',
94
- success: 'text-success',
95
- danger: 'text-danger',
96
- warning: 'text-warning',
97
- info: 'text-info',
67
+ border: {
68
+ true: 'border-b',
69
+ false: '',
98
70
  },
99
71
  },
100
72
  });
101
73
 
102
- let expanded = $state(!expandable);
103
74
  const onToggle = () => {
104
75
  expanded = !expanded;
105
76
  };
106
77
 
107
78
  const { getChildren: getChildSnippet } = withChildrenSnippets(ChildKey.Card);
108
- const headerChildren = $derived(getChildSnippet(ChildKey.CardHeader));
109
- const bodyChildren = $derived(getChildSnippet(ChildKey.CardBody));
110
- const footerChildren = $derived(getChildSnippet(ChildKey.CardFooter));
79
+ const headerChild = $derived(getChildSnippet(ChildKey.CardHeader));
80
+ const bodyChild = $derived(getChildSnippet(ChildKey.CardBody));
81
+ const footerChild = $derived(getChildSnippet(ChildKey.CardFooter));
82
+
83
+ const headerBorder = $derived(!color);
84
+ const headerPadding = $derived(headerBorder || !expanded);
111
85
 
112
- const headerClasses = 'flex flex-col space-y-1.5';
113
86
  const headerContainerClasses = $derived(
114
- cleanClass(
115
- headerContainerStyles({
116
- bottomPadding: variant === 'filled' || !bodyChildren,
117
- outlineColor: variant === 'outline' ? color : undefined,
118
- filledColor: variant === 'filled' ? color : undefined,
119
- }),
87
+ twMerge(
88
+ cleanClass(
89
+ headerContainerStyles({
90
+ padding: headerPadding,
91
+ border: headerBorder,
92
+ }),
93
+ headerChild?.class,
94
+ ),
120
95
  ),
121
96
  );
122
97
  </script>
123
98
 
124
99
  {#snippet header()}
125
100
  {#if expandable}
126
- <button type="button" onclick={onToggle} class="w-full">
127
- <div class={cleanClass(headerContainerClasses, 'flex items-center justify-between px-4')}>
128
- <div class={cleanClass(headerClasses, 'py-4')}>
129
- {@render headerChildren?.()}
130
- </div>
131
- <div>
132
- <IconButton
133
- class={iconStyles({
134
- filledColor: variant === 'filled' ? color : undefined,
135
- outlineColor: variant === 'outline' ? color : undefined,
136
- }) as Color}
137
- icon={mdiChevronDown}
138
- flopped={expanded}
139
- variant="ghost"
140
- shape="round"
141
- size="large"
142
- />
143
- </div>
101
+ <button
102
+ type="button"
103
+ onclick={onToggle}
104
+ class={cleanClass('flex w-full items-center justify-between px-4', headerContainerClasses)}
105
+ >
106
+ <div class="flex flex-col">
107
+ {@render headerChild?.snippet()}
108
+ </div>
109
+ <div>
110
+ <IconButton
111
+ color="secondary"
112
+ icon={mdiChevronDown}
113
+ flopped={expanded}
114
+ variant="ghost"
115
+ shape="round"
116
+ size="large"
117
+ />
144
118
  </div>
145
119
  </button>
146
120
  {:else}
147
- <div class={cleanClass(headerClasses, headerContainerClasses, 'p-4')}>
148
- {@render headerChildren?.()}
121
+ <div class={cleanClass('flex flex-col', headerContainerClasses)}>
122
+ {@render headerChild?.snippet()}
149
123
  </div>
150
124
  {/if}
151
125
  {/snippet}
152
126
 
153
- {#snippet body()}
154
- {@render bodyChildren?.()}
155
- {/snippet}
156
-
157
- {#snippet footer()}
158
- {@render footerChildren?.()}
159
- {/snippet}
160
-
161
127
  <div
162
128
  class={cleanClass(
163
- cardStyles({
164
- defaultStyle: variant === undefined,
165
- outlineColor: variant === 'outline' || variant === 'filled' ? color : undefined,
166
- subtleColor: variant === 'subtle' ? color : undefined,
129
+ containerStyles({
130
+ shape,
131
+ border: !color,
167
132
  }),
168
133
  className,
169
134
  )}
170
135
  {...restProps}
171
136
  >
172
- {#if headerChildren}
173
- {@render header()}
174
- {/if}
137
+ <div class={cleanClass(cardStyles({ color }))}>
138
+ {#if headerChild}
139
+ {@render header()}
140
+ {/if}
175
141
 
176
- {#if bodyChildren && expanded}
177
- {@render body()}
178
- {/if}
142
+ {#if bodyChild && expanded}
143
+ <Scrollable class={twMerge(cleanClass('p-4', bodyChild?.class))}>
144
+ {@render bodyChild?.snippet()}
145
+ </Scrollable>
146
+ {/if}
179
147
 
180
- {#if footerChildren}
181
- {@render footer()}
182
- {/if}
148
+ {#if footerChild}
149
+ <div
150
+ class={twMerge(
151
+ cleanClass('flex items-center border-t border-t-subtle p-4', footerChild.class),
152
+ )}
153
+ >
154
+ {@render footerChild.snippet()}
155
+ </div>
156
+ {/if}
183
157
 
184
- {@render children()}
158
+ {@render children()}
159
+ </div>
185
160
  </div>
@@ -1,11 +1,11 @@
1
- import type { Color, Shape } from '../../types.js';
1
+ import type { Color } from '../../types.js';
2
2
  import { type Snippet } from 'svelte';
3
3
  import type { HTMLAttributes } from 'svelte/elements';
4
4
  declare const Card: import("svelte").Component<HTMLAttributes<HTMLDivElement> & {
5
5
  color?: Color;
6
- shape?: Shape;
7
- variant?: "filled" | "outline" | "subtle";
6
+ shape?: "round" | "rectangle";
7
+ expanded?: boolean;
8
8
  expandable?: boolean;
9
9
  children: Snippet;
10
- }, {}, "">;
10
+ }, {}, "expanded">;
11
11
  export default Card;
@@ -1,9 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { ChildKey } from '../../constants.js';
3
3
  import Child from '../../internal/Child.svelte';
4
- import { cleanClass } from '../../utils.js';
5
4
  import type { Snippet } from 'svelte';
6
- import { twMerge } from 'tailwind-merge';
7
5
 
8
6
  type Props = {
9
7
  class?: string;
@@ -13,8 +11,6 @@
13
11
  let { class: className, children }: Props = $props();
14
12
  </script>
15
13
 
16
- <Child for={ChildKey.Card} as={ChildKey.CardBody}>
17
- <div class={twMerge(cleanClass('w-full grow p-4', className))}>
18
- {@render children?.()}
19
- </div>
14
+ <Child for={ChildKey.Card} as={ChildKey.CardBody} class={className}>
15
+ {@render children?.()}
20
16
  </Child>
@@ -1,19 +1,16 @@
1
1
  <script lang="ts">
2
2
  import { ChildKey } from '../../constants.js';
3
3
  import Child from '../../internal/Child.svelte';
4
- import { cleanClass } from '../../utils.js';
5
4
  import type { Snippet } from 'svelte';
6
5
 
7
6
  type Props = {
8
- children: Snippet;
9
7
  class?: string;
8
+ children: Snippet;
10
9
  };
11
10
 
12
- let { children, class: className }: Props = $props();
11
+ let { class: className, children }: Props = $props();
13
12
  </script>
14
13
 
15
- <Child for={ChildKey.Card} as={ChildKey.CardFooter}>
16
- <div class={cleanClass('flex items-center p-4 pt-0', className)}>
17
- {@render children?.()}
18
- </div>
14
+ <Child for={ChildKey.Card} as={ChildKey.CardFooter} class={className}>
15
+ {@render children?.()}
19
16
  </Child>
@@ -1,6 +1,6 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  declare const CardFooter: import("svelte").Component<{
3
- children: Snippet;
4
3
  class?: string;
4
+ children: Snippet;
5
5
  }, {}, "">;
6
6
  export default CardFooter;
@@ -4,12 +4,13 @@
4
4
  import type { Snippet } from 'svelte';
5
5
 
6
6
  type Props = {
7
+ class?: string;
7
8
  children: Snippet;
8
9
  };
9
10
 
10
- let { children }: Props = $props();
11
+ let { class: className, children }: Props = $props();
11
12
  </script>
12
13
 
13
- <Child for={ChildKey.Card} as={ChildKey.CardHeader}>
14
+ <Child for={ChildKey.Card} as={ChildKey.CardHeader} class={className}>
14
15
  {@render children?.()}
15
16
  </Child>
@@ -1,5 +1,6 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  declare const CardHeader: import("svelte").Component<{
3
+ class?: string;
3
4
  children: Snippet;
4
5
  }, {}, "">;
5
6
  export default CardHeader;
@@ -1,9 +1,23 @@
1
1
  <script lang="ts">
2
2
  import IconButton from '../IconButton/IconButton.svelte';
3
+ import { t } from '../../services/translation.svelte.js';
3
4
  import type { CloseButtonProps } from '../../types.js';
4
5
  import { mdiClose } from '@mdi/js';
5
6
 
6
- const { size = 'medium', variant = 'ghost', ...restProps }: CloseButtonProps = $props();
7
+ const {
8
+ size = 'medium',
9
+ variant = 'ghost',
10
+ translations,
11
+ ...restProps
12
+ }: CloseButtonProps = $props();
7
13
  </script>
8
14
 
9
- <IconButton {...restProps} icon={mdiClose} shape="round" {variant} {size} color="secondary" />
15
+ <IconButton
16
+ {...restProps}
17
+ icon={mdiClose}
18
+ shape="round"
19
+ {variant}
20
+ {size}
21
+ color="secondary"
22
+ title={t('close', translations)}
23
+ />
@@ -32,7 +32,7 @@
32
32
 
33
33
  filledColor: {
34
34
  false: '',
35
- muted: 'bg-gray-600 dark:bg-gray-800 text-light',
35
+ muted: 'bg-gray-600 text-light dark:bg-gray-800',
36
36
  primary: 'bg-primary text-light',
37
37
  secondary: 'bg-dark text-light',
38
38
  success: 'bg-success text-light',
@@ -32,7 +32,7 @@
32
32
  } = $derived(getFieldContext());
33
33
 
34
34
  const containerStyles = tv({
35
- base: 'border-2 ring-offset-background focus-visible:ring-ring peer box-content focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[disabled=true]:cursor-not-allowed data-[state=checked]:bg-primary data-[disabled=true]:opacity-50 overflow-hidden',
35
+ base: 'ring-offset-background focus-visible:ring-ring peer box-content overflow-hidden border-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[disabled=true]:cursor-not-allowed data-[state=checked]:bg-primary data-[disabled=true]:opacity-50',
36
36
  variants: {
37
37
  shape: {
38
38
  rectangle: 'rounded-none',
@@ -3,6 +3,7 @@
3
3
  import { withChildrenSnippets } from '../../common/use-child.svelte.js';
4
4
  import { ChildKey } from '../../constants.js';
5
5
  import type { FieldContext } from '../../types.js';
6
+ import { cleanClass } from '../../utils.js';
6
7
  import { type Snippet } from 'svelte';
7
8
 
8
9
  type Props = FieldContext & {
@@ -22,8 +23,8 @@
22
23
  <div>
23
24
  {@render children()}
24
25
  {#if helperTextChildren}
25
- <div class="pt-1">
26
- {@render helperTextChildren?.()}
26
+ <div class={cleanClass('pt-1', helperTextChildren.class)}>
27
+ {@render helperTextChildren.snippet()}
27
28
  </div>
28
29
  {/if}
29
30
  </div>
@@ -36,7 +36,7 @@
36
36
  });
37
37
 
38
38
  const inputStyles = tv({
39
- base: 'w-full outline-none disabled:cursor-not-allowed bg-gray-200 dark:bg-gray-600 disabled:bg-gray-300 disabled:text-gray-200 dark:disabled:bg-gray-800 aria-readonly:text-dark/50 dark:aria-readonly:text-dark/75',
39
+ base: 'w-full bg-gray-200 outline-none disabled:cursor-not-allowed disabled:bg-gray-300 disabled:text-gray-200 aria-readonly:text-dark/50 dark:bg-gray-600 dark:disabled:bg-gray-800 dark:aria-readonly:text-dark/75',
40
40
  variants: {
41
41
  shape: {
42
42
  rectangle: 'rounded-none',
@@ -1,13 +1,13 @@
1
1
  <script lang="ts">
2
2
  import Input from './Input.svelte';
3
3
  import IconButton from '../IconButton/IconButton.svelte';
4
+ import { t } from '../../services/translation.svelte.js';
4
5
  import type { PasswordInputProps } from '../../types.js';
5
6
  import { mdiEyeOffOutline, mdiEyeOutline } from '@mdi/js';
6
7
 
7
8
  let {
8
9
  value = $bindable<string>(),
9
- showLabel = 'Show password',
10
- hideLabel = 'Hide password',
10
+ translations,
11
11
  isVisible = $bindable<boolean>(false),
12
12
  color = 'secondary',
13
13
  ...props
@@ -24,7 +24,7 @@
24
24
  class="m-1"
25
25
  icon={isVisible ? mdiEyeOffOutline : mdiEyeOutline}
26
26
  onclick={() => (isVisible = !isVisible)}
27
- title={isVisible ? hideLabel : showLabel}
27
+ title={isVisible ? t('hidePassword', translations) : t('showPassword', translations)}
28
28
  ></IconButton>
29
29
  {/if}
30
30
  {/snippet}
@@ -12,7 +12,7 @@
12
12
  children: Snippet;
13
13
  };
14
14
 
15
- const { color, size, class: className, children }: Props = $props();
15
+ const { color, size = 'medium', class: className, children }: Props = $props();
16
16
 
17
17
  const sizes = {
18
18
  title: 'h1',
@@ -0,0 +1,33 @@
1
+ <script lang="ts">
2
+ import type { Color, Size } from '../../types.js';
3
+ import { cleanClass } from '../../utils.js';
4
+ import type { Snippet } from 'svelte';
5
+ import type { HTMLAttributes } from 'svelte/elements';
6
+ import { tv } from 'tailwind-variants';
7
+
8
+ type Props = {
9
+ size?: Size;
10
+ color?: Color;
11
+ class?: string;
12
+ children?: Snippet;
13
+ } & HTMLAttributes<HTMLElement>;
14
+
15
+ const { class: className, size = 'small', children, ...restProps }: Props = $props();
16
+
17
+ const styles = tv({
18
+ base: 'flex flex-col rounded-md border border-b-2 bg-subtle px-1 font-mono text-dark shadow',
19
+ variants: {
20
+ size: {
21
+ tiny: 'text-xs',
22
+ small: 'text-sm',
23
+ medium: 'text-md',
24
+ large: 'text-lg',
25
+ giant: 'text-xl',
26
+ },
27
+ },
28
+ });
29
+ </script>
30
+
31
+ <kbd class={cleanClass(styles({ size }), className)} {...restProps}>
32
+ {@render children?.()}
33
+ </kbd>
@@ -0,0 +1,10 @@
1
+ import type { Color, Size } from '../../types.js';
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ declare const Kbd: import("svelte").Component<{
5
+ size?: Size;
6
+ color?: Color;
7
+ class?: string;
8
+ children?: Snippet;
9
+ } & HTMLAttributes<HTMLElement>, {}, "">;
10
+ export default Kbd;
@@ -0,0 +1,88 @@
1
+ <script lang="ts">
2
+ import { withChildrenSnippets } from '../../common/use-child.svelte.js';
3
+ import Card from '../Card/Card.svelte';
4
+ import CardBody from '../Card/CardBody.svelte';
5
+ import CardFooter from '../Card/CardFooter.svelte';
6
+ import CardHeader from '../Card/CardHeader.svelte';
7
+ import CardTitle from '../Card/CardTitle.svelte';
8
+ import CloseButton from '../CloseButton/CloseButton.svelte';
9
+ import { ChildKey } from '../../constants.js';
10
+ import type { ModalSize } from '../../types.js';
11
+ import { cleanClass } from '../../utils.js';
12
+ import { Dialog } from 'bits-ui';
13
+ import { type Snippet } from 'svelte';
14
+ import { tv } from 'tailwind-variants';
15
+
16
+ type Props = Dialog.RootProps & {
17
+ title: string;
18
+ size?: ModalSize;
19
+ class?: string;
20
+ open?: boolean;
21
+ expandable?: boolean;
22
+ children: Snippet;
23
+ };
24
+
25
+ let {
26
+ title,
27
+ size = 'medium',
28
+ open = $bindable(true),
29
+ class: className,
30
+ children,
31
+ ...restProps
32
+ }: Props = $props();
33
+
34
+ const modalStyles = tv({
35
+ base: 'flex rounded-none border border-subtle bg-subtle sm:rounded-2xl',
36
+ variants: {
37
+ size: {
38
+ tiny: 'h-full sm:h-min md:max-w-64',
39
+ small: 'h-full sm:h-min md:max-w-96',
40
+ medium: 'h-full sm:h-min md:max-w-screen-sm',
41
+ large: 'h-full sm:h-min md:max-w-screen-md',
42
+ giant: 'h-full sm:h-min md:max-w-screen-lg',
43
+ full: 'h-full w-full',
44
+ },
45
+ },
46
+ });
47
+
48
+ const { getChildren: getChildSnippet } = withChildrenSnippets(ChildKey.Modal);
49
+ const bodyChildren = $derived(getChildSnippet(ChildKey.ModalBody));
50
+ const footerChildren = $derived(getChildSnippet(ChildKey.ModalFooter));
51
+
52
+ const handleClose = () => {
53
+ open = false;
54
+ };
55
+ </script>
56
+
57
+ <Dialog.Root bind:open {...restProps}>
58
+ <Dialog.Portal>
59
+ <Dialog.Overlay class="absolute left-0 top-0 flex h-screen w-screen backdrop-blur" />
60
+ <Dialog.Content
61
+ class={cleanClass(
62
+ 'absolute left-0 top-0 flex h-dvh w-screen items-center justify-center overflow-hidden sm:p-4',
63
+ )}
64
+ >
65
+ <div class={cleanClass('flex h-full w-full flex-col items-center justify-center ')}>
66
+ <Card class={cleanClass(modalStyles({ size }), className)}>
67
+ <CardHeader class="border-0 py-2">
68
+ <div class="flex items-center justify-between">
69
+ <CardTitle>{title}</CardTitle>
70
+ <CloseButton size="large" onclick={handleClose} />
71
+ </div>
72
+ </CardHeader>
73
+
74
+ <CardBody class="grow py-2">
75
+ {@render bodyChildren?.snippet()}
76
+ </CardBody>
77
+
78
+ {#if footerChildren}
79
+ <CardFooter class="py-2">
80
+ {@render footerChildren.snippet()}
81
+ </CardFooter>
82
+ {/if}
83
+ </Card>
84
+ </div>
85
+ </Dialog.Content>
86
+ </Dialog.Portal>
87
+ </Dialog.Root>
88
+ {@render children?.()}
@@ -0,0 +1,16 @@
1
+ import type { ModalSize } from '../../types.js';
2
+ import { type Snippet } from 'svelte';
3
+ declare const Modal: import("svelte").Component<{
4
+ open?: boolean;
5
+ onOpenChange?: import("bits-ui/dist/internal/types").OnChangeFn<boolean>;
6
+ } & {
7
+ children?: Snippet | undefined;
8
+ } & {
9
+ title: string;
10
+ size?: ModalSize;
11
+ class?: string;
12
+ open?: boolean;
13
+ expandable?: boolean;
14
+ children: Snippet;
15
+ }, {}, "open">;
16
+ export default Modal;
@@ -0,0 +1,15 @@
1
+ <script lang="ts">
2
+ import { ChildKey } from '../../constants.js';
3
+ import Child from '../../internal/Child.svelte';
4
+ import type { Snippet } from 'svelte';
5
+
6
+ type Props = {
7
+ children: Snippet;
8
+ };
9
+
10
+ let { children }: Props = $props();
11
+ </script>
12
+
13
+ <Child for={ChildKey.Modal} as={ChildKey.ModalBody}>
14
+ {@render children?.()}
15
+ </Child>
@@ -0,0 +1,5 @@
1
+ import type { Snippet } from 'svelte';
2
+ declare const ModalBody: import("svelte").Component<{
3
+ children: Snippet;
4
+ }, {}, "">;
5
+ export default ModalBody;
@@ -0,0 +1,15 @@
1
+ <script lang="ts">
2
+ import { ChildKey } from '../../constants.js';
3
+ import Child from '../../internal/Child.svelte';
4
+ import type { Snippet } from 'svelte';
5
+
6
+ type Props = {
7
+ children: Snippet;
8
+ };
9
+
10
+ let { children }: Props = $props();
11
+ </script>
12
+
13
+ <Child for={ChildKey.Modal} as={ChildKey.ModalFooter}>
14
+ {@render children?.()}
15
+ </Child>
@@ -0,0 +1,5 @@
1
+ import type { Snippet } from 'svelte';
2
+ declare const ModalFooter: import("svelte").Component<{
3
+ children: Snippet;
4
+ }, {}, "">;
5
+ export default ModalFooter;
@@ -0,0 +1,15 @@
1
+ <script lang="ts">
2
+ import { ChildKey } from '../../constants.js';
3
+ import Child from '../../internal/Child.svelte';
4
+ import type { Snippet } from 'svelte';
5
+
6
+ type Props = {
7
+ children: Snippet;
8
+ };
9
+
10
+ let { children }: Props = $props();
11
+ </script>
12
+
13
+ <Child for={ChildKey.Modal} as={ChildKey.ModalHeader}>
14
+ {@render children?.()}
15
+ </Child>
@@ -0,0 +1,5 @@
1
+ import type { Snippet } from 'svelte';
2
+ declare const ModalHeader: import("svelte").Component<{
3
+ children: Snippet;
4
+ }, {}, "">;
5
+ export default ModalHeader;
@@ -12,7 +12,7 @@
12
12
  let { href, title, active = false, ...iconProps }: Props = $props();
13
13
 
14
14
  const styles = tv({
15
- base: 'hover:bg-subtle hover:text-primary flex w-full place-items-center gap-4 rounded-r-full py-3 transition-[padding] delay-100 duration-100 pl-5 group-hover:sm:px-5 md:px-5',
15
+ base: 'flex w-full place-items-center gap-4 rounded-r-full py-3 pl-5 transition-[padding] delay-100 duration-100 hover:bg-subtle hover:text-primary group-hover:sm:px-5 md:px-5',
16
16
  variants: {
17
17
  active: {
18
18
  true: 'bg-primary/10 text-primary',
@@ -24,7 +24,7 @@
24
24
  };
25
25
 
26
26
  const containerStyles = tv({
27
- base: 'bg-secondary flex place-items-center gap-2 overflow-hidden rounded-lg transition-all',
27
+ base: 'bg-secondary flex place-items-center gap-2 overflow-hidden rounded-lg transition-all',
28
28
  variants: {
29
29
  size: {
30
30
  tiny: 'px-2 py-1',
@@ -34,8 +34,8 @@
34
34
  giant: 'px-3 py-2',
35
35
  },
36
36
  effect: {
37
- hover: 'border border-dark/25 supporter-effect-hover',
38
- always: 'shadow supporter-effect',
37
+ hover: 'supporter-effect-hover border border-dark/25',
38
+ always: 'supporter-effect shadow',
39
39
  },
40
40
  },
41
41
  });
@@ -43,7 +43,7 @@
43
43
  });
44
44
 
45
45
  const bar = tv({
46
- base: 'w-12 h-3 my-2 rounded-full border border-transparent',
46
+ base: 'my-2 h-3 w-12 rounded-full border border-transparent',
47
47
  variants: {
48
48
  fillColor: {
49
49
  default: 'bg-gray-400',
@@ -58,7 +58,7 @@
58
58
  });
59
59
 
60
60
  const dot = tv({
61
- base: 'absolute transition-colors h-6 w-6 rounded-full transition-transform duration-[400ms]',
61
+ base: 'absolute h-6 w-6 rounded-full transition-transform duration-[400ms]',
62
62
  variants: {
63
63
  checked: {
64
64
  true: 'translate-x-6',
@@ -0,0 +1,33 @@
1
+ <script lang="ts">
2
+ import IconButton from '../IconButton/IconButton.svelte';
3
+ import { theme } from '../../services/theme.svelte.js';
4
+ import { Theme, type Size, type Variants } from '../../types.js';
5
+ import { cleanClass } from '../../utils.js';
6
+ import { mdiWeatherNight, mdiWeatherSunny } from '@mdi/js';
7
+
8
+ type Props = {
9
+ size?: Size;
10
+ class?: string;
11
+ variant?: Variants;
12
+ onChange?: (theme: Theme) => void;
13
+ };
14
+
15
+ const { variant = 'ghost', size, class: className, onChange }: Props = $props();
16
+
17
+ const handleToggleTheme = () => {
18
+ theme.value = theme.value === Theme.Dark ? Theme.Light : Theme.Dark;
19
+ onChange?.(theme.value);
20
+ };
21
+
22
+ const themeIcon = $derived(theme.value === Theme.Light ? mdiWeatherSunny : mdiWeatherNight);
23
+ </script>
24
+
25
+ <IconButton
26
+ shape="round"
27
+ color="primary"
28
+ {size}
29
+ {variant}
30
+ icon={themeIcon}
31
+ onclick={handleToggleTheme}
32
+ class={cleanClass(className)}
33
+ />
@@ -0,0 +1,8 @@
1
+ import { Theme, type Size, type Variants } from '../../types.js';
2
+ declare const ThemeSwitcher: import("svelte").Component<{
3
+ size?: Size;
4
+ class?: string;
5
+ variant?: Variants;
6
+ onChange?: (theme: Theme) => void;
7
+ }, {}, "">;
8
+ export default ThemeSwitcher;
@@ -7,5 +7,9 @@ export declare enum ChildKey {
7
7
  Card = "card",
8
8
  CardHeader = "card-header",
9
9
  CardBody = "card-body",
10
- CardFooter = "card-footer"
10
+ CardFooter = "card-footer",
11
+ Modal = "modal",
12
+ ModalHeader = "modal-header",
13
+ ModalBody = "modal-body",
14
+ ModalFooter = "modal-footer"
11
15
  }
package/dist/constants.js CHANGED
@@ -9,4 +9,8 @@ export var ChildKey;
9
9
  ChildKey["CardHeader"] = "card-header";
10
10
  ChildKey["CardBody"] = "card-body";
11
11
  ChildKey["CardFooter"] = "card-footer";
12
+ ChildKey["Modal"] = "modal";
13
+ ChildKey["ModalHeader"] = "modal-header";
14
+ ChildKey["ModalBody"] = "modal-body";
15
+ ChildKey["ModalFooter"] = "modal-footer";
12
16
  })(ChildKey || (ChildKey = {}));
package/dist/index.d.ts CHANGED
@@ -31,9 +31,13 @@ export { default as FormatBytes } from './components/FormatBytes/FormatBytes.sve
31
31
  export { default as Heading } from './components/Heading/Heading.svelte';
32
32
  export { default as Icon } from './components/Icon/Icon.svelte';
33
33
  export { default as IconButton } from './components/IconButton/IconButton.svelte';
34
+ export { default as Kbd } from './components/Kbd/Kbd.svelte';
34
35
  export { default as Link } from './components/Link/Link.svelte';
35
36
  export { default as LoadingSpinner } from './components/LoadingSpinner/LoadingSpinner.svelte';
36
37
  export { default as Logo } from './components/Logo/Logo.svelte';
38
+ export { default as Modal } from './components/Modal/Modal.svelte';
39
+ export { default as ModalBody } from './components/Modal/ModalBody.svelte';
40
+ export { default as ModalFooter } from './components/Modal/ModalFooter.svelte';
37
41
  export { default as MultiSelect } from './components/MultiSelect/MultiSelect.svelte';
38
42
  export { default as NavbarGroup } from './components/Navbar/NavbarGroup.svelte';
39
43
  export { default as NavbarItem } from './components/Navbar/NavbarItem.svelte';
@@ -45,6 +49,8 @@ export { default as VStack } from './components/Stack/VStack.svelte';
45
49
  export { default as SupporterBadge } from './components/SupporterBadge/SupporterBadge.svelte';
46
50
  export { default as Switch } from './components/Switch/Switch.svelte';
47
51
  export { default as Text } from './components/Text/Text.svelte';
52
+ export { default as ThemeSwitcher } from './components/ThemeSwitcher/ThemeSwitcher.svelte';
48
53
  export * from './services/theme.svelte.js';
49
54
  export * from './types.js';
50
55
  export * from './utilities/byte-units.js';
56
+ export * from './services/translation.svelte.js';
package/dist/index.js CHANGED
@@ -33,9 +33,13 @@ export { default as FormatBytes } from './components/FormatBytes/FormatBytes.sve
33
33
  export { default as Heading } from './components/Heading/Heading.svelte';
34
34
  export { default as Icon } from './components/Icon/Icon.svelte';
35
35
  export { default as IconButton } from './components/IconButton/IconButton.svelte';
36
+ export { default as Kbd } from './components/Kbd/Kbd.svelte';
36
37
  export { default as Link } from './components/Link/Link.svelte';
37
38
  export { default as LoadingSpinner } from './components/LoadingSpinner/LoadingSpinner.svelte';
38
39
  export { default as Logo } from './components/Logo/Logo.svelte';
40
+ export { default as Modal } from './components/Modal/Modal.svelte';
41
+ export { default as ModalBody } from './components/Modal/ModalBody.svelte';
42
+ export { default as ModalFooter } from './components/Modal/ModalFooter.svelte';
39
43
  export { default as MultiSelect } from './components/MultiSelect/MultiSelect.svelte';
40
44
  export { default as NavbarGroup } from './components/Navbar/NavbarGroup.svelte';
41
45
  export { default as NavbarItem } from './components/Navbar/NavbarItem.svelte';
@@ -47,7 +51,9 @@ export { default as VStack } from './components/Stack/VStack.svelte';
47
51
  export { default as SupporterBadge } from './components/SupporterBadge/SupporterBadge.svelte';
48
52
  export { default as Switch } from './components/Switch/Switch.svelte';
49
53
  export { default as Text } from './components/Text/Text.svelte';
54
+ export { default as ThemeSwitcher } from './components/ThemeSwitcher/ThemeSwitcher.svelte';
50
55
  // helpers
51
56
  export * from './services/theme.svelte.js';
52
57
  export * from './types.js';
53
58
  export * from './utilities/byte-units.js';
59
+ export * from './services/translation.svelte.js';
@@ -57,7 +57,7 @@
57
57
  iconSize: {
58
58
  tiny: 'h-4 w-4 text-xs',
59
59
  small: 'h-6 w-6 text-sm',
60
- medium: 'h-8 w-8 text-md',
60
+ medium: 'text-md h-8 w-8',
61
61
  large: 'h-10 w-10 text-lg',
62
62
  giant: 'h-12 w-12 text-lg',
63
63
  },
@@ -77,12 +77,12 @@
77
77
  info: 'bg-info text-light hover:bg-info/80',
78
78
  },
79
79
  outlineColor: {
80
- primary: 'bg-primary/10 text-primary border border-primary hover:bg-primary/20',
81
- secondary: 'bg-dark/10 text-dark border border-dark hover:bg-dark/20',
82
- success: 'bg-success/10 text-success border border-success hover:bg-success/20',
83
- danger: 'bg-danger/10 text-danger border border-danger hover:bg-danger/20',
84
- warning: 'bg-warning/10 text-warning border border-warning hover:bg-warning/20',
85
- info: 'bg-info/10 text-info border border-info hover:bg-info/20',
80
+ primary: 'border border-primary bg-primary/10 text-primary hover:bg-primary/20',
81
+ secondary: 'border border-dark bg-dark/10 text-dark hover:bg-dark/20',
82
+ success: 'border border-success bg-success/10 text-success hover:bg-success/20',
83
+ danger: 'border border-danger bg-danger/10 text-danger hover:bg-danger/20',
84
+ warning: 'border border-warning bg-warning/10 text-warning hover:bg-warning/20',
85
+ info: 'border border-info bg-info/10 text-info hover:bg-info/20',
86
86
  },
87
87
  ghostColor: {
88
88
  primary: 'text-primary hover:bg-primary/10',
@@ -1,20 +1,27 @@
1
1
  <script lang="ts">
2
2
  import { ChildKey } from '../constants.js';
3
+ import type { ChildData } from '../types.js';
3
4
  import { withPrefix } from '../utils.js';
4
5
  import { getContext, type Snippet } from 'svelte';
5
6
 
6
- type ContextType = { register: (key: ChildKey, snippet: Snippet) => void };
7
+ type ContextType = {
8
+ register: (key: ChildKey, data: () => ChildData) => void;
9
+ };
7
10
  type Props = {
8
11
  for: ChildKey;
9
12
  as: ChildKey;
13
+ class?: string;
10
14
  children: Snippet;
11
15
  };
12
16
 
13
- const { for: key, as, children }: Props = $props();
17
+ const { for: key, as, children, class: className }: Props = $props();
14
18
 
15
19
  const context = getContext<ContextType>(withPrefix(key));
20
+
21
+ const data = $derived({ snippet: children, class: className });
22
+
16
23
  if (context) {
17
- context.register(as, children);
24
+ context.register(as, () => data);
18
25
  } else {
19
26
  console.log('Unable to find context for key:', key);
20
27
  }
@@ -3,6 +3,7 @@ import { type Snippet } from 'svelte';
3
3
  declare const Child: import("svelte").Component<{
4
4
  for: ChildKey;
5
5
  as: ChildKey;
6
+ class?: string;
6
7
  children: Snippet;
7
8
  }, {}, "">;
8
9
  export default Child;
@@ -0,0 +1,11 @@
1
+ import type { TranslationProps } from '../types.js';
2
+ declare const defaultTranslations: {
3
+ close: string;
4
+ showPassword: string;
5
+ hidePassword: string;
6
+ };
7
+ export type Translations = typeof defaultTranslations;
8
+ export declare const translate: <T extends keyof Translations>(key: T, overrides?: TranslationProps<T>) => string;
9
+ export declare const t: <T extends keyof Translations>(key: T, overrides?: TranslationProps<T>) => string;
10
+ export declare const setTranslations: (newTranslations: Partial<Translations>) => void;
11
+ export {};
@@ -0,0 +1,11 @@
1
+ const defaultTranslations = {
2
+ close: 'Close',
3
+ showPassword: 'Show password',
4
+ hidePassword: 'Hide password',
5
+ };
6
+ let translations = $state(defaultTranslations);
7
+ export const translate = (key, overrides) => overrides?.[key] ?? translations[key];
8
+ export const t = translate;
9
+ export const setTranslations = (newTranslations) => {
10
+ translations = { ...defaultTranslations, ...newTranslations };
11
+ };
package/dist/types.d.ts CHANGED
@@ -1,9 +1,11 @@
1
+ import type { Translations } from './services/translation.svelte.js';
1
2
  import type { Snippet } from 'svelte';
2
3
  import type { HTMLAnchorAttributes, HTMLButtonAttributes, HTMLInputAttributes } from 'svelte/elements';
3
4
  export type Color = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info';
4
5
  export type TextColor = Color | 'muted';
5
6
  export type HeadingColor = TextColor;
6
7
  export type Size = 'tiny' | 'small' | 'medium' | 'large' | 'giant';
8
+ export type ModalSize = Size | 'full';
7
9
  export type HeadingSize = Size | 'title';
8
10
  export type Shape = 'rectangle' | 'semi-round' | 'round';
9
11
  export type Variants = 'filled' | 'outline' | 'ghost';
@@ -12,6 +14,9 @@ export declare enum Theme {
12
14
  Light = "light",
13
15
  Dark = "dark"
14
16
  }
17
+ export type TranslationProps<T extends keyof Translations> = {
18
+ [K in T]?: string;
19
+ };
15
20
  export type IconProps = {
16
21
  icon: string;
17
22
  title?: string;
@@ -46,6 +51,7 @@ export type CloseButtonProps = {
46
51
  size?: Size;
47
52
  variant?: Variants;
48
53
  class?: string;
54
+ translations?: TranslationProps<'close'>;
49
55
  } & ButtonOrAnchor;
50
56
  export type IconButtonProps = ButtonBase & {
51
57
  icon: string;
@@ -60,6 +66,10 @@ type StackBaseProps = {
60
66
  fullWidth?: boolean;
61
67
  fullHeight?: boolean;
62
68
  };
69
+ export type ChildData = {
70
+ snippet: Snippet;
71
+ class?: string;
72
+ };
63
73
  export type StackProps = StackBaseProps & {
64
74
  align?: 'start' | 'center' | 'end';
65
75
  direction?: 'row' | 'column';
@@ -86,8 +96,7 @@ export type InputProps = BaseInputProps & {
86
96
  trailingIcon?: Snippet;
87
97
  };
88
98
  export type PasswordInputProps = BaseInputProps & {
89
- showLabel?: string;
90
- hideLabel?: string;
99
+ translations?: TranslationProps<'showPassword' | 'hidePassword'>;
91
100
  isVisible?: boolean;
92
101
  };
93
102
  export type SelectItem = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@immich/ui",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "license": "GNU Affero General Public License version 3",
5
5
  "scripts": {
6
6
  "create": "node scripts/create.js",
@@ -53,7 +53,7 @@
53
53
  "prettier": "^3.3.2",
54
54
  "prettier-plugin-svelte": "^3.2.6",
55
55
  "prettier-plugin-tailwindcss": "^0.6.5",
56
- "publint": "^0.2.0",
56
+ "publint": "^0.3.0",
57
57
  "svelte": "^5.0.0",
58
58
  "svelte-check": "^4.0.0",
59
59
  "svelte-highlight": "^7.8.0",