@immich/ui 0.9.0 → 0.10.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.
@@ -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?.()}
@@ -1,48 +1,52 @@
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 flex-col w-full h-full',
48
+ variants: {
49
+ color: {
46
50
  primary: 'bg-primary/25 dark:bg-primary/25',
47
51
  secondary: 'bg-dark/5 dark:bg-dark/25 text-dark',
48
52
  success: 'bg-success/15 dark:bg-success/30',
@@ -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;
@@ -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>
@@ -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,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,17 @@
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
+ controlledOpen?: boolean;
7
+ } & {
8
+ children?: Snippet | undefined;
9
+ } & {
10
+ title: string;
11
+ size?: ModalSize;
12
+ class?: string;
13
+ open?: boolean;
14
+ expandable?: boolean;
15
+ children: Snippet;
16
+ }, {}, "open">;
17
+ 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;
@@ -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
@@ -19,6 +19,9 @@ export { default as CardDescription } from './components/Card/CardDescription.sv
19
19
  export { default as CardFooter } from './components/Card/CardFooter.svelte';
20
20
  export { default as CardHeader } from './components/Card/CardHeader.svelte';
21
21
  export { default as CardTitle } from './components/Card/CardTitle.svelte';
22
+ export { default as Modal } from './components/Modal/Modal.svelte';
23
+ export { default as ModalBody } from './components/Modal/ModalBody.svelte';
24
+ export { default as ModalFooter } from './components/Modal/ModalFooter.svelte';
22
25
  export { default as CloseButton } from './components/CloseButton/CloseButton.svelte';
23
26
  export { default as Code } from './components/Code/Code.svelte';
24
27
  export { default as Checkbox } from './components/Form/Checkbox.svelte';
package/dist/index.js CHANGED
@@ -21,6 +21,9 @@ export { default as CardDescription } from './components/Card/CardDescription.sv
21
21
  export { default as CardFooter } from './components/Card/CardFooter.svelte';
22
22
  export { default as CardHeader } from './components/Card/CardHeader.svelte';
23
23
  export { default as CardTitle } from './components/Card/CardTitle.svelte';
24
+ export { default as Modal } from './components/Modal/Modal.svelte';
25
+ export { default as ModalBody } from './components/Modal/ModalBody.svelte';
26
+ export { default as ModalFooter } from './components/Modal/ModalFooter.svelte';
24
27
  export { default as CloseButton } from './components/CloseButton/CloseButton.svelte';
25
28
  export { default as Code } from './components/Code/Code.svelte';
26
29
  export { default as Checkbox } from './components/Form/Checkbox.svelte';
@@ -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;
package/dist/types.d.ts CHANGED
@@ -4,6 +4,7 @@ export type Color = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' |
4
4
  export type TextColor = Color | 'muted';
5
5
  export type HeadingColor = TextColor;
6
6
  export type Size = 'tiny' | 'small' | 'medium' | 'large' | 'giant';
7
+ export type ModalSize = Size | 'full';
7
8
  export type HeadingSize = Size | 'title';
8
9
  export type Shape = 'rectangle' | 'semi-round' | 'round';
9
10
  export type Variants = 'filled' | 'outline' | 'ghost';
@@ -60,6 +61,10 @@ type StackBaseProps = {
60
61
  fullWidth?: boolean;
61
62
  fullHeight?: boolean;
62
63
  };
64
+ export type ChildData = {
65
+ snippet: Snippet;
66
+ class?: string;
67
+ };
63
68
  export type StackProps = StackBaseProps & {
64
69
  align?: 'start' | 'center' | 'end';
65
70
  direction?: 'row' | 'column';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@immich/ui",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "license": "GNU Affero General Public License version 3",
5
5
  "scripts": {
6
6
  "create": "node scripts/create.js",