@placeholderco/placeholder-ui 2.2.1 → 2.2.3
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/dist/layout/Navbar.svelte +122 -4
- package/dist/layout/Navbar.svelte.d.ts +8 -2
- package/dist/layout/NavbarItemView.svelte +7 -2
- package/dist/models/NavbarItem.d.ts +2 -0
- package/dist/ui/Dialog.svelte +94 -84
- package/dist/ui/Link.svelte +5 -1
- package/dist/ui/Link.svelte.d.ts +2 -0
- package/dist/ui/Table.svelte.d.ts +1 -1
- package/package.json +1 -1
|
@@ -12,10 +12,16 @@
|
|
|
12
12
|
import Logo from '../ui/Logo.svelte';
|
|
13
13
|
import type { Snippet } from 'svelte';
|
|
14
14
|
|
|
15
|
-
export type NavbarVariant = 'default' | 'primary';
|
|
15
|
+
export type NavbarVariant = 'default' | 'primary' | 'site';
|
|
16
16
|
|
|
17
17
|
export interface NavbarProps {
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Visual variant.
|
|
20
|
+
* - `primary` uses the primary brand colour as the background across all themes.
|
|
21
|
+
* - `site` is a marketing-site header: logo on the left, links pushed to the right with an
|
|
22
|
+
* accent underline on the `active` item. Below 768px the links collapse and the drawer
|
|
23
|
+
* button (enable with `showDrawerButton`) is shown instead.
|
|
24
|
+
*/
|
|
19
25
|
variant?: NavbarVariant;
|
|
20
26
|
/** App navigation link displayed as a header */
|
|
21
27
|
appNav?: Hyperlink;
|
|
@@ -67,10 +73,16 @@
|
|
|
67
73
|
}: NavbarProps = $props();
|
|
68
74
|
|
|
69
75
|
const isPrimary = $derived(variant === 'primary');
|
|
76
|
+
const isSite = $derived(variant === 'site');
|
|
70
77
|
</script>
|
|
71
78
|
|
|
72
|
-
<header class={isPrimary ? 'primary' : ''}>
|
|
79
|
+
<header class={isPrimary ? 'primary' : isSite ? 'site' : ''}>
|
|
73
80
|
<div class="inner-navbar {className} {inContainer ? 'container' : ''}">
|
|
81
|
+
{#if isSite && !noLogo}
|
|
82
|
+
<span class="site-logo">
|
|
83
|
+
<Logo href={logoHref} />
|
|
84
|
+
</span>
|
|
85
|
+
{/if}
|
|
74
86
|
{@render leftSection?.()}
|
|
75
87
|
{#if showDrawerButton && drawerButtonPosition === 'left'}
|
|
76
88
|
<ActionIcon
|
|
@@ -122,7 +134,7 @@
|
|
|
122
134
|
darkVariant="accent-subtle"
|
|
123
135
|
lightVariant={isPrimary ? 'accent-subtle' : 'primary-subtle'}
|
|
124
136
|
/>
|
|
125
|
-
{#if !viewportState.isMobile && !noLogo}
|
|
137
|
+
{#if !isSite && !viewportState.isMobile && !noLogo}
|
|
126
138
|
{#if logoHref}
|
|
127
139
|
<Logo href={logoHref} fill={isPrimary ? 'white' : undefined} />
|
|
128
140
|
{:else}
|
|
@@ -197,6 +209,112 @@
|
|
|
197
209
|
color: var(--ui-accent);
|
|
198
210
|
}
|
|
199
211
|
|
|
212
|
+
/* Site variant: marketing-site header. Logo on the left, links on the right with a 2px
|
|
213
|
+
underline that lights up (accent) on the active item. */
|
|
214
|
+
header.site .inner-navbar .links-container {
|
|
215
|
+
gap: 1.5rem;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
header.site .inner-navbar .links-container > :global(a),
|
|
219
|
+
header.site
|
|
220
|
+
.inner-navbar
|
|
221
|
+
.links-container
|
|
222
|
+
> :global(.navbar-parent)
|
|
223
|
+
> :global(.navbar-parent-trigger) {
|
|
224
|
+
font-weight: 500;
|
|
225
|
+
padding: 0.35rem 0;
|
|
226
|
+
border-bottom: 2px solid transparent;
|
|
227
|
+
transition:
|
|
228
|
+
color 200ms,
|
|
229
|
+
border-color 200ms;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
header.site .inner-navbar .links-container > :global(a:hover),
|
|
233
|
+
header.site
|
|
234
|
+
.inner-navbar
|
|
235
|
+
.links-container
|
|
236
|
+
> :global(.navbar-parent)
|
|
237
|
+
> :global(.navbar-parent-trigger:hover) {
|
|
238
|
+
color: var(--ui-tertiary-dark);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
:global(.dark) header.site .inner-navbar .links-container > :global(a:hover),
|
|
242
|
+
:global(.dark)
|
|
243
|
+
header.site
|
|
244
|
+
.inner-navbar
|
|
245
|
+
.links-container
|
|
246
|
+
> :global(.navbar-parent)
|
|
247
|
+
> :global(.navbar-parent-trigger:hover) {
|
|
248
|
+
color: var(--ui-accent);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
header.site .inner-navbar .links-container > :global(a.active),
|
|
252
|
+
header.site
|
|
253
|
+
.inner-navbar
|
|
254
|
+
.links-container
|
|
255
|
+
> :global(.navbar-parent)
|
|
256
|
+
> :global(.navbar-parent-trigger.active) {
|
|
257
|
+
border-bottom-color: var(--ui-accent);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/* Brand logo sits on the left and is sized by height so any aspect ratio works */
|
|
261
|
+
header.site .site-logo {
|
|
262
|
+
display: inline-flex;
|
|
263
|
+
align-items: center;
|
|
264
|
+
flex-shrink: 0;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
header.site .site-logo :global(.logo),
|
|
268
|
+
header.site .site-logo :global(.pui-icon) {
|
|
269
|
+
display: inline-flex;
|
|
270
|
+
align-items: center;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
header.site .site-logo :global(.pui-icon svg) {
|
|
274
|
+
height: 40px;
|
|
275
|
+
width: auto;
|
|
276
|
+
display: block;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/* Primary links are right-aligned in the site variant (unless a growing .middle exists) */
|
|
280
|
+
header.site .primary.links-container {
|
|
281
|
+
margin-left: auto;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
header.site .primary.links-container ~ .secondary,
|
|
285
|
+
header.site .primary.links-container ~ .right,
|
|
286
|
+
header.site .primary.links-container ~ :global(.theme-switcher) {
|
|
287
|
+
margin-left: 0;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
@media (max-width: 767px) {
|
|
291
|
+
/* Links collapse into the drawer; the drawer button takes their place */
|
|
292
|
+
header.site .inner-navbar .links-container {
|
|
293
|
+
display: none;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
header.site .site-logo :global(.pui-icon svg) {
|
|
297
|
+
height: 34px;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/* The hidden links containers still count as siblings, so re-apply the auto margin
|
|
301
|
+
to the first visible right-hand element */
|
|
302
|
+
header.site .inner-navbar > .right,
|
|
303
|
+
header.site .inner-navbar > :global(.theme-switcher) {
|
|
304
|
+
margin-left: auto;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
header.site .inner-navbar > .right ~ :global(.theme-switcher) {
|
|
308
|
+
margin-left: 0;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
@media (min-width: 768px) {
|
|
313
|
+
header.site .inner-navbar :global(.drawer-btn) {
|
|
314
|
+
display: none;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
200
318
|
.inner-navbar {
|
|
201
319
|
display: flex;
|
|
202
320
|
align-items: center;
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import type { NavbarItem } from '../models/NavbarItem.js';
|
|
2
2
|
import { type Hyperlink } from '../index.js';
|
|
3
3
|
import type { Snippet } from 'svelte';
|
|
4
|
-
export type NavbarVariant = 'default' | 'primary';
|
|
4
|
+
export type NavbarVariant = 'default' | 'primary' | 'site';
|
|
5
5
|
export interface NavbarProps {
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Visual variant.
|
|
8
|
+
* - `primary` uses the primary brand colour as the background across all themes.
|
|
9
|
+
* - `site` is a marketing-site header: logo on the left, links pushed to the right with an
|
|
10
|
+
* accent underline on the `active` item. Below 768px the links collapse and the drawer
|
|
11
|
+
* button (enable with `showDrawerButton`) is shown instead.
|
|
12
|
+
*/
|
|
7
13
|
variant?: NavbarVariant;
|
|
8
14
|
/** App navigation link displayed as a header */
|
|
9
15
|
appNav?: Hyperlink;
|
|
@@ -25,7 +25,12 @@
|
|
|
25
25
|
{@const Component = item.component}
|
|
26
26
|
<Component {...item.componentProps} />
|
|
27
27
|
{:else if 'href' in item}
|
|
28
|
-
<Link
|
|
28
|
+
<Link
|
|
29
|
+
href={item.href}
|
|
30
|
+
onclick={item.onclick}
|
|
31
|
+
class="navbar-item {item.class ?? ''} {item.active ? 'active' : ''}"
|
|
32
|
+
ariaCurrent={item.active ? 'page' : undefined}
|
|
33
|
+
>
|
|
29
34
|
{#if item.iconSvg}
|
|
30
35
|
<Icon svg={item.iconSvg} size="1.1em" class="navbar-item-icon" />
|
|
31
36
|
{/if}
|
|
@@ -35,7 +40,7 @@
|
|
|
35
40
|
<div class="navbar-parent" use:clickOutside={close}>
|
|
36
41
|
<button
|
|
37
42
|
type="button"
|
|
38
|
-
class="navbar-item navbar-parent-trigger {item.class ?? ''}"
|
|
43
|
+
class="navbar-item navbar-parent-trigger {item.class ?? ''} {item.active ? 'active' : ''}"
|
|
39
44
|
aria-expanded={open}
|
|
40
45
|
aria-haspopup="true"
|
|
41
46
|
onclick={(e) => {
|
|
@@ -3,6 +3,8 @@ type BaseNavbarItem = {
|
|
|
3
3
|
alwaysShow?: boolean;
|
|
4
4
|
showInOnly?: undefined | 'Navbar' | 'Drawer';
|
|
5
5
|
class?: string;
|
|
6
|
+
/** Marks the item as the current page. Adds an `active` class (and `aria-current="page"` on links); the `site` navbar variant underlines it. */
|
|
7
|
+
active?: boolean;
|
|
6
8
|
/** Custom click handler. For link items, call event.preventDefault() to override the default href navigation. */
|
|
7
9
|
onclick?: (event: MouseEvent) => void;
|
|
8
10
|
};
|
package/dist/ui/Dialog.svelte
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
// One lock shared by every instance so a nested dialog closing does not
|
|
3
|
+
// hand the page its scrollbar back while the parent is still open
|
|
4
|
+
let lockCount = 0;
|
|
5
|
+
let savedOverflow = '';
|
|
6
|
+
let savedPaddingRight = '';
|
|
7
|
+
|
|
8
|
+
function lockBodyScroll() {
|
|
9
|
+
if (lockCount++ > 0) return;
|
|
10
|
+
const body = document.body;
|
|
11
|
+
savedOverflow = body.style.overflow;
|
|
12
|
+
savedPaddingRight = body.style.paddingRight;
|
|
13
|
+
// Hiding the scrollbar widens the page and shifts everything sideways,
|
|
14
|
+
// which reads as a flicker behind the backdrop; pad by its width instead
|
|
15
|
+
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
16
|
+
if (scrollbarWidth > 0) {
|
|
17
|
+
const current = parseFloat(getComputedStyle(body).paddingRight) || 0;
|
|
18
|
+
body.style.paddingRight = `${current + scrollbarWidth}px`;
|
|
19
|
+
}
|
|
20
|
+
body.style.overflow = 'hidden';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function unlockBodyScroll() {
|
|
24
|
+
if (--lockCount > 0) return;
|
|
25
|
+
document.body.style.overflow = savedOverflow;
|
|
26
|
+
document.body.style.paddingRight = savedPaddingRight;
|
|
27
|
+
}
|
|
28
|
+
</script>
|
|
29
|
+
|
|
1
30
|
<script lang="ts">
|
|
2
31
|
import Paper from '../display/Paper.svelte';
|
|
3
32
|
import { iconX } from '../icon/index.js';
|
|
@@ -110,10 +139,8 @@
|
|
|
110
139
|
// Lock body scroll while open; effects only run in the browser, so this is SSR-safe
|
|
111
140
|
$effect(() => {
|
|
112
141
|
if (show) {
|
|
113
|
-
|
|
114
|
-
return
|
|
115
|
-
document.body.style.overflow = '';
|
|
116
|
-
};
|
|
142
|
+
lockBodyScroll();
|
|
143
|
+
return unlockBodyScroll;
|
|
117
144
|
}
|
|
118
145
|
});
|
|
119
146
|
|
|
@@ -193,66 +220,21 @@
|
|
|
193
220
|
</dialog>
|
|
194
221
|
|
|
195
222
|
<style>
|
|
196
|
-
/*
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
to {
|
|
205
|
-
opacity: 1;
|
|
206
|
-
transform: translateY(0);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
@keyframes fadeOut {
|
|
210
|
-
from {
|
|
211
|
-
opacity: 1;
|
|
212
|
-
transform: translateY(0);
|
|
213
|
-
}
|
|
214
|
-
to {
|
|
215
|
-
opacity: 0;
|
|
216
|
-
transform: translateY(-0.5rem);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
@keyframes fadeInFull {
|
|
221
|
-
from {
|
|
222
|
-
opacity: 0;
|
|
223
|
-
}
|
|
224
|
-
to {
|
|
225
|
-
opacity: 1;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
@keyframes fadeOutFull {
|
|
229
|
-
from {
|
|
230
|
-
opacity: 1;
|
|
231
|
-
}
|
|
232
|
-
to {
|
|
233
|
-
opacity: 0;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/* Keyframes for the backdrop pseudo-element */
|
|
238
|
-
@keyframes backdropFadeIn {
|
|
239
|
-
from {
|
|
240
|
-
background: hsl(0 0% 0% / 0%);
|
|
241
|
-
}
|
|
242
|
-
to {
|
|
243
|
-
background: hsl(0 0% 0% / 65%);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
@keyframes backdropFadeOut {
|
|
247
|
-
from {
|
|
248
|
-
background: hsl(0 0% 0% / 65%);
|
|
249
|
-
}
|
|
250
|
-
to {
|
|
251
|
-
background: hsl(0 0% 0% / 0%);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
223
|
+
/* Open/close is a transition driven by [open] plus @starting-style, not a
|
|
224
|
+
keyframe animation. Keyframes with a `forwards` fill kept a transform
|
|
225
|
+
applied while open, and the backdrop's static colour could paint for a
|
|
226
|
+
frame before its animation took over, showing as a flash on open.
|
|
227
|
+
Transitions have no fill state: the closed values are the base rule, the
|
|
228
|
+
open values live on [open], and @starting-style supplies the from-values
|
|
229
|
+
for the first frame after display switches on */
|
|
255
230
|
dialog {
|
|
231
|
+
/* Everything that shapes the box lives here, not on [open]: the close
|
|
232
|
+
transition runs after [open] is removed, so rules scoped to it would
|
|
233
|
+
drop out while the dialog is still fading. That includes the browser's
|
|
234
|
+
own :modal positioning, which stops applying the moment close() runs */
|
|
235
|
+
position: fixed;
|
|
236
|
+
inset: 0;
|
|
237
|
+
flex-direction: column;
|
|
256
238
|
color: var(--text-color);
|
|
257
239
|
border: none;
|
|
258
240
|
/* The dialog element itself is focused by showModal(); don't draw a
|
|
@@ -270,22 +252,56 @@
|
|
|
270
252
|
max-height: calc(100vh - 2rem);
|
|
271
253
|
max-height: calc(100dvh - 2rem);
|
|
272
254
|
|
|
273
|
-
|
|
255
|
+
opacity: 0;
|
|
256
|
+
/* Animate transform, not margin: the native dialog centres itself via
|
|
257
|
+
`margin: auto` */
|
|
258
|
+
transform: translateY(-0.5rem);
|
|
274
259
|
transition:
|
|
260
|
+
opacity 0.2s ease,
|
|
261
|
+
transform 0.2s ease,
|
|
275
262
|
display 0.2s allow-discrete,
|
|
276
263
|
overlay 0.2s allow-discrete;
|
|
277
|
-
|
|
278
|
-
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
dialog[open] {
|
|
267
|
+
/* Only when [open] — an unconditional author display would override
|
|
268
|
+
the UA's display: none on closed dialogs and make them visible */
|
|
269
|
+
display: flex;
|
|
270
|
+
opacity: 1;
|
|
271
|
+
/* `none`, not translateY(0): a transform of any value makes the dialog
|
|
272
|
+
the containing block for position: fixed descendants */
|
|
273
|
+
transform: none;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
@starting-style {
|
|
277
|
+
dialog[open] {
|
|
278
|
+
opacity: 0;
|
|
279
|
+
transform: translateY(-0.5rem);
|
|
279
280
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
dialog::backdrop {
|
|
284
|
+
background-color: rgb(0 0 0 / 0);
|
|
285
|
+
transition:
|
|
286
|
+
background-color 0.2s ease,
|
|
287
|
+
display 0.2s allow-discrete,
|
|
288
|
+
overlay 0.2s allow-discrete;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
dialog[open]::backdrop {
|
|
292
|
+
background-color: rgb(0 0 0 / 0.65);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
@starting-style {
|
|
296
|
+
dialog[open]::backdrop {
|
|
297
|
+
background-color: rgb(0 0 0 / 0);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
@media (prefers-reduced-motion: reduce) {
|
|
302
|
+
dialog,
|
|
303
|
+
dialog::backdrop {
|
|
304
|
+
transition-duration: 0.01ms;
|
|
289
305
|
}
|
|
290
306
|
}
|
|
291
307
|
|
|
@@ -389,10 +405,6 @@
|
|
|
389
405
|
background-color: var(--paper-body-bg);
|
|
390
406
|
}
|
|
391
407
|
|
|
392
|
-
dialog::backdrop {
|
|
393
|
-
background-color: #0008;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
408
|
.dialog.md {
|
|
397
409
|
width: 30rem;
|
|
398
410
|
}
|
|
@@ -410,11 +422,9 @@
|
|
|
410
422
|
max-width: 100%;
|
|
411
423
|
max-height: 100%;
|
|
412
424
|
margin-top: auto;
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
animation: fadeInFull 0.2s forwards;
|
|
417
|
-
}
|
|
425
|
+
/* Full-screen fades in place; more specific than the @starting-style
|
|
426
|
+
rule above, so it wins for both the starting and the open state */
|
|
427
|
+
transform: none;
|
|
418
428
|
}
|
|
419
429
|
|
|
420
430
|
.dialog.full,
|
package/dist/ui/Link.svelte
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
children?: Snippet;
|
|
17
17
|
/** Click event handler */
|
|
18
18
|
onclick?: (event: MouseEvent) => void;
|
|
19
|
+
/** Value for the `aria-current` attribute (e.g. `'page'` for the current page) */
|
|
20
|
+
ariaCurrent?: 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | undefined;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
let {
|
|
@@ -24,7 +26,8 @@
|
|
|
24
26
|
target = undefined,
|
|
25
27
|
class: classes = '',
|
|
26
28
|
children,
|
|
27
|
-
onclick
|
|
29
|
+
onclick,
|
|
30
|
+
ariaCurrent = undefined
|
|
28
31
|
}: LinkProps = $props();
|
|
29
32
|
</script>
|
|
30
33
|
|
|
@@ -33,6 +36,7 @@
|
|
|
33
36
|
class={classes}
|
|
34
37
|
href={href?.startsWith('/') ? resolve(href as any) : href}
|
|
35
38
|
{rel}
|
|
39
|
+
aria-current={ariaCurrent}
|
|
36
40
|
onclick={(e) => interceptLinkClick(e, { href, target, onclick })}
|
|
37
41
|
data-sveltekit-preload-data="hover"
|
|
38
42
|
>
|
package/dist/ui/Link.svelte.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export interface LinkProps {
|
|
|
12
12
|
children?: Snippet;
|
|
13
13
|
/** Click event handler */
|
|
14
14
|
onclick?: (event: MouseEvent) => void;
|
|
15
|
+
/** Value for the `aria-current` attribute (e.g. `'page'` for the current page) */
|
|
16
|
+
ariaCurrent?: 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | undefined;
|
|
15
17
|
}
|
|
16
18
|
declare const Link: import("svelte").Component<LinkProps, {}, "">;
|
|
17
19
|
type Link = ReturnType<typeof Link>;
|
|
@@ -84,6 +84,6 @@ export interface TableProps<T = any> {
|
|
|
84
84
|
* Use with `onsort` when the server returns pre-sorted rows. */
|
|
85
85
|
manualSort?: boolean;
|
|
86
86
|
}
|
|
87
|
-
declare const Table: import("svelte").Component<TableProps<any>, {}, "
|
|
87
|
+
declare const Table: import("svelte").Component<TableProps<any>, {}, "page" | "selectedRows" | "expandedKeys" | "sortKey" | "sortDirection">;
|
|
88
88
|
type Table = ReturnType<typeof Table>;
|
|
89
89
|
export default Table;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@placeholderco/placeholder-ui",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.3",
|
|
4
4
|
"description": "A modern, customizable Svelte 5 UI component library with comprehensive theming support. Re-brand it with a single config object.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Placeholderco",
|