@ibobbyts/svelte-ui-utils 0.3.0 → 0.3.4

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.
package/README.md CHANGED
@@ -10,19 +10,19 @@ Install from the public npm registry. No GitHub Packages token is required.
10
10
  With Bun:
11
11
 
12
12
  ```bash
13
- bun add @ibobbyts/svelte-ui-utils@0.3.0
13
+ bun add @ibobbyts/svelte-ui-utils@0.3.1
14
14
  ```
15
15
 
16
16
  Canonical Bun pull address:
17
17
 
18
18
  ```text
19
- @ibobbyts/svelte-ui-utils@0.3.0
19
+ @ibobbyts/svelte-ui-utils@0.3.1
20
20
  ```
21
21
 
22
22
  With npm:
23
23
 
24
24
  ```bash
25
- npm install @ibobbyts/svelte-ui-utils@0.3.0
25
+ npm install @ibobbyts/svelte-ui-utils@0.3.1
26
26
  ```
27
27
 
28
28
  The repository does not track `dist/`; releases and local integration builds run
@@ -707,7 +707,7 @@ consumer project and installs the released npm version without registry-specific
707
707
  tokens:
708
708
 
709
709
  ```bash
710
- bun add @ibobbyts/svelte-ui-utils@0.3.0 svelte
710
+ bun add @ibobbyts/svelte-ui-utils@0.3.1 svelte
711
711
  ```
712
712
 
713
713
  Use it after each release when a Bun-based project will consume the package.
@@ -26,6 +26,7 @@
26
26
  export let minWidth: string | undefined = undefined;
27
27
  export let maxWidth: string | undefined = undefined;
28
28
  export let className: string | undefined = undefined;
29
+ export let portal = false;
29
30
  export let onChange: DropdownChangeHandler | undefined = undefined;
30
31
  export let onTriggerClick: DropdownTriggerClickHandler | undefined = undefined;
31
32
 
@@ -36,8 +37,13 @@
36
37
  let activeValue: DropdownValue = value;
37
38
  let dropdownElement: HTMLSpanElement | undefined;
38
39
  let buttonElement: HTMLButtonElement | undefined;
40
+ let menuElement: HTMLDivElement | undefined;
39
41
  let resolvedPlacement: Exclude<DropdownPlacement, 'auto'> = placement === 'up' ? 'up' : 'down';
40
42
  let viewportPanelMaxHeight: string | undefined = undefined;
43
+ let portalMenuTop = '-9999px';
44
+ let portalMenuLeft: string | undefined = undefined;
45
+ let portalMenuRight: string | undefined = undefined;
46
+ let portalMenuWidth: string | undefined = undefined;
41
47
  let removeOpenViewportListeners: (() => void) | undefined = undefined;
42
48
 
43
49
  $: resolvedOptions = optionGroups === undefined ? options : optionGroups.flatMap((group) => group.options);
@@ -147,6 +153,9 @@
147
153
 
148
154
  function handleFocusout(event: FocusEvent) {
149
155
  const nextTarget = event.relatedTarget;
156
+ if (portal && nextTarget instanceof Node && menuElement?.contains(nextTarget)) {
157
+ return;
158
+ }
150
159
  if (nextTarget instanceof Node && event.currentTarget instanceof Node && event.currentTarget.contains(nextTarget)) {
151
160
  return;
152
161
  }
@@ -204,6 +213,7 @@
204
213
 
205
214
  updateResolvedPlacement(rect);
206
215
  if (!fitViewport) {
216
+ updatePortalPosition(rect);
207
217
  return;
208
218
  }
209
219
 
@@ -212,6 +222,39 @@
212
222
  ? rect.top - viewportMargin - menuGap
213
223
  : window.innerHeight - rect.bottom - viewportMargin - menuGap;
214
224
  viewportPanelMaxHeight = `${Math.max(0, Math.floor(available))}px`;
225
+ updatePortalPosition(rect);
226
+ }
227
+
228
+ function updatePortalPosition(rect: DOMRect) {
229
+ if (!portal || typeof window === 'undefined') {
230
+ return;
231
+ }
232
+
233
+ const menuHeight = menuElement?.getBoundingClientRect().height ?? 0;
234
+ portalMenuTop = `${Math.round(
235
+ resolvedPlacement === 'up' ? rect.top - menuHeight - menuGap : rect.bottom + menuGap
236
+ )}px`;
237
+ if (menuAlign === 'right') {
238
+ portalMenuLeft = undefined;
239
+ portalMenuRight = `${Math.round(window.innerWidth - rect.right)}px`;
240
+ } else {
241
+ portalMenuLeft = `${Math.round(rect.left)}px`;
242
+ portalMenuRight = undefined;
243
+ }
244
+ portalMenuWidth = fitContent ? undefined : `${Math.round(rect.width)}px`;
245
+ }
246
+
247
+ function portalMenu(node: HTMLDivElement, enabled: boolean) {
248
+ if (enabled && typeof document !== 'undefined') {
249
+ document.body.appendChild(node);
250
+ }
251
+ return {
252
+ destroy() {
253
+ if (node.parentNode) {
254
+ node.parentNode.removeChild(node);
255
+ }
256
+ }
257
+ };
215
258
  }
