@makolabs/ripple 0.0.1-dev.43 → 0.0.1-dev.47

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.
@@ -123,10 +123,21 @@
123
123
  }
124
124
 
125
125
  function handleClickOutside(event: MouseEvent) {
126
- if (labelRef && !labelRef.contains(event.target as Node) && open) {
127
- open = false;
128
- onclose();
126
+ // Check if the click is inside the portal content
127
+ const portalContent = document.querySelector('.ripple-portal .portal-content');
128
+
129
+ // If the click is inside either the label (trigger) or the portal content, don't close
130
+ if (
131
+ (labelRef && labelRef.contains(event.target as Node)) ||
132
+ (portalContent && portalContent.contains(event.target as Node)) ||
133
+ !open
134
+ ) {
135
+ return;
129
136
  }
137
+
138
+ // Otherwise close the dropdown
139
+ open = false;
140
+ onclose();
130
141
  }
131
142
 
132
143
  function handleKeydown(event: KeyboardEvent) {
package/dist/index.d.ts CHANGED
@@ -198,11 +198,8 @@ export type SortState = {
198
198
  export type TableProps<T extends DataRow = any> = {
199
199
  data: T[];
200
200
  columns: TableColumn<T>[];
201
- color?: VariantColors;
202
- size?: VariantSizes;
203
201
  bordered?: boolean;
204
202
  striped?: boolean;
205
- emptyStateText?: string;
206
203
  pageSize?: number;
207
204
  selectable?: boolean;
208
205
  selected?: T[];
@@ -220,6 +217,7 @@ export type TableProps<T extends DataRow = any> = {
220
217
  onselect?: (selected: T[]) => void;
221
218
  rowclass?: (row: T, index: number) => ClassValue;
222
219
  loading?: boolean;
220
+ expandedContent?: Snippet<[T]>;
223
221
  };
224
222
  export type BreadcrumbItem = {
225
223
  label: string;
@@ -2,11 +2,10 @@
2
2
  import { cn } from '../../helper/cls.js';
3
3
  import { table } from './table.js';
4
4
  import type { TableProps, SortDirection, SortState } from '../../index.js';
5
+
5
6
  let {
6
7
  data = [],
7
8
  columns = [],
8
- color = 'default',
9
- size = 'base',
10
9
  bordered = true,
11
10
  striped = false,
12
11
  pageSize = 10,
@@ -25,7 +24,8 @@
25
24
  tdclass: tdClass = '',
26
25
  footerclass: footerClass = '',
27
26
  rowclass = () => '',
28
- loading = false
27
+ loading = false,
28
+ expandedContent
29
29
  }: TableProps<any> = $props();
30
30
 
31
31
  let sortColumn = $state('');
@@ -36,38 +36,36 @@
36
36
  const pagination = $derived(pageSize > 0 && data.length > pageSize);
37
37
 
38
38
  const {
39
- base,
40
- wrapper,
39
+ base: baseClass,
40
+ wrapper: wrapperBaseClass,
41
41
  table: tableBaseClass,
42
- thead,
43
- tbody,
44
- tr,
45
- th,
46
- td,
47
- footer,
48
- pagination: paginationClass,
49
- emptyState,
50
- sortButton,
51
- sortIcon
42
+ thead: theadBaseClass,
43
+ tbody: tbodyBaseClass,
44
+ tr: trBaseClass,
45
+ th: thBaseClass,
46
+ td: tdBaseClass,
47
+ footer: footerBaseClass,
48
+ pagination: paginationBaseClass,
49
+ emptyState: emptyStateBaseClass,
50
+ sortButton: sortButtonBaseClass,
51
+ sortIcon: sortIconBaseClass
52
52
  } = $derived(
53
53
  table({
54
- size,
55
- color,
56
54
  bordered,
57
55
  striped
58
56
  })
59
57
  );
60
58
 
61
- const baseClasses = $derived(cn(base(), classname));
62
- const wrapperClasses = $derived(cn(wrapper(), wrapperClass));
59
+ const baseClasses = $derived(cn(baseClass(), classname));
60
+ const wrapperClasses = $derived(cn(wrapperBaseClass(), wrapperClass));
63
61
  const tableClasses = $derived(cn(tableBaseClass(), tableClass));
64
- const theadClasses = $derived(cn(thead(), theadClass));
65
- const tbodyClasses = $derived(cn(tbody(), tbodyClass));
66
- const trClasses = $derived(cn(tr(), trClass));
67
- const thClasses = $derived(cn(th(), thClass));
68
- const tdClasses = $derived(cn(td(), tdClass));
69
- const footerClasses = $derived(cn(footer(), footerClass));
70
- const emptyStateClasses = $derived(emptyState());
62
+ const theadClasses = $derived(cn(theadBaseClass(), theadClass));
63
+ const tbodyClasses = $derived(cn(tbodyBaseClass(), tbodyClass));
64
+ const trClasses = $derived(cn(trBaseClass(), trClass));
65
+ const thClasses = $derived(cn(thBaseClass(), thClass));
66
+ const tdClasses = $derived(cn(tdBaseClass(), tdClass));
67
+ const footerClasses = $derived(cn(footerBaseClass(), footerClass));
68
+ const emptyStateClasses = $derived(emptyStateBaseClass());
71
69
 
72
70
  // Handle pagination
73
71
  const totalPages = $derived(Math.ceil(data.length / pageSize));
@@ -175,12 +173,12 @@
175
173
  {#if column.sortable}
176
174
  <button
177
175
  type="button"
178
- class={sortButton()}
176
+ class={sortButtonBaseClass()}
179
177
  onclick={() => toggleSort(column.sortKey || column.key)}
180
178
  aria-label={`Sort by ${column.header}`}
181
179
  >
182
180
  {column.header}
183
- <span class={sortIcon()}>
181
+ <span class={sortIconBaseClass()}>
184
182
  {#if sortColumn === (column.sortKey || column.key)}
185
183
  {#if sortDirection === 'asc'}
186
184
  <svg
@@ -315,6 +313,13 @@
315
313
  </td>
316
314
  {/each}
317
315
  </tr>
316
+ {#if expandedContent}
317
+ <tr class="expandedContent-row">
318
+ <td colspan={selectable ? columns.length + 1 : columns.length} class="border-0 p-0">
319
+ {@render expandedContent(row)}
320
+ </td>
321
+ </tr>
322
+ {/if}
318
323
  {/each}
319
324
  {/if}
320
325
  </tbody>
@@ -323,7 +328,7 @@
323
328
 
324
329
  {#if pagination && totalPages > 1}
325
330
  <div class={footerClasses}>
326
- <div class={paginationClass}>
331
+ <div class={paginationBaseClass()}>
327
332
  <div class="flex items-center gap-2">
328
333
  <span class="text-default-500 text-sm">
329
334
  Showing {Math.min((currentPage - 1) * pageSize + 1, data.length)}
@@ -1,5 +1,3 @@
1
- import type { ClassValue } from 'tailwind-variants';
2
- import type { VariantColors, VariantSizes } from '../../index.js';
3
1
  export declare const table: import("tailwind-variants").TVReturnType<{
4
2
  size: {
5
3
  xs: {
@@ -256,29 +254,3 @@ export declare const table: import("tailwind-variants").TVReturnType<{
256
254
  sortButton: string;
257
255
  sortIcon: string;
258
256
  }, undefined, unknown, unknown, undefined>>;
259
- export type TableProps<T extends DataRow = any> = {
260
- data: T[];
261
- columns: TableColumn<T>[];
262
- color?: VariantColors;
263
- size?: VariantSizes;
264
- bordered?: boolean;
265
- striped?: boolean;
266
- emptyStateText?: string;
267
- pageSize?: number;
268
- selectable?: boolean;
269
- selected?: T[];
270
- class?: ClassValue;
271
- wrapperclass?: ClassValue;
272
- tableclass?: ClassValue;
273
- theadclass?: ClassValue;
274
- tbodyclass?: ClassValue;
275
- trclass?: ClassValue;
276
- thclass?: ClassValue;
277
- tdclass?: ClassValue;
278
- footerclass?: ClassValue;
279
- onrowclick?: (row: T, index: number) => void;
280
- onsort?: (sortState: SortState) => void;
281
- onselect?: (selected: T[]) => void;
282
- rowclass?: (row: T, index: number) => ClassValue;
283
- loading?: boolean;
284
- };
@@ -17,15 +17,17 @@
17
17
  if (!ref || !target) return;
18
18
 
19
19
  const { top, left, width, height } = target.getBoundingClientRect();
20
+ const scrollY = window.scrollY || document.documentElement.scrollTop;
21
+ const scrollX = window.scrollX || document.documentElement.scrollLeft;
20
22
 
21
23
  // Set instant positioning without transitions for first render
22
24
  if (!isPositioned) {
23
- ref.style.position = 'fixed';
25
+ ref.style.position = 'absolute';
24
26
  ref.style.width = `${width}px`;
25
- ref.style.height = `${height}px`;
26
- ref.style.top = '0';
27
- ref.style.left = '0';
28
- ref.style.transform = `translate(${left}px, ${top}px)`;
27
+ ref.style.zIndex = '10000'; // Ensure the highest z-index
28
+ ref.style.top = `${height}px`; // Position below the target
29
+ ref.style.left = '0px';
30
+ ref.style.transform = `translate(${left + scrollX}px, ${top + scrollY}px)`;
29
31
  ref.style.visibility = 'hidden'; // Keep hidden until fully positioned
30
32
 
31
33
  // Wait for next frame to ensure positioning is applied before showing
@@ -39,7 +41,7 @@
39
41
  });
40
42
  } else {
41
43
  // For subsequent updates, smoothly transition
42
- ref.style.transform = `translate(${left}px, ${top}px)`;
44
+ ref.style.transform = `translate(${left + scrollX}px, ${top + scrollY}px)`;
43
45
  }
44
46
  }
45
47
 
@@ -56,14 +58,23 @@
56
58
  // Create portal container
57
59
  portal = document.createElement('div');
58
60
  portal.className = 'ripple-portal';
61
+ portal.style.position = 'fixed';
62
+ portal.style.zIndex = '10000'; // Ensure highest z-index
63
+ portal.style.top = '0';
64
+ portal.style.left = '0';
65
+ portal.style.width = '100%';
66
+ portal.style.pointerEvents = 'none'; // Allow clicking through the container but not its children
59
67
 
60
68
  // Default to document.body if no target is provided
61
- const targetElement = target || document.body;
69
+ const targetElement = document.body; // Always append to body for best visibility
62
70
  targetElement.appendChild(portal);
63
71
 
64
72
  // Move the content to the portal
65
73
  portal.appendChild(ref);
66
74
 
75
+ // Allow pointer events on the content
76
+ ref.style.pointerEvents = 'auto';
77
+
67
78
  // Initially hide the content
68
79
  ref.style.opacity = '0';
69
80
 
@@ -95,4 +106,3 @@
95
106
  <div class="portal-content" bind:this={ref}>
96
107
  {@render children()}
97
108
  </div>
98
-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makolabs/ripple",
3
- "version": "0.0.1-dev.43",
3
+ "version": "0.0.1-dev.47",
4
4
  "description": "Simple Svelte 5 powered component library ✨",
5
5
  "repository": {
6
6
  "type": "git",