@ibobbyts/svelte-ui-utils 0.2.13 → 0.3.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.
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.
|
|
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.
|
|
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.
|
|
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
|
|
@@ -82,7 +82,8 @@ Dropdown menus default to `placement="auto"` and open toward whichever side of
|
|
|
82
82
|
the trigger has more available viewport space. The direction is recalculated
|
|
83
83
|
while the menu is open when the viewport is resized or a scroll container
|
|
84
84
|
moves. Set `placement="up"` or `placement="down"` to force a direction. Use
|
|
85
|
-
`fitViewport={
|
|
85
|
+
`fitViewport={false}` to disable the default panel-height constraint for the
|
|
86
|
+
chosen side.
|
|
86
87
|
|
|
87
88
|
## DropdownSearch
|
|
88
89
|
|
|
@@ -363,7 +364,6 @@ prop is available on all dialog wrapper components.
|
|
|
363
364
|
options={pageSizeOptions}
|
|
364
365
|
ariaLabel="Rows"
|
|
365
366
|
placement="down"
|
|
366
|
-
menuAlign="left"
|
|
367
367
|
onChange={(next) => {
|
|
368
368
|
pageSize = next;
|
|
369
369
|
}}
|
|
@@ -372,19 +372,86 @@ prop is available on all dialog wrapper components.
|
|
|
372
372
|
|
|
373
373
|
`Dropdown` is a controlled select-like component for simple option lists. Use
|
|
374
374
|
`placement="up"` when the menu should open above the trigger, such as bottom
|
|
375
|
-
pagination bars.
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
375
|
+
pagination bars. The expanded menu shares the trigger's left edge by default;
|
|
376
|
+
use `menuAlign="right"` to align their right edges instead. `fitContent` sizes
|
|
377
|
+
the menu to its longest option while keeping the selected edge aligned.
|
|
378
|
+
`DataTable` uses this same component for its page-size picker.
|
|
379
|
+
|
|
380
|
+
The dropdown panel is constrained by default to the space available above or
|
|
381
|
+
below the trigger and remains scrollable when its contents exceed that height.
|
|
382
|
+
Set `fitViewport={false}` to fall back to the stylesheet's viewport-height
|
|
383
|
+
limit (`100vh`).
|
|
384
|
+
|
|
385
|
+
### Allowing a Dropdown menu to extend outside a modal
|
|
386
|
+
|
|
387
|
+
`fitViewport` chooses the opening direction and limits the panel height against
|
|
388
|
+
the browser viewport. It does not portal the menu to `document.body`, so an
|
|
389
|
+
ancestor with `overflow: auto` or `overflow: hidden` can still clip the menu or
|
|
390
|
+
include it in the ancestor's scrollable overflow area.
|
|
391
|
+
|
|
392
|
+
For a modal whose content otherwise fits without scrolling, use a full-width
|
|
393
|
+
positioning boundary around the Dropdown and release the modal overflow only
|
|
394
|
+
while the menu exists:
|
|
395
|
+
|
|
396
|
+
```svelte
|
|
397
|
+
<div class="app-modal">
|
|
398
|
+
<div class="app-modal__body">
|
|
399
|
+
<div class="dropdown-overflow-boundary">
|
|
400
|
+
<Dropdown
|
|
401
|
+
value={selectedValue}
|
|
402
|
+
options={options}
|
|
403
|
+
onChange={(next) => {
|
|
404
|
+
selectedValue = next;
|
|
405
|
+
}}
|
|
406
|
+
/>
|
|
407
|
+
</div>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
```css
|
|
413
|
+
.dropdown-overflow-boundary {
|
|
414
|
+
position: relative;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/* Position the absolute menu against the full-width boundary, not the
|
|
418
|
+
intrinsic-width Dropdown trigger. */
|
|
419
|
+
.dropdown-overflow-boundary .suu-dropdown {
|
|
420
|
+
position: static;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.dropdown-overflow-boundary .suu-dropdown__menu {
|
|
424
|
+
width: max-content;
|
|
425
|
+
min-width: 0;
|
|
426
|
+
max-width: 100%;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.dropdown-overflow-boundary .suu-dropdown__option {
|
|
430
|
+
white-space: normal;
|
|
431
|
+
overflow-wrap: anywhere;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/* :has() scopes the overflow exception to the time the menu is open. */
|
|
435
|
+
.app-modal:has(.dropdown-overflow-boundary .suu-dropdown__menu),
|
|
436
|
+
.app-modal:has(.dropdown-overflow-boundary .suu-dropdown__menu) .app-modal__body {
|
|
437
|
+
overflow: visible;
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
This keeps the trigger at its intrinsic width, lets the menu grow toward its
|
|
442
|
+
aligned edge up to the modal content width, wraps longer options, and allows
|
|
443
|
+
the menu to paint outside the modal. The default `fitViewport={true}` still
|
|
444
|
+
sets the panel's upper or lower limit from the browser viewport and keeps an
|
|
445
|
+
oversized option list scrollable.
|
|
446
|
+
|
|
447
|
+
This CSS pattern intentionally does not implement a portal. If the modal body
|
|
448
|
+
must remain independently scrollable while the menu is open, use a portal or
|
|
449
|
+
floating-layer component instead; releasing `overflow` would change that
|
|
450
|
+
scrolling contract. `:has()` also requires a browser that supports the CSS
|
|
451
|
+
relational pseudo-class.
|
|
452
|
+
|
|
453
|
+
The original flat `options` API remains available. New callers may opt into
|
|
454
|
+
grouped options with `optionGroups`; each group can have an
|
|
388
455
|
optional accessible label and its options keep the same keyboard and disabled
|
|
389
456
|
semantics. `width`, `minWidth`, `maxWidth`, and `className` are optional styling
|
|
390
457
|
hooks. `onTriggerClick` runs before the dropdown toggles, so a nested control
|
|
@@ -640,7 +707,7 @@ consumer project and installs the released npm version without registry-specific
|
|
|
640
707
|
tokens:
|
|
641
708
|
|
|
642
709
|
```bash
|
|
643
|
-
bun add @ibobbyts/svelte-ui-utils@0.
|
|
710
|
+
bun add @ibobbyts/svelte-ui-utils@0.3.1 svelte
|
|
644
711
|
```
|
|
645
712
|
|
|
646
713
|
Use it after each release when a Bun-based project will consume the package.
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
export let optionGroups: DropdownOptionGroup[] | undefined = undefined;
|
|
19
19
|
export let ariaLabel: string | undefined = undefined;
|
|
20
20
|
export let placement: DropdownPlacement = 'auto';
|
|
21
|
-
export let menuAlign: DropdownMenuAlign = '
|
|
22
|
-
export let fitViewport =
|
|
21
|
+
export let menuAlign: DropdownMenuAlign = 'left';
|
|
22
|
+
export let fitViewport = true;
|
|
23
23
|
export let fitContent = false;
|
|
24
24
|
export let disabled = false;
|
|
25
25
|
export let width: string | undefined = undefined;
|
|
@@ -76,32 +76,35 @@
|
|
|
76
76
|
}
|
|
77
77
|
</script>
|
|
78
78
|
|
|
79
|
-
<
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
{
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
<
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
<
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
</
|
|
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;;;;;;
|
|
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/package.json
CHANGED