@r2digisolutions/ui 0.25.5 → 0.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,10 +3,11 @@
3
3
  import type { DialogProps } from './type.js';
4
4
  import { createDialogContext } from './context.svelte';
5
5
  import { tick } from 'svelte';
6
+ import { STYLES } from '../../../constants/styles.js';
6
7
 
7
8
  let {
8
9
  open = $bindable(),
9
- padding = 'md',
10
+ padding = 'none',
10
11
  children,
11
12
  header,
12
13
  footer,
@@ -14,6 +15,9 @@
14
15
  size = 'lg',
15
16
  onOpenChange,
16
17
  closedby = 'any',
18
+ aside,
19
+ asideWidth = '320px',
20
+ showGridBackground = false,
17
21
  ...props
18
22
  }: DialogProps = $props();
19
23
 
@@ -25,11 +29,13 @@
25
29
  onclose?.();
26
30
  };
27
31
 
32
+ (cx as any).onclose = _onclose;
33
+
28
34
  const paddings: Record<typeof padding, string> = {
29
35
  none: 'p-0',
30
- sm: 'md:p-4 p-4',
31
- md: 'md:p-6 p-4',
32
- lg: 'md:p-8 p-4'
36
+ sm: 'p-4 md:p-4',
37
+ md: 'p-4 md:p-6',
38
+ lg: 'p-4 md:p-8'
33
39
  };
34
40
 
35
41
  const sizes: Record<typeof size, string> = {
@@ -44,9 +50,12 @@
44
50
  '5xl': 'w-full md:max-w-5xl',
45
51
  '6xl': 'w-full md:max-w-6xl',
46
52
  '7xl': 'w-full md:max-w-7xl',
47
- full: 'w-full md:max-w-full h-full md:h-full'
53
+ full: 'w-full max-w-full h-full max-h-full'
48
54
  };
49
55
 
