uisv 0.0.20 → 0.0.22

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 (76) hide show
  1. package/dist/components/accordion.svelte +20 -21
  2. package/dist/components/accordion.svelte.d.ts +10 -10
  3. package/dist/components/alert.svelte +22 -28
  4. package/dist/components/alert.svelte.d.ts +5 -5
  5. package/dist/components/app.svelte +57 -0
  6. package/dist/components/app.svelte.d.ts +15 -0
  7. package/dist/components/badge.svelte +33 -38
  8. package/dist/components/badge.svelte.d.ts +3 -3
  9. package/dist/components/banner.svelte +47 -55
  10. package/dist/components/banner.svelte.d.ts +5 -5
  11. package/dist/components/breadcrumb.svelte +6 -6
  12. package/dist/components/breadcrumb.svelte.d.ts +4 -25
  13. package/dist/components/button.svelte +36 -48
  14. package/dist/components/button.svelte.d.ts +12 -12
  15. package/dist/components/calendar.svelte +6 -7
  16. package/dist/components/calendar.svelte.d.ts +3 -3
  17. package/dist/components/card.svelte +14 -15
  18. package/dist/components/card.svelte.d.ts +5 -5
  19. package/dist/components/checkbox-group.svelte +12 -13
  20. package/dist/components/checkbox-group.svelte.d.ts +4 -4
  21. package/dist/components/checkbox.svelte +39 -38
  22. package/dist/components/checkbox.svelte.d.ts +6 -6
  23. package/dist/components/chip.svelte +21 -22
  24. package/dist/components/chip.svelte.d.ts +3 -3
  25. package/dist/components/collapsible.svelte +4 -5
  26. package/dist/components/collapsible.svelte.d.ts +4 -4
  27. package/dist/components/color-picker.svelte +1 -1
  28. package/dist/components/h1.svelte +8 -7
  29. package/dist/components/h2.svelte +12 -11
  30. package/dist/components/h3.svelte +9 -8
  31. package/dist/components/h4.svelte +12 -11
  32. package/dist/components/h5.svelte +12 -11
  33. package/dist/components/h6.svelte +12 -11
  34. package/dist/components/icon.svelte +0 -2
  35. package/dist/components/index.d.ts +6 -0
  36. package/dist/components/index.js +6 -0
  37. package/dist/components/input-number.svelte +5 -7
  38. package/dist/components/input-number.svelte.d.ts +5 -5
  39. package/dist/components/input-time.svelte +11 -12
  40. package/dist/components/input-time.svelte.d.ts +6 -6
  41. package/dist/components/input.svelte +11 -12
  42. package/dist/components/input.svelte.d.ts +6 -6
  43. package/dist/components/kbd.svelte +6 -7
  44. package/dist/components/kbd.svelte.d.ts +2 -2
  45. package/dist/components/modal.svelte +189 -0
  46. package/dist/components/modal.svelte.d.ts +33 -0
  47. package/dist/components/p.svelte +3 -1
  48. package/dist/components/pin-input.svelte +10 -11
  49. package/dist/components/pin-input.svelte.d.ts +3 -3
  50. package/dist/components/placeholder.svelte +4 -4
  51. package/dist/components/popover.svelte +33 -61
  52. package/dist/components/popover.svelte.d.ts +8 -30
  53. package/dist/components/progress.svelte +22 -21
  54. package/dist/components/progress.svelte.d.ts +5 -5
  55. package/dist/components/select.svelte +48 -53
  56. package/dist/components/select.svelte.d.ts +22 -29
  57. package/dist/components/seperator.svelte +6 -7
  58. package/dist/components/seperator.svelte.d.ts +6 -6
  59. package/dist/components/slider.svelte +13 -14
  60. package/dist/components/slider.svelte.d.ts +4 -4
  61. package/dist/components/switch.svelte +17 -22
  62. package/dist/components/switch.svelte.d.ts +6 -6
  63. package/dist/components/tabs.svelte +19 -20
  64. package/dist/components/tabs.svelte.d.ts +7 -7
  65. package/dist/components/tooltip.svelte +94 -0
  66. package/dist/components/tooltip.svelte.d.ts +24 -0
  67. package/dist/contexts.d.ts +47 -0
  68. package/dist/contexts.js +46 -0
  69. package/dist/index.d.ts +1 -0
  70. package/dist/index.js +1 -0
  71. package/dist/mode.d.ts +89 -0
  72. package/dist/mode.js +1 -0
  73. package/dist/utilities.svelte.d.ts +1 -1
  74. package/dist/vite.d.ts +2 -1
  75. package/dist/vite.js +32 -37
  76. package/package.json +31 -26