216
259
 
217
260
  function enableOpenViewportTracking() {
@@ -267,18 +310,25 @@
267
310
  on:click={handleTriggerClick}
268
311
  on:keydown={handleKeydown}
269
312
  >
270
- <span>{selectedText}</span>
313
+ <span class="suu-dropdown__label">{selectedText}</span>
271
314
  <span class="suu-dropdown__chevron" aria-hidden="true"></span>
272
315
  </button>
273
316
 
274
317
  {#if open}
275
318
  <div
319
+ bind:this={menuElement}
320
+ use:portalMenu={portal}
276
321
  class="suu-dropdown__menu"
322
+ class:suu-dropdown__menu--portal={portal}
277
323
  class:suu-dropdown__menu--up={resolvedPlacement === 'up'}
278
324
  class:suu-dropdown__menu--down={resolvedPlacement === 'down'}
279
325
  class:suu-dropdown__menu--left={menuAlign === 'left'}
280
326
  class:suu-dropdown__menu--right={menuAlign === 'right'}
281
327
  class:suu-dropdown__menu--fit-content={fitContent}
328
+ style:--suu-dropdown-menu-top={portalMenuTop}
329
+ style:--suu-dropdown-menu-left={portalMenuLeft}
330
+ style:--suu-dropdown-menu-right={portalMenuRight}
331
+ style:--suu-dropdown-menu-width={portalMenuWidth}
282
332
  >
283
333
  <div class="suu-dropdown__panel" role="listbox" aria-label={ariaLabel}>
284
334
  {#if optionGroups === undefined}
@@ -301,7 +351,7 @@
301
351
  }}
302
352
  on:click={() => selectOption(option)}
303
353
  >
304
- {option.label}
354
+ <span class="suu-dropdown__label">{option.label}</span>
305
355
  </button>
306
356
  {/each}
307
357
  {:else}
@@ -329,7 +379,7 @@
329
379
  }}
330
380
  on:click={() => selectOption(option)}
331
381
  >
332
- {option.label}
382
+ <span class="suu-dropdown__label">{option.label}</span>
333
383
  </button>
334
384
  {/each}
335
385
  </div>
@@ -27,6 +27,7 @@ declare const Dropdown: $$__sveltets_2_IsomorphicComponent<{
27
27
  minWidth?: string | undefined;
28
28
  maxWidth?: string | undefined;
29
29
  className?: string | undefined;
30
+ portal?: boolean;
30
31
  onChange?: DropdownChangeHandler | undefined;
31
32
  onTriggerClick?: DropdownTriggerClickHandler | undefined;
32
33
  }, {
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/Dropdown.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACR,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,2BAA2B,EAC3B,aAAa,EACd,MAAM,YAAY,CAAC;AA6RtB,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAC9G,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,QAAQ;SAVuW,MAAM,GAAG,SAAS;YAAU,aAAa;cAAY,cAAc,EAAE;mBAAiB,mBAAmB,EAAE,GAAG,SAAS;gBAAc,MAAM,GAAG,SAAS;gBAAc,iBAAiB;gBAAc,iBAAiB;;;;YAAwG,MAAM,GAAG,SAAS;eAAa,MAAM,GAAG,SAAS;eAAa,MAAM,GAAG,SAAS;gBAAc,MAAM,GAAG,SAAS;eAAa,qBAAqB,GAAG,SAAS;qBAAmB,2BAA2B,GAAG,SAAS;;;kBAU7yB,CAAC;AAC5E,KAAK,QAAQ,GAAG,YAAY,CAAC,OAAO,QAAQ,CAAC,CAAC;AAChD,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"Dropdown.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/Dropdown.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACR,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,2BAA2B,EAC3B,aAAa,EACd,MAAM,YAAY,CAAC;AAwUtB,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAC9G,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,QAAQ;SAVwX,MAAM,GAAG,SAAS;YAAU,aAAa;cAAY,cAAc,EAAE;mBAAiB,mBAAmB,EAAE,GAAG,SAAS;gBAAc,MAAM,GAAG,SAAS;gBAAc,iBAAiB;gBAAc,iBAAiB;;;;YAAwG,MAAM,GAAG,SAAS;eAAa,MAAM,GAAG,SAAS;eAAa,MAAM,GAAG,SAAS;gBAAc,MAAM,GAAG,SAAS;;eAAqC,qBAAqB,GAAG,SAAS;qBAAmB,2BAA2B,GAAG,SAAS;;;kBAUt1B,CAAC;AAC5E,KAAK,QAAQ,GAAG,YAAY,CAAC,OAAO,QAAQ,CAAC,CAAC;AAChD,eAAe,QAAQ,CAAC"}
@@ -76,32 +76,35 @@
76
76
  }