56
+ const effectiveSize = $derived(cx.is_maximized ? 'full' : size);
57
+ const effectivePadding = $derived(cx.is_minimized ? 'none' : padding);
58
+
50
59
  $effect(() => {
51
60
  if (open) {
52
61
  document.body.style.overflow = 'hidden';
@@ -65,21 +74,76 @@
65
74
  bind:this={cx.ref_dialog}
66
75
  aria-modal="true"
67
76
  class={[
68
- 'fixed inset-0 flex h-full max-h-full w-full max-w-full flex-col gap-4 overflow-hidden bg-white shadow-lg duration-200 backdrop:bg-black/50 backdrop:backdrop-blur-xs md:m-auto md:h-fit dark:border-gray-600 dark:bg-gray-800',
69
- props.class,
70
- // paddings[padding],
71
- sizes[size],
72
- {
73
- 'sm:rounded-lg': size !== 'full'
74
- }
77
+ 'fixed inset-0 z-50 m-0 flex h-full max-h-full w-full max-w-full items-center justify-center p-5 backdrop:p-0',
78
+ 'bg-transparent backdrop:bg-black/60 backdrop:backdrop-blur-sm',
79
+ 'duration-200',
80
+ props.class
75
81
  ]}
76
82
  >
77
- {#if header}
78
- {@render header()}
79
- {/if}
80
- {@render children()}
81
- {#if footer}
82
- {@render footer()}
83
- {/if}
83
+ <div
84
+ class={[
85
+ 'flex max-h-[min(90vh,700px)] flex-col overflow-hidden',
86
+ STYLES.SHELL_TRANSPARENT,
87
+ paddings[effectivePadding],
88
+ sizes[effectiveSize],
89
+ effectiveSize !== 'full' && 'rounded-lg'
90
+ ]}
91
+ >
92
+ {#if aside}
93
+ <!-- Layout con sidebar (similar a tu React LayoutWithAside) -->
94
+ <div
95
+ class="grid h-full w-full gap-0"
96
+ style={`grid-template-columns: minmax(0, ${asideWidth}) minmax(0, 1fr);`}
97
+ >
98
+ <aside
99
+ class="hidden h-full border-r border-neutral-200/80 bg-white/20 p-4 md:block dark:border-neutral-800/80 dark:bg-black/20"
100
+ >
101
+ <div
102
+ class="h-full overflow-hidden rounded-xl bg-white/70 p-3 ring-1 ring-black/10 dark:bg-neutral-900/60 dark:ring-white/10"
103
+ >
104
+ {@render aside()}
105
+ </div>
106
+ </aside>
107
+
108
+ <section class="relative flex h-full flex-1 flex-col overflow-hidden">
109
+ {#if showGridBackground}
110
+ <div
111
+ aria-hidden="true"
112
+ class="pointer-events-none absolute inset-0 opacity-[0.06]"
113
+ style="
114
+ background-image:
115
+ linear-gradient(to bottom, rgba(0,0,0,0.8) 1px, transparent 1px),
116
+ linear-gradient(to right, rgba(0,0,0,0.8) 1px, transparent 1px);
117
+ background-size: 22px 22px;
118
+ "
119
+ ></div>
120
+ {/if}
121
+
122
+ <div class="relative flex h-full flex-col">
123
+ {#if header}
124
+ {@render header()}
125
+ {/if}
126
+
127
+ {@render children()}
128
+
129
+ {#if footer}
130
+ {@render footer()}
131
+ {/if}
132
+ </div>
133
+ </section>
134
+ </div>
135
+ {:else}
136
+ <!-- Layout normal sin sidebar -->
137
+ {#if header}
138
+ {@render header()}
139
+ {/if}
140
+
141
+ {@render children()}
142
+
143
+ {#if footer}
144
+ {@render footer()}
145
+ {/if}
146
+ {/if}
147
+ </div>
84
148
  </dialog>
85
149
  {/if}
@@ -5,9 +5,9 @@
5
5
 
6
6
  const paddings: Record<typeof padding, string> = {
7
7
  none: 'p-0',
8
- sm: 'md:px-4 px-4 pb-4',
9
- md: 'md:px-6 px-4 pb-4',
10
- lg: 'md:px-8 px-4 pb-4'
8
+ sm: 'md:p-4 p-4',
9
+ md: 'md:p-6 p-4',
10
+ lg: 'md:p-8 p-4'
11
11
  };
12
12
  </script>
13
13
 
@@ -4,6 +4,12 @@
4
4
  const { children, ...props }: DialogDescriptionProps = $props();
5
5
  </script>
6
6
 
7
- <p class={['text-md text-center text-pretty sm:text-left dark:text-gray-300', props.class]}>
7
+ <p
8
+ class={[
9
+ 'text-md text-center text-pretty sm:text-left',
10
+ 'text-neutral-600 dark:text-neutral-300',
11
+ props.class
12
+ ]}
13
+ >
8
14
  {@render children()}
9
15
  </p>
@@ -1,19 +1,81 @@
1
1
  <script lang="ts">
2
- import { X } from 'lucide-svelte';
2
+ import { useDialogContext } from './context.svelte.js';
3
3
  import type { DialogPropsgHeaderProps } from './type.js';
4
+ import { X } from 'lucide-svelte';
4
5
 
5
6
  let { children, ...props }: DialogPropsgHeaderProps = $props();
7
+ const dialog = useDialogContext();
8
+
9
+ const handleClose = () => {
10
+ dialog.onclose?.();
11
+ };
12
+
13
+ const handleMinimize = () => {
14
+ dialog.onRequestMinimize?.();
15
+ };
16
+
17
+ const handleMaximize = () => {
18
+ dialog.onRequestMaximize?.();
19
+ };
6
20
  </script>
7
21
 
8
- <header class={['flex flex-col px-6 text-center sm:text-left', props.class, children && 'pt-6']}>
9
- {@render children?.()}
10
- <form method="dialog" class="absolute top-0 right-0">
22
+ <header
23
+ class={[
24
+ 'relative flex flex-col px-6 pb-3 text-center sm:text-left',
25
+ 'border-b border-neutral-200/80 dark:border-neutral-800/80',
26
+ children && 'pt-8',
27
+ props.class
28
+ ]}
29
+ >
30
+ <div class="absolute top-3 left-6 flex items-center gap-2">
31
+ <button
32
+ type="button"
33
+ class="
34
+ inline-flex h-3.5 w-3.5 cursor-pointer items-center justify-center rounded-full
35
+ border border-black/10 bg-[#ff5f57]
36
+ transition hover:border-black/20
37
+ "
38
+ aria-label="Cerrar"
39
+ onclick={handleClose}
40
+ ></button>
41
+ <button
42
+ type="button"
43
+ class="
44
+ inline-flex h-3.5 w-3.5 cursor-pointer items-center justify-center
45
+ rounded-full
46
+ border border-black/10 bg-[#febc2e]
47
+ transition hover:border-black/20
48
+ "
49
+ aria-label="Minimizar"
50
+ onclick={handleMinimize}
51
+ ></button>
52
+ <button
53
+ type="button"
54
+ class="
55
+ inline-flex h-3.5 w-3.5 cursor-pointer items-center justify-center
56
+ rounded-full
57
+ border border-black/10 bg-[#28c840]
58
+ transition hover:border-black/20
59
+ "
60
+ aria-label="Maximizar"
61
+ onclick={handleMaximize}
62
+ ></button>
63
+ </div>
64
+
65
+ <form method="dialog" class="absolute top-2 right-2">
11
66
  <button
12
67
  type="submit"
13
- class="cursor-pointer p-2 text-gray-400 hover:text-gray-500 focus:outline-none"
14
- aria-label="Close"
68
+ class="
69
+ cursor-pointer rounded-full p-1.5
70
+ text-neutral-400 hover:bg-neutral-100/70 hover:text-neutral-700
71
+ focus:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500/70
72
+ dark:text-neutral-500 dark:hover:bg-neutral-800/80 dark:hover:text-neutral-100
73
+ "
74
+ aria-label="Cerrar"
15
75
  >
16
- <X class="h-6 w-6" />
76
+ <X class="h-4 w-4" />
17
77
  </button>
18
78
  </form>
79
+
80
+ {@render children?.()}
19
81
  </header>
@@ -4,6 +4,12 @@
4
4
  const { children, ...props }: DialogTitleProps = $props();
5
5
  </script>
6
6
 
7
- <h2 class={['text-center text-2xl font-bold sm:text-left dark:text-white', props.class]}>
7
+ <h2
8
+ class={[
9
+ 'text-center text-2xl font-bold sm:text-left',
10
+ 'text-neutral-900 dark:text-neutral-50',
11
+ props.class
12
+ ]}
13
+ >
8
14
  {@render children()}
9
15
  </h2>
@@ -2,8 +2,12 @@ export declare class ModalContext {
2
2
  #private;
3
3
  constructor(initialOpen?: boolean);
4
4
  onclose(): void;
5
+ onRequestMinimize(): void;
6
+ onRequestMaximize(): void;
5
7
  get open(): boolean;
6
8
  set open(value: boolean);
7
9
  get ref_dialog(): HTMLDialogElement | undefined;
10
+ get is_minimized(): boolean;
11
+ get is_maximized(): boolean;
8
12
  set ref_dialog(value: HTMLDialogElement | undefined);
9
13
  }
@@ -1,5 +1,7 @@
1
1
  export class ModalContext {
2
2
  #open = $state(false);
3
+ #is_minimized = $state(false);
4
+ #is_maximized = $state(false);
3
5
  #ref_dialog = $state();
4
6
  constructor(initialOpen = false) {
5
7
  this.#open = initialOpen;
@@ -16,6 +18,12 @@ export class ModalContext {
16
18
  this.#open = false;
17
19
  this.#ref_dialog?.close();
18
20
  }
21
+ onRequestMinimize() {
22
+ this.#is_minimized = !this.#is_minimized;
23
+ }
24
+ onRequestMaximize() {
25
+ this.#is_maximized = !this.#is_maximized;
26
+ }
19
27
  get open() {
20
28
  return this.#open;
21
29
  }
@@ -25,6 +33,12 @@ export class ModalContext {
25
33
  get ref_dialog() {
26
34
  return this.#ref_dialog;
27
35
  }
36
+ get is_minimized() {
37
+ return this.#is_minimized;
38
+ }
39
+ get is_maximized() {
40
+ return this.#is_maximized;
41
+ }
28
42
  set ref_dialog(value) {
29
43
  this.#ref_dialog = value;
30
44
  if (value) {
@@ -7,6 +7,9 @@ export interface DialogProps {
7
7
  class?: ClassValue;
8
8
  children: Snippet;
9
9
  open?: boolean;
10
+ aside?: Snippet;
11
+ asideWidth?: string;
12
+ showGridBackground?: boolean;
10
13
  header?: Snippet;
11
14
  footer?: Snippet;
12
15
  onclose?(): void;
@@ -0,0 +1,12 @@
1
+ export declare const STYLES: {
2
+ SHELL: string;
3
+ SHELL_TRANSPARENT: "backdrop-blur-xl ring-1 ring-neutral-200/80 dark:ring-neutral-800/80 shadow-xs shadow-black/10 bg-white/95";
4
+ SHELL_ROUNDED: string;
5
+ INPUT_SHELL: string;
6
+ ITEM_BASE: "flex items-center rounded-xl px-2 py-1.5 select-none transition shadow-none ring-1 ring-transparent border border-transparent";
7
+ ITEM_HOVER: "hover:bg-neutral-100/60 hover:dark:bg-neutral-800/50 cursor-pointer";
8
+ ITEM_ACTIVE: "bg-neutral-50/95 dark:bg-neutral-900/85 ring-1 !ring-indigo-400/60 dark:ring-indigo-500/70 border !border-indigo-200/70 dark:border-indigo-600/70";
9
+ GROUP_TITLE: "px-3 pt-2 pb-1 text-[11px] font-semibold uppercase tracking-wide text-neutral-500 dark:text-neutral-400";
10
+ ACCENT_GRADIENT: "from-indigo-500 via-violet-500 to-blue-500";
11
+ ACCENT: string;
12
+ };
@@ -0,0 +1,23 @@
1
+ const SHELL_TRANSPARENT = "backdrop-blur-xl ring-1 ring-neutral-200/80 dark:ring-neutral-800/80 shadow-xs shadow-black/10 bg-white/95";
2
+ const SHELL = 'bg-white/95 dark:bg-neutral-950/95 ' + SHELL_TRANSPARENT;
3
+ const ACCENT_GRADIENT = 'from-indigo-500 via-violet-500 to-blue-500';
4
+ const LOCAL_STYLES = {
5
+ SHELL,
6
+ SHELL_TRANSPARENT,
7
+ SHELL_ROUNDED: 'rounded-2xl ' + SHELL,
8
+ INPUT_SHELL: [
9
+ 'flex h-11 w-full items-center gap-3 rounded-xl',
10
+ 'border border-neutral-200/80 bg-white/90 px-3 text-sm text-neutral-900',
11
+ 'shadow-xs ring-1 ring-black/5 transition',
12
+ 'hover:border-neutral-300 hover:bg-white',
13
+ 'dark:border-neutral-800 dark:bg-neutral-900/80 dark:text-neutral-100 dark:ring-white/5',
14
+ 'hover:dark:border-neutral-600 hover:dark:bg-neutral-900'
15
+ ].join(' '),
16
+ ITEM_BASE: 'flex items-center rounded-xl px-2 py-1.5 select-none transition shadow-none ring-1 ring-transparent border border-transparent',
17
+ ITEM_HOVER: 'hover:bg-neutral-100/60 hover:dark:bg-neutral-800/50 cursor-pointer',
18
+ ITEM_ACTIVE: 'bg-neutral-50/95 dark:bg-neutral-900/85 ring-1 !ring-indigo-400/60 dark:ring-indigo-500/70 border !border-indigo-200/70 dark:border-indigo-600/70',
19
+ GROUP_TITLE: 'px-3 pt-2 pb-1 text-[11px] font-semibold uppercase tracking-wide text-neutral-500 dark:text-neutral-400',
20
+ ACCENT_GRADIENT,
21
+ ACCENT: 'bg-gradient-to-b ' + ACCENT_GRADIENT
22
+ };
23
+ export const STYLES = { ...LOCAL_STYLES };
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@r2digisolutions/ui",
3
- "version": "0.25.5",
3
+ "version": "0.26.1",
4
4
  "private": false,
5
- "packageManager": "bun@1.3.1",
5
+ "packageManager": "bun@1.3.2",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },
@@ -55,35 +55,35 @@
55
55
  "@storybook/addon-interactions": "8.6.14",
56
56
  "@storybook/addon-svelte-csf": "5.0.10",
57
57
  "@storybook/blocks": "8.6.14",
58
- "@storybook/svelte": "10.0.2",
59
- "@storybook/sveltekit": "10.0.2",
58
+ "@storybook/svelte": "10.0.6",
59
+ "@storybook/sveltekit": "10.0.6",
60
60
  "@storybook/test": "8.6.14",
61
61
  "@sveltejs/adapter-static": "3.0.10",
62
62
  "@sveltejs/kit": "2.48.4",
63
63
  "@sveltejs/package": "2.5.4",
64
64
  "@sveltejs/vite-plugin-svelte": "6.2.1",
65
- "@tailwindcss/postcss": "4.1.16",
65
+ "@tailwindcss/postcss": "4.1.17",
66
66
  "@testing-library/svelte": "5.2.8",
67
- "@vitest/browser": "4.0.6",
67
+ "@vitest/browser": "4.0.8",
68
68
  "changeset": "0.2.6",
69
- "eslint": "9.38.0",
69
+ "eslint": "9.39.1",
70
70
  "eslint-config-prettier": "10.1.8",
71
71
  "eslint-plugin-svelte": "3.13.0",
72
- "globals": "16.4.0",
72
+ "globals": "16.5.0",
73
73
  "jsdom": "27.1.0",
74
- "lucide-svelte": "0.552.0",
74
+ "lucide-svelte": "0.553.0",
75
75
  "prettier": "3.6.2",
76
76
  "prettier-plugin-svelte": "3.4.0",
77
77
  "prettier-plugin-tailwindcss": "0.7.1",
78
78
  "publint": "0.3.15",
79
- "storybook": "10.0.2",
80
- "svelte": "5.43.2",
79
+ "storybook": "10.0.6",
80
+ "svelte": "5.43.5",
81
81
  "svelte-check": "4.3.3",
82
- "tailwindcss": "4.1.16",
82
+ "tailwindcss": "4.1.17",
83
83
  "typescript": "5.9.3",
84
- "typescript-eslint": "8.46.2",
85
- "vite": "7.1.12",
86
- "vitest": "4.0.6"
84
+ "typescript-eslint": "8.46.3",
85
+ "vite": "7.2.2",
86
+ "vitest": "4.0.8"
87
87
  },
88
88
  "dependencies": {
89
89
  "@tailwindcss/container-queries": "0.1.1",