@@ -2,18 +2,19 @@
2
2
  import type { SvelteHTMLElements } from 'svelte/elements';
3
3
  import { cn } from 'tailwind-variants';
4
4
  const { children, class: classes, ...rest }: SvelteHTMLElements['h4'] = $props();
5
+
6
+ const classname = $derived(
7
+ cn(
8
+ 'relative text-2xl text-label-highlighted font-bold mt-12 mb-6',
9
+ 'scroll-mt-[calc(48px+45px+var(--ui-header-height))] lg:scroll-mt-[calc(48px+var(--ui-header-height))]',
10
+ 'hover:[&>a>code]:border-primary hover:[&>a>code]:text-primary',
11
+ '[&>a>code]:transition-colors [&>a>code]:text-xl/7 [&>a>code]:font-bold [&>a>code]:border-dashed',
12
+ '[&>a]:focus-visible:outline-primary',
13
+ classes,
14
+ ),
15
+ );
5
16
  </script>
6
17
 
7
- <h4
8
- {...rest}
9
- class={cn(
10
- 'relative text-2xl text-highlighted font-bold mt-12 mb-6',
11
- 'scroll-mt-[calc(48px+45px+var(--ui-header-height))] lg:scroll-mt-[calc(48px+var(--ui-header-height))]',
12
- 'hover:[&>a>code]:border-primary hover:[&>a>code]:text-primary',
13
- '[&>a>code]:transition-colors [&>a>code]:text-xl/7 [&>a>code]:font-bold [&>a>code]:border-dashed',
14
- '[&>a]:focus-visible:outline-primary',
15
- classes,
16
- )}
17
- >
18
+ <h4 {...rest} class={classname}>
18
19
  {@render children?.()}
19
20
  </h4>
@@ -2,18 +2,19 @@
2
2
  import type { SvelteHTMLElements } from 'svelte/elements';
3
3
  import { cn } from 'tailwind-variants';
4
4
  const { children, class: classes, ...rest }: SvelteHTMLElements['h5'] = $props();
5
+
6
+ const classname = $derived(
7
+ cn(
8
+ 'relative text-2xl text-label-highlighted font-bold mt-12 mb-6',
9
+ 'scroll-mt-[calc(48px+45px+var(--ui-header-height))] lg:scroll-mt-[calc(48px+var(--ui-header-height))]',
10
+ 'hover:[&>a>code]:border-primary hover:[&>a>code]:text-primary',
11
+ '[&>a>code]:transition-colors [&>a>code]:text-xl/7 [&>a>code]:font-bold [&>a>code]:border-dashed',
12
+ '[&>a]:focus-visible:outline-primary',
13
+ classes,
14
+ ),
15
+ );
5
16
  </script>
6
17
 
7
- <h5
8
- {...rest}
9
- class={cn(
10
- 'relative text-2xl text-highlighted font-bold mt-12 mb-6',
11
- 'scroll-mt-[calc(48px+45px+var(--ui-header-height))] lg:scroll-mt-[calc(48px+var(--ui-header-height))]',
12
- 'hover:[&>a>code]:border-primary hover:[&>a>code]:text-primary',
13
- '[&>a>code]:transition-colors [&>a>code]:text-xl/7 [&>a>code]:font-bold [&>a>code]:border-dashed',
14
- '[&>a]:focus-visible:outline-primary',
15
- classes,
16
- )}
17
- >
18
+ <h5 {...rest} class={classname}>
18
19
  {@render children?.()}
19
20
  </h5>
@@ -2,18 +2,19 @@
2
2
  import type { SvelteHTMLElements } from 'svelte/elements';
3
3
  import { cn } from 'tailwind-variants';
4
4
  const { children, class: classes, ...rest }: SvelteHTMLElements['h6'] = $props();