77
77
  </script>
78
78
 
79
- <table class={`suu-sortable-table ${tableClass}`.trim()}>
80
- <thead><tr><th class="suu-sortable-table__drag-column" aria-hidden="true"></th>{@render header()}<th class="suu-sortable-table__remove-column" aria-hidden="true"></th></tr></thead>
81
- <tbody>
82
- {#each items as item, index (getId(item))}
83
- {@const id = getId(item)}
84
- {@const dragLabel = getDragLabel(item, index)}
85
- {@const removeLabel = getRemoveLabel(item, index)}
86
- <tr class={rowClass(item, index)} data-sortable-id={id} ondragover={(event) => dragOver(event, id)} ondrop={(event) => drop(event, id)}>
87
- <td class="suu-sortable-table__drag-cell">
88
- <button type="button" class="suu-sortable-table__drag-handle" disabled={disabled} draggable={!disabled} aria-label={dragLabel} title={dragLabel} ondragstart={(event) => startDrag(event, id)} ondragend={finishDrag}>⋮⋮</button>
89
- {#if dragAccessory}{@render dragAccessory(item, index)}{/if}
90
- </td>
91
- {@render children(item, index)}
92
- <td class="suu-sortable-table__remove-cell">
93
- {#if onRemove}
94
- <button type="button" class="suu-sortable-table__remove" disabled={disabled || (!allowRemoveLast && items.length === 1)} aria-label={removeLabel} title={removeLabel} onclick={() => onRemove?.(item)}>
95
- <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9 3h6l1 2h4v2H4V5h4l1-2Zm-2 6h2v9H7V9Zm4 0h2v9h-2V9Zm4 0h2v9h-2V9ZM6 21V8h12v13H6Z" fill="currentColor"/></svg>
96
- </button>
97
- {/if}
98
- </td>
99
- </tr>
100
- {/each}
101
- </tbody>
102
- </table>
79
+ <div class="suu-sortable-table-wrap">
80
+ <table class={`suu-sortable-table ${tableClass}`.trim()}>
81
+ <thead><tr><th class="suu-sortable-table__drag-column" aria-hidden="true"></th>{@render header()}<th class="suu-sortable-table__remove-column" aria-hidden="true"></th></tr></thead>
82
+ <tbody>
83
+ {#each items as item, index (getId(item))}
84
+ {@const id = getId(item)}
85
+ {@const dragLabel = getDragLabel(item, index)}
86
+ {@const removeLabel = getRemoveLabel(item, index)}
87
+ <tr class={rowClass(item, index)} data-sortable-id={id} ondragover={(event) => dragOver(event, id)} ondrop={(event) => drop(event, id)}>
88
+ <td class="suu-sortable-table__drag-cell">
89
+ <button type="button" class="suu-sortable-table__drag-handle" disabled={disabled} draggable={!disabled} aria-label={dragLabel} title={dragLabel} ondragstart={(event) => startDrag(event, id)} ondragend={finishDrag}>⋮⋮</button>
90
+ {#if dragAccessory}{@render dragAccessory(item, index)}{/if}
91
+ </td>
92
+ {@render children(item, index)}
93
+ <td class="suu-sortable-table__remove-cell">
94
+ {#if onRemove}
95
+ <button type="button" class="suu-sortable-table__remove" disabled={disabled || (!allowRemoveLast && items.length === 1)} aria-label={removeLabel} title={removeLabel} onclick={() => onRemove?.(item)}>
96
+ <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9 3h6l1 2h4v2H4V5h4l1-2Zm-2 6h2v9H7V9Zm4 0h2v9h-2V9Zm4 0h2v9h-2V9ZM6 21V8h12v13H6Z" fill="currentColor"/></svg>
97
+ </button>
98
+ {/if}
99
+ </td>
100
+ </tr>
101
+ {/each}
102
+ </tbody>
103
+ </table>
104
+ </div>
103
105
 
104
106
  <style>
107
+ .suu-sortable-table-wrap { overflow: auto; border: 1px solid var(--suu-color-border, #d1d5db); border-radius: var(--suu-radius, 8px); }
105
108
  .suu-sortable-table { width: 100%; border-collapse: collapse; }
106
109
  .suu-sortable-table__drag-column, .suu-sortable-table__remove-column { width: 38px; }
107
110
  .suu-sortable-table__drag-cell, .suu-sortable-table__remove-cell { width: 38px; padding: 6px; text-align: center; vertical-align: middle; }
@@ -111,6 +114,7 @@
111
114
  .suu-sortable-table__drag-handle:active { cursor: grabbing; }
112
115
  .suu-sortable-table__drag-handle:disabled, .suu-sortable-table__remove:disabled { cursor: default; opacity: .35; }
113
116
  .suu-sortable-table__row { position: relative; border-bottom: 1px solid var(--suu-color-border, #d1d5db); }
117
+ .suu-sortable-table__row:last-child { border-bottom: 0; }
114
118
  .suu-sortable-table :global(td) { border-bottom: 0; }
115
119
  .suu-sortable-table__row--dragging { opacity: .55; }
116
120
  .suu-sortable-table__row--drop-before :global(td) { box-shadow: inset 0 3px 0 var(--suu-color-accent, #2563eb); }
@@ -1 +1 @@
1
- {"version":3,"file":"SortableTable.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/sortable-table/SortableTable.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAChF,iBAAS,QAAQ,CAAC,IAAI,SAAS,iBAAiB;;gBAKpC,IAAI,EAAE;gBACN,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM;mBACnB,OAAO;0BACA,OAAO;qBACZ,MAAM;sBACL,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAAG,IAAI;uBACvD,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM;yBACnC,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM;oBAC1C,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,0BAA0B,KAAK,IAAI;mBAC5D,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI;wBACf,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC/B,OAAO;kBACL,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;;;;;;EA0FoF;AACzH,cAAM,iBAAiB,CAAC,IAAI,SAAS,iBAAiB;IAClD,KAAK,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;IACnD,MAAM,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrD,KAAK,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;IACnD,QAAQ;IACR,OAAO;CACV;AAED,UAAU,qBAAqB;IAC3B,KAAK,IAAI,SAAS,iBAAiB,EAAE,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;KAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3a,CAAC,IAAI,SAAS,iBAAiB,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC9J,YAAY,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;CACjE;AACD,QAAA,MAAM,aAAa,EAAE,qBAAmC,CAAC;AACvC,KAAK,aAAa,CAAC,IAAI,SAAS,iBAAiB,IAAI,YAAY,CAAC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;AAChG,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"SortableTable.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/sortable-table/SortableTable.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAChF,iBAAS,QAAQ,CAAC,IAAI,SAAS,iBAAiB;;gBAKpC,IAAI,EAAE;gBACN,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM;mBACnB,OAAO;0BACA,OAAO;qBACZ,MAAM;sBACL,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAAG,IAAI;uBACvD,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM;yBACnC,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM;oBAC1C,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,0BAA0B,KAAK,IAAI;mBAC5D,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI;wBACf,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC/B,OAAO;kBACL,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;;;;;;EA4FoF;AACzH,cAAM,iBAAiB,CAAC,IAAI,SAAS,iBAAiB;IAClD,KAAK,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;IACnD,MAAM,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrD,KAAK,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;IACnD,QAAQ;IACR,OAAO;CACV;AAED,UAAU,qBAAqB;IAC3B,KAAK,IAAI,SAAS,iBAAiB,EAAE,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;KAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3a,CAAC,IAAI,SAAS,iBAAiB,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAC9J,YAAY,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;CACjE;AACD,QAAA,MAAM,aAAa,EAAE,qBAAmC,CAAC;AACvC,KAAK,aAAa,CAAC,IAAI,SAAS,iBAAiB,IAAI,YAAY,CAAC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;AAChG,eAAe,aAAa,CAAC"}
package/dist/style.css CHANGED
@@ -1128,7 +1128,8 @@
1128
1128
  gap: var(--suu-dropdown-space);
1129
1129
  align-items: center;
1130
1130
  justify-content: space-between;
1131
- height: 42px;
1131
+ min-height: 42px;
1132
+ height: auto;
1132
1133
  padding: 0 var(--suu-dropdown-space);
1133
1134
  border: 1px solid var(--suu-color-border);
1134
1135
  border-radius: var(--suu-radius);
@@ -1137,6 +1138,21 @@
1137
1138
  cursor: pointer;
1138
1139
  font: inherit;
1139
1140
  line-height: 1;
1141
+ text-align: left;
1142
+ }
1143
+
1144
+ .suu-dropdown__label {
1145
+ flex: 1 1 auto;
1146
+ min-width: 0;
1147
+ overflow: hidden;
1148
+ text-overflow: ellipsis;
1149
+ display: -webkit-box;
1150
+ -webkit-box-orient: vertical;
1151
+ -webkit-line-clamp: 2;
1152
+ line-clamp: 2;
1153
+ white-space: normal;
1154
+ overflow-wrap: break-word;
1155
+ line-height: 1.2;
1140
1156
  }
1141
1157
 
1142
1158
  .suu-dropdown--sized .suu-dropdown__button {
@@ -1155,6 +1171,7 @@
1155
1171
  }
1156
1172
 
1157
1173
  .suu-dropdown__chevron {
1174
+ flex: 0 0 auto;
1158
1175
  width: 0.58em;
1159
1176
  height: 0.58em;
1160
1177
  border-right: 2px solid currentcolor;
@@ -1176,17 +1193,26 @@
1176
1193
  box-shadow: 0 18px 42px rgb(15 23 42 / 0.16);
1177
1194
  }
1178
1195
 
1179
- .suu-dropdown__menu--left {
1196
+ .suu-dropdown__menu--portal {
1197
+ position: fixed;
1198
+ top: var(--suu-dropdown-menu-top);
1199
+ right: var(--suu-dropdown-menu-right, auto);
1200
+ left: var(--suu-dropdown-menu-left, auto);
1201
+ width: var(--suu-dropdown-menu-width, max-content);
1202
+ z-index: 1200;
1203
+ }
1204
+
1205
+ .suu-dropdown__menu--left:not(.suu-dropdown__menu--portal) {
1180
1206
  right: auto;
1181
1207
  left: 0;
1182
1208
  }
1183
1209
 
1184
- .suu-dropdown__menu--right {
1210
+ .suu-dropdown__menu--right:not(.suu-dropdown__menu--portal) {
1185
1211
  right: 0;
1186
1212
  left: auto;
1187
1213
  }
1188
1214
 
1189
- .suu-dropdown__menu--up {
1215
+ .suu-dropdown__menu--up:not(.suu-dropdown__menu--portal) {
1190
1216
  top: auto;
1191
1217
  bottom: calc(100% + 6px);
1192
1218
  }
@@ -1205,6 +1231,16 @@
1205
1231
  white-space: nowrap;
1206
1232
  }
1207
1233
 
1234
+ .suu-dropdown__menu--fit-content .suu-dropdown__option .suu-dropdown__label {
1235
+ overflow: visible;
1236
+ text-overflow: clip;
1237
+ display: block;
1238
+ -webkit-line-clamp: unset;
1239
+ line-clamp: unset;
1240
+ white-space: nowrap;
1241
+ overflow-wrap: normal;
1242
+ }
1243
+
1208
1244
  .suu-dropdown__panel {
1209
1245
  max-height: var(--suu-dropdown-panel-max-height, 100vh);
1210
1246
  overflow-y: auto;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ibobbyts/svelte-ui-utils",
3
- "version": "0.3.0",
3
+ "version": "0.3.4",
4
4
  "description": "Reusable Svelte 5 UI utilities for dialogs, toast notifications, dropdown search, and data tables.",
5
5
  "type": "module",
6
6
  "license": "MIT",