5
+
6
+ const classname = $derived(
7
+ cn(
8
+ 'relative text-2xl text-label-highlighted font-bold mt-12 mb-6',
9
+ 'scroll-mt-[calc(48px+45px+var(--ui-header-height))] lg:scroll-mt-[calc(48px+var(--ui-header-height))]',
10
+ 'hover:[&>a>code]:border-primary hover:[&>a>code]:text-primary',
11
+ '[&>a>code]:transition-colors [&>a>code]:text-xl/7 [&>a>code]:font-bold [&>a>code]:border-dashed',
12
+ '[&>a]:focus-visible:outline-primary',
13
+ classes,
14
+ ),
15
+ );
5
16
  </script>
6
17
 
7
- <h6
8
- {...rest}
9
- class={cn(
10
- 'relative text-2xl text-highlighted font-bold mt-12 mb-6',
11
- 'scroll-mt-[calc(48px+45px+var(--ui-header-height))] lg:scroll-mt-[calc(48px+var(--ui-header-height))]',
12
- 'hover:[&>a>code]:border-primary hover:[&>a>code]:text-primary',
13
- '[&>a>code]:transition-colors [&>a>code]:text-xl/7 [&>a>code]:font-bold [&>a>code]:border-dashed',
14
- '[&>a]:focus-visible:outline-primary',
15
- classes,
16
- )}
17
- >
18
+ <h6 {...rest} class={classname}>
18
19
  {@render children?.()}
19
20
  </h6>
@@ -46,8 +46,6 @@
46
46
  },
47
47
  );
48
48
 
49
- $inspect(isComponent(name), name);
50
-
51
49
  useStyle(() => css_style);
52
50
  </script>
53
51
 
@@ -55,3 +55,9 @@ export * from './breadcrumb.svelte';
55
55
  export { default as Breadcrumb } from './breadcrumb.svelte';
56
56
  export * from './input-number.svelte';
57
57
  export { default as InputNumber } from './input-number.svelte';
58
+ export * from './modal.svelte';
59
+ export { default as Modal } from './modal.svelte';
60
+ export * from './tooltip.svelte';
61
+ export { default as Tooltip } from './tooltip.svelte';
62
+ export * from './app.svelte';
63
+ export { default as App } from './app.svelte';
@@ -55,3 +55,9 @@ export * from './breadcrumb.svelte';
55
55
  export { default as Breadcrumb } from './breadcrumb.svelte';
56
56
  export * from './input-number.svelte';
57
57
  export { default as InputNumber } from './input-number.svelte';
58
+ export * from './modal.svelte';
59
+ export { default as Modal } from './modal.svelte';
60
+ export * from './tooltip.svelte';
61
+ export { default as Tooltip } from './tooltip.svelte';
62
+ export * from './app.svelte';
63
+ export { default as App } from './app.svelte';
@@ -7,9 +7,7 @@
7
7
  type PropVariant,
8
8
  } from '../index.js';
9
9
  import type { SvelteHTMLElements } from 'svelte/elements';
10
- import type { ClassNameValue } from 'tailwind-merge';
11
- import { tv } from 'tailwind-variants';
12
- import Accordion from './accordion.svelte';
10
+ import { tv, type ClassValue } from 'tailwind-variants';
13
11
  import { useId } from 'bits-ui';
14
12
 
15
13
  export type InputNumberProps = Omit<SvelteHTMLElements['input'], 'size' | 'value'> & {
@@ -38,10 +36,10 @@
38
36
  focusonchange?: boolean;
39
37
  autocomplete?: 'on' | 'off' | string;
40
38
  ui?: {
41
- root?: ClassNameValue;
42
- base?: ClassNameValue;
43
- increment?: ClassNameValue;
44
- decrement?: ClassNameValue;
39
+ root?: ClassValue;
40
+ base?: ClassValue;
41
+ increment?: ClassValue;
42
+ decrement?: ClassValue;
45
43
  };
46
44
  };
47
45
  </script>
@@ -1,6 +1,6 @@
1
1
  import { type ButtonProps, type PropColor, type PropSize, type PropVariant } from '../index.js';
2
2
  import type { SvelteHTMLElements } from 'svelte/elements';
3
- import type { ClassNameValue } from 'tailwind-merge';
3
+ import { type ClassValue } from 'tailwind-variants';
4
4
  export type InputNumberProps = Omit<SvelteHTMLElements['input'], 'size' | 'value'> & {
5
5
  value?: number;
6
6
  placeholder?: string;
@@ -27,10 +27,10 @@ export type InputNumberProps = Omit<SvelteHTMLElements['input'], 'size' | 'value
27
27
  focusonchange?: boolean;
28
28
  autocomplete?: 'on' | 'off' | string;
29
29
  ui?: {
30
- root?: ClassNameValue;
31
- base?: ClassNameValue;
32
- increment?: ClassNameValue;
33
- decrement?: ClassNameValue;
30
+ root?: ClassValue;
31
+ base?: ClassValue;
32
+ increment?: ClassValue;
33
+ decrement?: ClassValue;
34
34
  };
35
35
  };
36
36
  declare const InputNumber: import("svelte").Component<InputNumberProps, {}, "value">;
@@ -1,8 +1,7 @@
1
1
  <script module lang="ts">
2
2
  import { type PropColor, type PropVariant } from '../index.js';
3
3
  import type { Component, Snippet } from 'svelte';
4
- import type { ClassNameValue } from 'tailwind-merge';
5
- import { tv } from 'tailwind-variants';
4
+ import { tv, type ClassValue } from 'tailwind-variants';
6
5
  import { Time } from '../date.js';
7
6
 
8
7
  export { default as InputTime } from './input-time.svelte';
@@ -45,11 +44,11 @@
45
44
  value?: Time;
46
45
  icon?: string | Snippet | Component;
47
46
  ui?: {
48
- root?: ClassNameValue;
49
- leading?: ClassNameValue;
50
- icon?: ClassNameValue;
51
- trailing?: ClassNameValue;
52
- segment?: ClassNameValue;
47
+ root?: ClassValue;
48
+ leading?: ClassValue;
49
+ icon?: ClassValue;
50
+ trailing?: ClassValue;
51
+ segment?: ClassValue;
53
52
  };
54
53
  };
55
54
  </script>
@@ -74,12 +73,12 @@
74
73
  tv({
75
74
  slots: {
76
75
  root: 'inline-flex items-center rounded transition-all ring ring-inset ring-transparent',
77
- leading: 'text-muted',
78
- trailing: 'text-muted',
76
+ leading: 'text-label-muted',
77
+ trailing: 'text-label-muted',
79
78
  icon: '',
80
79
  segment: [
81
80
  'rounded text-center outline-hidden transition-all focus:bg-surface-accented shrink',
82
- 'aria-[valuetext="Empty"]:text-dimmed data-[segment="literal"]:text-muted data-[segment="literal"]:px-1 data-invalid:text-error data-disabled:cursor-not-allowed data-disabled:opacity-75',
81
+ 'aria-[valuetext="Empty"]:text-label-dimmed data-[segment="literal"]:text-label-muted data-[segment="literal"]:px-1 data-invalid:text-error data-disabled:cursor-not-allowed data-disabled:opacity-75',
83
82
  ],
84
83
  },
85
84
  variants: {
@@ -158,7 +157,7 @@
158
157
  true: '',
159
158
  },
160
159
  type: {
161
- file: 'file:me-1.5 file:font-medium file:text-muted file:outline-none',
160
+ file: 'file:me-1.5 file:font-medium file:text-label-muted file:outline-none',
162
161
  },
163
162
  },
164
163
  compoundVariants: [
@@ -175,7 +174,7 @@
175
174
  variant: ['outline', 'subtle'],
176
175
  highlight: true,
177
176
  class: {
178
- root: 'ring-surface-800 ring-2',
177
+ root: 'ring-surface-inverted ring-2',
179
178
  },
180
179
  },
181
180
  {
@@ -1,6 +1,6 @@
1
1
  import { type PropColor, type PropVariant } from '../index.js';
2
2
  import type { Component, Snippet } from 'svelte';
3
- import type { ClassNameValue } from 'tailwind-merge';
3
+ import { type ClassValue } from 'tailwind-variants';
4
4
  import { Time } from '../date.js';
5
5
  export { default as InputTime } from './input-time.svelte';
6
6
  export type InputTimeProps = {
@@ -41,11 +41,11 @@ export type InputTimeProps = {
41
41
  value?: Time;
42
42
  icon?: string | Snippet | Component;
43
43
  ui?: {
44
- root?: ClassNameValue;
45
- leading?: ClassNameValue;
46
- icon?: ClassNameValue;
47
- trailing?: ClassNameValue;
48
- segment?: ClassNameValue;
44
+ root?: ClassValue;
45
+ leading?: ClassValue;
46
+ icon?: ClassValue;
47
+ trailing?: ClassValue;
48
+ segment?: ClassValue;
49
49
  };
50
50
  };
51
51
  declare const InputTime: Component<InputTimeProps, {}, "value">;
@@ -2,10 +2,9 @@
2
2
  import { type PropColor, type PropVariant, isComponent, isSnippet } from '../index.js';
3
3
  import type { Component, Snippet } from 'svelte';
4
4
  import type { SvelteHTMLElements } from 'svelte/elements';
5
- import type { ClassNameValue } from 'tailwind-merge';
6
5
  import { maska } from 'maska/svelte';
7
6
  import { type MaskInputOptions } from 'maska';
8
- import { tv } from 'tailwind-variants';
7
+ import { tv, type ClassValue } from 'tailwind-variants';
9
8
 
10
9
  export type InputProps = Omit<SvelteHTMLElements['input'], 'size'> & {
11
10
  name?: string;
@@ -47,11 +46,11 @@
47
46
  loadingicon?: string | Component;
48
47
  mask?: string | MaskInputOptions;
49
48
  ui?: {
50
- root?: ClassNameValue;
51
- base?: ClassNameValue;
52
- leading?: ClassNameValue;
53
- icon?: ClassNameValue;
54
- trailing?: ClassNameValue;
49
+ root?: ClassValue;
50
+ base?: ClassValue;
51
+ leading?: ClassValue;
52
+ icon?: ClassValue;
53
+ trailing?: ClassValue;
55
54
  };
56
55
  };
57
56
  </script>
@@ -84,9 +83,9 @@
84
83
  tv({
85
84
  slots: {
86
85
  root: 'inline-flex items-center rounded transition-all ring ring-inset ring-transparent',
87
- base: 'appearance-none outline-none placeholder:text-muted',
88
- leading: 'text-muted flex items-center',
89
- trailing: 'text-muted flex items-center',
86
+ base: 'appearance-none outline-none placeholder:text-label-muted',
87
+ leading: 'text-label-muted flex items-center',
88
+ trailing: 'text-label-muted flex items-center',
90
89
  icon: '',
91
90
  },
92
91
  variants: {
@@ -162,7 +161,7 @@
162
161
  true: '',
163
162
  },
164
163
  type: {
165
- file: 'file:me-1.5 file:font-medium file:text-muted file:outline-none',
164
+ file: 'file:me-1.5 file:font-medium file:text-label-muted file:outline-none',
166
165
  },
167
166
  },
168
167
  compoundVariants: [
@@ -177,7 +176,7 @@
177
176
  color: 'surface',
178
177
  variant: ['outline', 'subtle'],
179
178
  class: {
180
- root: 'focus-within:ring-surface-800 focus-within:ring-2',
179
+ root: 'focus-within:ring-surface-inverted focus-within:ring-2',
181
180
  },
182
181
  },
183
182
  {
@@ -1,8 +1,8 @@
1
1
  import { type PropColor, type PropVariant } from '../index.js';
2
2
  import type { Component, Snippet } from 'svelte';
3
3
  import type { SvelteHTMLElements } from 'svelte/elements';
4
- import type { ClassNameValue } from 'tailwind-merge';
5
4
  import { type MaskInputOptions } from 'maska';
5
+ import { type ClassValue } from 'tailwind-variants';
6
6
  export type InputProps = Omit<SvelteHTMLElements['input'], 'size'> & {
7
7
  name?: string;
8
8
  /**
@@ -43,11 +43,11 @@ export type InputProps = Omit<SvelteHTMLElements['input'], 'size'> & {
43
43
  loadingicon?: string | Component;
44
44
  mask?: string | MaskInputOptions;
45
45
  ui?: {
46
- root?: ClassNameValue;
47
- base?: ClassNameValue;
48
- leading?: ClassNameValue;
49
- icon?: ClassNameValue;
50
- trailing?: ClassNameValue;
46
+ root?: ClassValue;
47
+ base?: ClassValue;
48
+ leading?: ClassValue;
49
+ icon?: ClassValue;
50
+ trailing?: ClassValue;
51
51
  };
52
52
  };
53
53
  declare const Input: Component<InputProps, {}, "value">;
@@ -1,8 +1,7 @@
1
1
  <script module lang="ts">
2
2
  import type { PropColor, PropVariant } from '../index.js';
3
3
  import type { Snippet } from 'svelte';
4
- import type { ClassNameValue } from 'tailwind-merge';
5
- import { tv } from 'tailwind-variants';
4
+ import { tv, type ClassValue } from 'tailwind-variants';
6
5
 
7
6
  export type KbdProps = {
8
7
  children?: Snippet;
@@ -10,7 +9,7 @@
10
9
  color?: PropColor;
11
10
  variant?: Exclude<PropVariant, 'none' | 'ghost'>;
12
11
  size?: 'sm' | 'md' | 'lg';
13
- class?: ClassNameValue;
12
+ class?: ClassValue;
14
13
  };
15
14
 
16
15
  export const KBD_KEYS = {
@@ -110,7 +109,7 @@
110
109
  {
111
110
  color: 'surface',
112
111
  variant: 'outline',
113
- class: 'border-surface-600',
112
+ class: 'border-label-toned',
114
113
  },
115
114
  {
116
115
  color: 'info',
@@ -142,7 +141,7 @@
142
141
  {
143
142
  color: 'surface',
144
143
  variant: 'solid',
145
- class: 'bg-surface-600 border-surface-700',
144
+ class: 'bg-label-toned border-label-highlighted',
146
145
  },
147
146
  {
148
147
  color: 'info',
@@ -174,7 +173,7 @@
174
173
  {
175
174
  color: 'surface',
176
175
  variant: 'soft',
177
- class: 'bg-surface-100 text-surface-700',
176
+ class: 'bg-surface-elevated text-label-toned',
178
177
  },
179
178
  {
180
179
  color: 'info',
@@ -206,7 +205,7 @@
206
205
  {
207
206
  color: 'surface',
208
207
  variant: 'subtle',
209
- class: 'bg-surface-100 border-surface-200 text-surface-700',
208
+ class: 'bg-surface-muted border-surface-accented text-label-toned',
210
209
  },
211
210
  {
212
211
  color: 'info',
@@ -1,13 +1,13 @@
1
1
  import type { PropColor, PropVariant } from '../index.js';
2
2
  import type { Snippet } from 'svelte';
3
- import type { ClassNameValue } from 'tailwind-merge';
3
+ import { type ClassValue } from 'tailwind-variants';
4
4
  export type KbdProps = {
5
5
  children?: Snippet;
6
6
  value?: string;
7
7
  color?: PropColor;
8
8
  variant?: Exclude<PropVariant, 'none' | 'ghost'>;
9
9
  size?: 'sm' | 'md' | 'lg';
10
- class?: ClassNameValue;
10
+ class?: ClassValue;
11
11
  };
12
12
  export declare const KBD_KEYS: {
13
13
  meta: string;
@@ -0,0 +1,189 @@
1
+ <script module lang="ts">
2
+ import { Dialog, type DialogContentProps, type PortalProps } from 'bits-ui';
3
+ import { tv, type ClassValue } from 'tailwind-variants';
4
+ import { Button, isComponent, isSnippet, type ButtonProps } from '../index.js';
5
+ import type { Component, Snippet } from 'svelte';
6
+ import defu from 'defu';
7
+ import { fade, scale } from 'svelte/transition';
8
+ import { cubicIn } from 'svelte/easing';
9
+ import { app_icons } from '../contexts.js';
10
+
11
+ export type ModalProps = {
12
+ open?: boolean;
13
+ trigger?: ButtonProps;
14
+ ui?: {
15
+ overlay?: ClassValue;
16
+ content?: ClassValue;
17
+ header?: ClassValue;
18
+ body?: ClassValue;
19
+ footer?: ClassValue;
20
+ title?: ClassValue;
21
+ description?: ClassValue;
22
+ };
23
+ children?: Snippet;
24
+ title?: string | Snippet<[Record<string, unknown>]> | Component;
25
+ description?: string | Snippet<[Record<string, unknown>]> | Component;
26
+ footer?: Snippet<[{ close: () => void }]>;
27
+ close?: boolean | ButtonProps;
28
+ transition?: boolean;
29
+ overlay?: boolean;
30
+ fullscreen?: boolean;
31
+ dismissable?: boolean;
32
+ portal?: PortalProps;
33
+ content?: DialogContentProps;
34
+ };
35
+ </script>
36
+
37
+ <script lang="ts">
38
+ let {
39
+ open = $bindable(false),
40
+ trigger,
41
+ ui = {},
42
+ children,
43
+ title,
44
+ description,
45
+ footer,
46
+ close = true,
47
+ transition = true,
48
+ overlay = true,
49
+ fullscreen,
50
+ dismissable = true,
51
+ portal,
52
+ content,
53
+ }: ModalProps = $props();
54
+
55
+ let content_element = $state<HTMLDivElement | null>(null);
56
+
57
+ const variants = $derived(
58
+ tv({
59
+ slots: {
60
+ content:
61
+ 'z-[calc(var(--bits-dialog-depth)*10+11)] fixed bg-surface-base border border-surface-accented rounded-md divide-y divide-surface-accented flex flex-col overflow-hidden pointer-events-auto',
62
+ overlay: 'fixed inset-0 bg-surface-elevated/75 z-[calc(var(--bits-dialog-depth)*10+10)] ',
63
+ header: 'flex items-center gap-1.5 p-4 sm:px-6',
64
+ body: 'flex-1 p-4 sm:p-6 overflow-y-auto',
65
+ footer: 'flex items-center gap-1.5 p-4 sm:px-6',
66
+ title: 'text-label-highlighted font-semibold select-all',
67
+ description: 'mt-1 text-label-muted text-sm',
68
+ },
69
+ variants: {
70
+ fullscreen: {
71
+ true: {
72
+ content: 'inset-0',
73
+ },
74
+ false: {
75
+ content:
76
+ '-translate-1/2 top-1/2 left-1/2 max-h-[calc(100dvh-2rem)] sm:max-h-[calc(100dvh-4rem)] max-w-lg w-full',
77
+ },
78
+ },
79
+ },
80
+ })({ fullscreen }),
81
+ );
82
+ </script>
83
+
84
+ <Dialog.Root bind:open>
85
+ {#if trigger}
86
+ <Dialog.Trigger>
87
+ {#snippet child({ props })}
88
+ <Button {...props} {...trigger} />
89
+ {/snippet}
90
+ </Dialog.Trigger>
91
+ {/if}
92
+
93
+ <Dialog.Portal {...portal}>
94
+ <Dialog.Overlay forceMount>
95
+ {#snippet child({ props })}
96
+ {#if overlay && open}
97
+ <div
98
+ {...props}
99
+ class={variants.overlay({
100
+ class: [ui.overlay],
101
+ })}
102
+ transition:fade={{ duration: transition ? 200 : 0 }}
103
+ ></div>
104
+ {/if}
105
+ {/snippet}
106
+ </Dialog.Overlay>
107
+
108
+ <Dialog.Content
109
+ {...content}
110
+ forceMount
111
+ escapeKeydownBehavior={dismissable ? 'close' : 'ignore'}
112
+ interactOutsideBehavior={dismissable ? 'close' : 'ignore'}
113
+ onInteractOutside={(e) => {
114
+ if (content_element?.contains(e.target as Node)) e.preventDefault();
115
+ if (content?.onInteractOutside) content.onInteractOutside(e);
116
+ }}
117
+ >
118
+ {#snippet child({ props })}
119
+ {#if open}
120
+ <div
121
+ bind:this={content_element}
122
+ {...props}
123
+ class={variants.content({ class: ui.content })}
124
+ transition:scale={{
125
+ duration: transition ? 200 : 0,
126
+ easing: cubicIn,
127
+ start: 0.95,
128
+ opacity: 0,
129
+ }}
130
+ >
131
+ {#if title || description}
132
+ <div class={variants.header({ class: ui.header })}>
133
+ <div class="flex-1">
134
+ {#if typeof title === 'string'}
135
+ <h1 class={variants.title({ class: ui.title })}>{title}</h1>
136
+ {:else if isSnippet(title)}
137
+ {@render title({ class: variants.title({ class: ui.title }) })}
138
+ {:else if isComponent(title)}
139
+ {@const Comp = title}
140
+
141
+ <Comp class={variants.title({ class: ui.title })} />
142
+ {/if}
143
+
144
+ {#if typeof description === 'string'}
145
+ <h1 class={variants.description({ class: ui.description })}>{description}</h1>
146
+ {:else if isSnippet(description)}
147
+ {@render description({
148
+ class: variants.description({ class: ui.description }),
149
+ })}
150
+ {:else if isComponent(title)}
151
+ {@const Comp = description}
152
+
153
+ <Comp class={variants.description({ class: ui.description })} />
154
+ {/if}
155
+ </div>
156
+
157
+ {#if close}
158
+ <Button
159
+ {...props}
160
+ {...defu(typeof close === 'boolean' ? {} : close, <ButtonProps>{
161
+ variant: 'ghost',
162
+ color: 'surface',
163
+ icon: app_icons.get().close,
164
+ onclick() {
165
+ open = false;
166
+ },
167
+ })}
168
+ />
169
+ {/if}
170
+ </div>
171
+ {/if}
172
+
173
+ <div class={variants.body({ class: ui.body })}>
174
+ {@render children?.()}
175
+ </div>
176
+
177
+ {#if footer}
178
+ <div class={variants.footer({ class: ui.footer })}>
179
+ {@render footer({
180
+ close: () => (open = false),
181
+ })}
182
+ </div>
183
+ {/if}
184
+ </div>
185
+ {/if}
186
+ {/snippet}
187
+ </Dialog.Content>
188
+ </Dialog.Portal>
189
+ </Dialog.Root>
@@ -0,0 +1,33 @@
1
+ import { type DialogContentProps, type PortalProps } from 'bits-ui';
2
+ import { type ClassValue } from 'tailwind-variants';
3
+ import { type ButtonProps } from '../index.js';
4
+ import type { Component, Snippet } from 'svelte';
5
+ export type ModalProps = {
6
+ open?: boolean;
7
+ trigger?: ButtonProps;
8
+ ui?: {
9
+ overlay?: ClassValue;
10
+ content?: ClassValue;
11
+ header?: ClassValue;
12
+ body?: ClassValue;
13
+ footer?: ClassValue;
14
+ title?: ClassValue;
15
+ description?: ClassValue;
16
+ };
17
+ children?: Snippet;
18
+ title?: string | Snippet<[Record<string, unknown>]> | Component;
19
+ description?: string | Snippet<[Record<string, unknown>]> | Component;
20
+ footer?: Snippet<[{
21
+ close: () => void;
22
+ }]>;
23
+ close?: boolean | ButtonProps;
24
+ transition?: boolean;
25
+ overlay?: boolean;
26
+ fullscreen?: boolean;
27
+ dismissable?: boolean;
28
+ portal?: PortalProps;
29
+ content?: DialogContentProps;
30
+ };
31
+ declare const Modal: Component<ModalProps, {}, "open">;
32
+ type Modal = ReturnType<typeof Modal>;
33
+ export default Modal;
@@ -2,8 +2,10 @@
2
2
  import type { SvelteHTMLElements } from 'svelte/elements';
3
3
  import { cn } from 'tailwind-variants';
4
4
  const { children, class: classes }: SvelteHTMLElements['p'] = $props();
5
+
6
+ const classname = $derived(cn('my-5 leading-7 text-pretty', classes));
5
7
  </script>
6
8
 
7
- <p class={cn('my-5 leading-7 text-pretty', classes)}>
9
+ <p class={classname}>
8
10
  {@render children?.()}
9
11
  </p>