@signal9/era-ui 4.12.0 → 4.13.0
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/dev/audit/audits/index.d.ts +2 -1
- package/dist/dev/audit/audits/index.js +3 -1
- package/dist/dev/audit/audits/pill-holds-its-ink.d.ts +2 -0
- package/dist/dev/audit/audits/pill-holds-its-ink.js +53 -0
- package/dist/era-ui.css +1 -1
- package/dist/generated-docs/dialog.md +14 -0
- package/dist/generated-docs/llms-full.txt +14 -0
- package/dist/generated-docs/manifest.json +3 -2
- package/dist/os/toast.svelte +5 -2
- package/dist/ui/alert-dialog/alert-dialog-content.svelte +1 -1
- package/dist/ui/badge/badge.svelte +7 -1
- package/dist/ui/badge/badge.svelte.d.ts +1 -1
- package/dist/ui/button-group/button-group.svelte +4 -1
- package/dist/ui/chip/chip.svelte +3 -1
- package/dist/ui/chip/chip.svelte.d.ts +1 -1
- package/dist/ui/command-bar/command-bar.svelte +8 -1
- package/dist/ui/dialog/dialog-content.svelte +25 -3
- package/dist/ui/dialog/dialog-content.svelte.d.ts +12 -1
- package/dist/ui/dialog/dialog-header.svelte +56 -0
- package/dist/ui/dialog/dialog-header.svelte.d.ts +10 -0
- package/dist/ui/dialog/index.d.ts +1 -0
- package/dist/ui/dialog/index.js +1 -0
- package/dist/ui/kv/kv.svelte +4 -1
- package/dist/ui/sheet/index.d.ts +1 -1
- package/dist/ui/sheet/index.js +1 -1
- package/dist/ui/sheet/sheet-content.svelte +44 -9
- package/dist/ui/sheet/sheet-content.svelte.d.ts +49 -13
- package/package.json +1 -1
|
@@ -16,6 +16,7 @@ Composed from sub-components — compose explicitly at the call site:
|
|
|
16
16
|
- `Dialog.Title`
|
|
17
17
|
- `Dialog.Description`
|
|
18
18
|
- `Dialog.Close`
|
|
19
|
+
- `Dialog.Header`
|
|
19
20
|
|
|
20
21
|
## Dialog.Trigger
|
|
21
22
|
|
|
@@ -33,6 +34,11 @@ Inherits all props from `PartProps<Dialog.ContentProps>`.
|
|
|
33
34
|
|
|
34
35
|
| Prop | Type | Default | Notes |
|
|
35
36
|
|------|------|---------|-------|
|
|
37
|
+
| `header?` | `Snippet` | — | A top bar in the pane's grammar — pass `Dialog.Header` (usually holding
|
|
38
|
+
`Dialog.Title`). With it the panel goes sectioned like a Card: the bar
|
|
39
|
+
runs edge to edge, the body keeps the padding, and the radius drops to
|
|
40
|
+
rd-md because the panel's corners are now formed by an md bar holding xxs
|
|
41
|
+
controls — the identical law that sizes the pane's own corners. |
|
|
36
42
|
| `ref?` | `(forwarded)` | `null` | bindable |
|
|
37
43
|
|
|
38
44
|
## Dialog.Overlay
|
|
@@ -68,3 +74,11 @@ Inherits all props from `Omit<ButtonVariants, 'active'>`.
|
|
|
68
74
|
|------|------|---------|-------|
|
|
69
75
|
| `children?` | `Snippet` | — | — |
|
|
70
76
|
| `ref?` | `(forwarded)` | `null` | bindable |
|
|
77
|
+
|
|
78
|
+
## Dialog.Header
|
|
79
|
+
|
|
80
|
+
| Prop | Type | Default | Notes |
|
|
81
|
+
|------|------|---------|-------|
|
|
82
|
+
| `dismissable?` | `boolean` | `true` | Render the trailing × (a `Dialog.Close`). Off for flows that must resolve. |
|
|
83
|
+
| `children?` | `Snippet` | — | — |
|
|
84
|
+
| `class?` | `string` | — | — |
|
|
@@ -2594,6 +2594,7 @@ Composed from sub-components — compose explicitly at the call site:
|
|
|
2594
2594
|
- `Dialog.Title`
|
|
2595
2595
|
- `Dialog.Description`
|
|
2596
2596
|
- `Dialog.Close`
|
|
2597
|
+
- `Dialog.Header`
|
|
2597
2598
|
|
|
2598
2599
|
## Dialog.Trigger
|
|
2599
2600
|
|
|
@@ -2611,6 +2612,11 @@ Inherits all props from `PartProps<Dialog.ContentProps>`.
|
|
|
2611
2612
|
|
|
2612
2613
|
| Prop | Type | Default | Notes |
|
|
2613
2614
|
|------|------|---------|-------|
|
|
2615
|
+
| `header?` | `Snippet` | — | A top bar in the pane's grammar — pass `Dialog.Header` (usually holding
|
|
2616
|
+
`Dialog.Title`). With it the panel goes sectioned like a Card: the bar
|
|
2617
|
+
runs edge to edge, the body keeps the padding, and the radius drops to
|
|
2618
|
+
rd-md because the panel's corners are now formed by an md bar holding xxs
|
|
2619
|
+
controls — the identical law that sizes the pane's own corners. |
|
|
2614
2620
|
| `ref?` | `(forwarded)` | `null` | bindable |
|
|
2615
2621
|
|
|
2616
2622
|
## Dialog.Overlay
|
|
@@ -2647,6 +2653,14 @@ Inherits all props from `Omit<ButtonVariants, 'active'>`.
|
|
|
2647
2653
|
| `children?` | `Snippet` | — | — |
|
|
2648
2654
|
| `ref?` | `(forwarded)` | `null` | bindable |
|
|
2649
2655
|
|
|
2656
|
+
## Dialog.Header
|
|
2657
|
+
|
|
2658
|
+
| Prop | Type | Default | Notes |
|
|
2659
|
+
|------|------|---------|-------|
|
|
2660
|
+
| `dismissable?` | `boolean` | `true` | Render the trailing × (a `Dialog.Close`). Off for flows that must resolve. |
|
|
2661
|
+
| `children?` | `Snippet` | — | — |
|
|
2662
|
+
| `class?` | `string` | — | — |
|
|
2663
|
+
|
|
2650
2664
|
<!-- end: dialog -->
|
|
2651
2665
|
|
|
2652
2666
|
<!-- begin: dropdown-menu -->
|
|
@@ -572,7 +572,7 @@
|
|
|
572
572
|
"slug": "dialog",
|
|
573
573
|
"title": "Dialog",
|
|
574
574
|
"summary": "A modal window for content or user input.",
|
|
575
|
-
"tokenEstimate":
|
|
575
|
+
"tokenEstimate": 576,
|
|
576
576
|
"sections": [
|
|
577
577
|
"Import",
|
|
578
578
|
"Dialog.Trigger",
|
|
@@ -580,7 +580,8 @@
|
|
|
580
580
|
"Dialog.Overlay",
|
|
581
581
|
"Dialog.Title",
|
|
582
582
|
"Dialog.Description",
|
|
583
|
-
"Dialog.Close"
|
|
583
|
+
"Dialog.Close",
|
|
584
|
+
"Dialog.Header"
|
|
584
585
|
],
|
|
585
586
|
"file": "dialog.md"
|
|
586
587
|
},
|
package/dist/os/toast.svelte
CHANGED
|
@@ -31,14 +31,17 @@
|
|
|
31
31
|
<div class="min-w-0 flex-1">
|
|
32
32
|
<div class="flex items-start gap-(--era-gap)">
|
|
33
33
|
<p class="min-w-0 flex-1 truncate text-body text-bright">{n.title}</p>
|
|
34
|
+
<!-- The dismiss family's ×: xxs tier, whose default glyph is the 12px
|
|
35
|
+
dismiss ink (the size class that sat on the <X> lost to the Button
|
|
36
|
+
variant's [&_svg] selector and never applied). -->
|
|
34
37
|
<Button
|
|
35
38
|
icon
|
|
36
|
-
size="
|
|
39
|
+
size="xxs"
|
|
37
40
|
aria-label="Dismiss"
|
|
38
41
|
class="-mt-1 -mr-1 shrink-0"
|
|
39
42
|
onclick={() => notif.dismiss(n.id)}
|
|
40
43
|
>
|
|
41
|
-
<X
|
|
44
|
+
<X />
|
|
42
45
|
</Button>
|
|
43
46
|
</div>
|
|
44
47
|
{#if n.body}<p class="mt-0.5 text-body break-words text-muted">{n.body}</p>{/if}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<AlertDialog.Content
|
|
16
16
|
bind:ref
|
|
17
17
|
class={cn(
|
|
18
|
-
'fixed top-1/2 left-1/2 z-50 flex w-full max-w-md -translate-x-1/2 -translate-y-1/2 flex-col gap-(--era-gap) rounded-(--era-rd-lg) bg-(--era-surface-bg) p-(--era-pad-md) shadow-(--era-shadow-lg) glass-blur',
|
|
18
|
+
'fixed top-1/2 left-1/2 z-50 flex w-full max-w-md -translate-x-1/2 -translate-y-1/2 flex-col gap-(--era-gap) rounded-(--era-rd-lg) border border-divider bg-(--era-surface-bg) p-(--era-pad-md) shadow-(--era-shadow-lg) glass-blur',
|
|
19
19
|
className
|
|
20
20
|
)}
|
|
21
21
|
{...restProps}
|
|
@@ -5,7 +5,13 @@
|
|
|
5
5
|
// min-w matches height (design rule #5): a single glyph — a count, a
|
|
6
6
|
// keycap letter — renders as a perfect square/circle instead of a
|
|
7
7
|
// skinny pill; wider content is unaffected.
|
|
8
|
-
|
|
8
|
+
//
|
|
9
|
+
// shrink-0 + whitespace-nowrap: a pill IS its text's size — it has no slack
|
|
10
|
+
// to give up, so letting a flex ancestor squeeze it just slid the background
|
|
11
|
+
// out from under the ink and the label bled past the fill. A pill that must
|
|
12
|
+
// fit a tight row does it the Tool.Chip way: the BOX holds and an inner
|
|
13
|
+
// min-w-0 span truncates. Enforced at runtime by layout/pill-holds-its-ink.
|
|
14
|
+
base: 'inline-flex h-(--era-h-xxs) min-w-(--era-h-xxs) shrink-0 items-center justify-center gap-(--era-gap) rounded-(--era-rd-xxs) px-(--era-pill-xxs) font-mono text-body leading-none whitespace-nowrap has-[svg]:gap-(--era-inset-xxs) era-text-trim',
|
|
9
15
|
variants: {
|
|
10
16
|
tone: {
|
|
11
17
|
default: 'bg-hover text-fg',
|
|
@@ -6,7 +6,7 @@ export declare const badgeVariants: import("tailwind-variants").TVReturnType<{
|
|
|
6
6
|
success: "bg-success text-success-fg";
|
|
7
7
|
warning: "bg-warning text-warning-fg";
|
|
8
8
|
};
|
|
9
|
-
}, undefined, "inline-flex h-(--era-h-xxs) min-w-(--era-h-xxs) items-center justify-center gap-(--era-gap) rounded-(--era-rd-xxs) px-(--era-pill-xxs) font-mono text-body leading-none has-[svg]:gap-(--era-inset-xxs) era-text-trim", {
|
|
9
|
+
}, undefined, "inline-flex h-(--era-h-xxs) min-w-(--era-h-xxs) shrink-0 items-center justify-center gap-(--era-gap) rounded-(--era-rd-xxs) px-(--era-pill-xxs) font-mono text-body leading-none whitespace-nowrap has-[svg]:gap-(--era-inset-xxs) era-text-trim", {
|
|
10
10
|
tone: {
|
|
11
11
|
default: "bg-hover text-fg";
|
|
12
12
|
accent: "bg-primary text-primary-fg";
|
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
<div
|
|
20
20
|
bind:this={ref}
|
|
21
21
|
class={cn(
|
|
22
|
-
|
|
22
|
+
// shrink-0: a segmented control is its buttons' width — Badge/Chip's law
|
|
23
|
+
// one tier up. Squeezed, its rounded fill slid out from under the end
|
|
24
|
+
// buttons (measured 4px at touch on the board).
|
|
25
|
+
'flex shrink-0 gap-(--era-xs-inset-sm)',
|
|
23
26
|
orientation === 'vertical'
|
|
24
27
|
? 'flex-col items-stretch p-(--era-xs-inset-sm) [&>*]:justify-start'
|
|
25
28
|
: 'items-center',
|
package/dist/ui/chip/chip.svelte
CHANGED
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
// select trigger): h-xxs = sp + 10, leaving the 3/5/7
|
|
12
12
|
// concentric gap so it sits evenly inset, not cramped.
|
|
13
13
|
export const chipVariants = tv({
|
|
14
|
-
|
|
14
|
+
// shrink-0 + nowrap for the same reason Badge carries them: the pill is
|
|
15
|
+
// already exactly its text's size, so any squeeze puts ink outside the fill.
|
|
16
|
+
base: 'inline-flex shrink-0 items-center bg-hover font-mono text-body leading-none whitespace-nowrap text-fg shadow-(--era-shadow) era-text-trim',
|
|
15
17
|
variants: {
|
|
16
18
|
size: {
|
|
17
19
|
sm: 'h-(--era-h-sm) min-w-(--era-h-sm) rounded-(--era-rd-sm) pl-(--era-pill-sm)',
|
|
@@ -7,7 +7,7 @@ export declare const chipVariants: import("tailwind-variants").TVReturnType<{
|
|
|
7
7
|
true: "";
|
|
8
8
|
false: "";
|
|
9
9
|
};
|
|
10
|
-
}, undefined, "inline-flex items-center bg-hover font-mono text-body leading-none text-fg shadow-(--era-shadow) era-text-trim", {
|
|
10
|
+
}, undefined, "inline-flex shrink-0 items-center bg-hover font-mono text-body leading-none whitespace-nowrap text-fg shadow-(--era-shadow) era-text-trim", {
|
|
11
11
|
size: {
|
|
12
12
|
sm: "h-(--era-h-sm) min-w-(--era-h-sm) rounded-(--era-rd-sm) pl-(--era-pill-sm)";
|
|
13
13
|
xxs: "h-(--era-h-xxs) min-w-(--era-h-xxs) rounded-(--era-rd-xxs) pl-(--era-pill-xxs)";
|
|
@@ -207,7 +207,14 @@
|
|
|
207
207
|
itself by the font's own metrics. The input and the ghost mirror BOTH inherit
|
|
208
208
|
it, so they centre by the identical mechanism — no native-input-centering vs
|
|
209
209
|
flex-centering divergence that reads as the ghost sitting a hair high. -->
|
|
210
|
-
|
|
210
|
+
<!-- overflow-hidden: the transparent <input> clips its text natively, but the
|
|
211
|
+
MIRROR that actually paints it did not — so in a host narrower than the
|
|
212
|
+
prompt line (placeholder included), the text bled past the bar's rounded
|
|
213
|
+
end where any real input would clip. Safe with the line-height centring:
|
|
214
|
+
the box is the bar's full h-md, well above the ink (clipped-glyphs' law). -->
|
|
215
|
+
<div
|
|
216
|
+
class="relative h-full min-w-0 flex-1 overflow-hidden text-body leading-(--era-h-md) text-bright"
|
|
217
|
+
>
|
|
211
218
|
<!-- Transparent input: it owns editing and the caret only, so the visible text
|
|
212
219
|
can come entirely from the mirror below (see it for why). Everything but
|
|
213
220
|
the see-through fill is inherited: font + line-height from the container,
|
|
@@ -1,25 +1,47 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
2
3
|
import { Dialog } from 'bits-ui';
|
|
3
4
|
import { cn, type PartProps } from '../../utils/index.js';
|
|
4
5
|
|
|
5
6
|
let {
|
|
6
7
|
ref = $bindable(null),
|
|
7
8
|
children,
|
|
9
|
+
header,
|
|
8
10
|
class: className,
|
|
9
11
|
...restProps
|
|
10
|
-
}: PartProps<Dialog.ContentProps>
|
|
12
|
+
}: PartProps<Dialog.ContentProps> & {
|
|
13
|
+
/**
|
|
14
|
+
* A top bar in the pane's grammar — pass `Dialog.Header` (usually holding
|
|
15
|
+
* `Dialog.Title`). With it the panel goes sectioned like a Card: the bar
|
|
16
|
+
* runs edge to edge, the body keeps the padding, and the radius drops to
|
|
17
|
+
* rd-md because the panel's corners are now formed by an md bar holding xxs
|
|
18
|
+
* controls — the identical law that sizes the pane's own corners.
|
|
19
|
+
*/
|
|
20
|
+
header?: Snippet;
|
|
21
|
+
} = $props();
|
|
11
22
|
</script>
|
|
12
23
|
|
|
13
24
|
<Dialog.Portal>
|
|
14
25
|
<Dialog.Overlay class="fixed inset-0 z-50 bg-(--era-overlay-bg)" />
|
|
26
|
+
<!-- border-divider: the pane's hairline-edge law. A floating panel must be
|
|
27
|
+
separable from what's behind it, and on the flat surface shadow-lg
|
|
28
|
+
collapses to none — without the hairline the whole edge was a tone step. -->
|
|
15
29
|
<Dialog.Content
|
|
16
30
|
bind:ref
|
|
17
31
|
class={cn(
|
|
18
|
-
'fixed top-1/2 left-1/2 z-50 flex w-full max-w-md -translate-x-1/2 -translate-y-1/2 flex-col
|
|
32
|
+
'fixed top-1/2 left-1/2 z-50 flex w-full max-w-md -translate-x-1/2 -translate-y-1/2 flex-col border border-divider bg-(--era-surface-bg) shadow-(--era-shadow-lg) glass-blur',
|
|
33
|
+
header ? 'rounded-(--era-rd-md)' : 'gap-(--era-gap) rounded-(--era-rd-lg) p-(--era-pad-md)',
|
|
19
34
|
className
|
|
20
35
|
)}
|
|
21
36
|
{...restProps}
|
|
22
37
|
>
|
|
23
|
-
{
|
|
38
|
+
{#if header}
|
|
39
|
+
{@render header()}
|
|
40
|
+
<div class="flex min-h-0 flex-col gap-(--era-gap) p-(--era-pad-md)">
|
|
41
|
+
{@render children?.()}
|
|
42
|
+
</div>
|
|
43
|
+
{:else}
|
|
44
|
+
{@render children?.()}
|
|
45
|
+
{/if}
|
|
24
46
|
</Dialog.Content>
|
|
25
47
|
</Dialog.Portal>
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
1
2
|
import { Dialog } from 'bits-ui';
|
|
2
3
|
import { type PartProps } from '../../utils/index.js';
|
|
3
|
-
|
|
4
|
+
type $$ComponentProps = PartProps<Dialog.ContentProps> & {
|
|
5
|
+
/**
|
|
6
|
+
* A top bar in the pane's grammar — pass `Dialog.Header` (usually holding
|
|
7
|
+
* `Dialog.Title`). With it the panel goes sectioned like a Card: the bar
|
|
8
|
+
* runs edge to edge, the body keeps the padding, and the radius drops to
|
|
9
|
+
* rd-md because the panel's corners are now formed by an md bar holding xxs
|
|
10
|
+
* controls — the identical law that sizes the pane's own corners.
|
|
11
|
+
*/
|
|
12
|
+
header?: Snippet;
|
|
13
|
+
};
|
|
14
|
+
declare const DialogContent: import("svelte").Component<$$ComponentProps, {}, "ref">;
|
|
4
15
|
type DialogContent = ReturnType<typeof DialogContent>;
|
|
5
16
|
export default DialogContent;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import { Dialog } from 'bits-ui';
|
|
4
|
+
import X from '@lucide/svelte/icons/x';
|
|
5
|
+
import { Bar } from '../bar';
|
|
6
|
+
import { Button } from '../button';
|
|
7
|
+
import { cn } from '../../utils/index.js';
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
dismissable = true,
|
|
11
|
+
children,
|
|
12
|
+
class: className
|
|
13
|
+
}: {
|
|
14
|
+
/** Render the trailing × (a `Dialog.Close`). Off for flows that must resolve. */
|
|
15
|
+
dismissable?: boolean;
|
|
16
|
+
children?: Snippet;
|
|
17
|
+
class?: string;
|
|
18
|
+
} = $props();
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<!-- The pane handle's chrome, verbatim, for an overlay's top bar — one grammar
|
|
22
|
+
for every floating panel's header so a dialog and a pane read as the same
|
|
23
|
+
kind of surface:
|
|
24
|
+
|
|
25
|
+
· an md bar holding xxs controls, walls and gap --era-xxs-inset-md
|
|
26
|
+
· the divider drawn OUTSIDE the box (an inset one eats a pixel of every
|
|
27
|
+
child's bottom gap — see Pane.Handle)
|
|
28
|
+
· the leading side at --era-inset-md: a title has no corner to nest, so
|
|
29
|
+
it takes the text inset, the same asymmetry the pane and the
|
|
30
|
+
Conversations row document
|
|
31
|
+
· the × is the dismiss family's: an xxs Button whose tier default IS the
|
|
32
|
+
12px ink, destructive like Pane.Close
|
|
33
|
+
|
|
34
|
+
Rendered flush by Dialog.Content / Sheet.Content when passed as their
|
|
35
|
+
`header` snippet, so the bar spans the panel edge to edge and the panel's
|
|
36
|
+
radius follows this corner region (rd-md — the same law that sizes the
|
|
37
|
+
pane's own corners). -->
|
|
38
|
+
<Bar
|
|
39
|
+
size="md"
|
|
40
|
+
content="xxs"
|
|
41
|
+
class={cn(
|
|
42
|
+
'shrink-0 rounded-t-none rounded-b-(--era-rd-md) pl-(--era-inset-md) [box-shadow:0_1px_0_var(--color-divider-faded)] select-none',
|
|
43
|
+
className
|
|
44
|
+
)}
|
|
45
|
+
>
|
|
46
|
+
{@render children?.()}
|
|
47
|
+
{#if dismissable}
|
|
48
|
+
<Dialog.Close>
|
|
49
|
+
{#snippet child({ props })}
|
|
50
|
+
<Button icon size="xxs" tone="destructive" aria-label="Close" class="ml-auto" {...props}>
|
|
51
|
+
<X />
|
|
52
|
+
</Button>
|
|
53
|
+
{/snippet}
|
|
54
|
+
</Dialog.Close>
|
|
55
|
+
{/if}
|
|
56
|
+
</Bar>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
/** Render the trailing × (a `Dialog.Close`). Off for flows that must resolve. */
|
|
4
|
+
dismissable?: boolean;
|
|
5
|
+
children?: Snippet;
|
|
6
|
+
class?: string;
|
|
7
|
+
};
|
|
8
|
+
declare const DialogHeader: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
9
|
+
type DialogHeader = ReturnType<typeof DialogHeader>;
|
|
10
|
+
export default DialogHeader;
|
|
@@ -7,3 +7,4 @@ export { default as Overlay } from './dialog-overlay.svelte';
|
|
|
7
7
|
export { default as Title } from './dialog-title.svelte';
|
|
8
8
|
export { default as Description } from './dialog-description.svelte';
|
|
9
9
|
export { default as Close } from './dialog-close.svelte';
|
|
10
|
+
export { default as Header } from './dialog-header.svelte';
|
package/dist/ui/dialog/index.js
CHANGED
|
@@ -7,3 +7,4 @@ export { default as Overlay } from './dialog-overlay.svelte';
|
|
|
7
7
|
export { default as Title } from './dialog-title.svelte';
|
|
8
8
|
export { default as Description } from './dialog-description.svelte';
|
|
9
9
|
export { default as Close } from './dialog-close.svelte';
|
|
10
|
+
export { default as Header } from './dialog-header.svelte';
|
package/dist/ui/kv/kv.svelte
CHANGED
|
@@ -21,7 +21,10 @@
|
|
|
21
21
|
<span
|
|
22
22
|
bind:this={ref}
|
|
23
23
|
class={cn(
|
|
24
|
-
|
|
24
|
+
// shrink-0 + nowrap like Badge/Chip: the overflow-hidden here is for the
|
|
25
|
+
// key cell's squared corners, not a licence to crush — squeezed, this pill
|
|
26
|
+
// clipped its value instead of bleeding it, which is quieter but no truer.
|
|
27
|
+
'inline-flex h-(--era-h-xxs) shrink-0 items-center overflow-hidden rounded-(--era-rd-xxs) bg-hover font-mono text-body era-text-trim leading-none whitespace-nowrap shadow-(--era-shadow)',
|
|
25
28
|
className
|
|
26
29
|
)}
|
|
27
30
|
{...restProps}
|
package/dist/ui/sheet/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { Root, Portal, Trigger, Title, Description, Close } from '../dialog/index.js';
|
|
1
|
+
export { Root, Portal, Trigger, Title, Description, Close, Header } from '../dialog/index.js';
|
|
2
2
|
export { default as Content, sheetVariants } from './sheet-content.svelte';
|
package/dist/ui/sheet/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Sheet is a Dialog anchored to a screen edge. Root/Trigger/Title/Description/
|
|
2
2
|
// Close are the Dialog wrappers verbatim (same behavior); only Content differs
|
|
3
3
|
// (edge-positioned, with a `side` prop).
|
|
4
|
-
export { Root, Portal, Trigger, Title, Description, Close } from '../dialog/index.js';
|
|
4
|
+
export { Root, Portal, Trigger, Title, Description, Close, Header } from '../dialog/index.js';
|
|
5
5
|
export { default as Content, sheetVariants } from './sheet-content.svelte';
|
|
@@ -4,38 +4,73 @@
|
|
|
4
4
|
// A Sheet is a Dialog pinned to a screen edge — the idiomatic mobile drawer
|
|
5
5
|
// (bottom for controls, left/right for navigation). Positioning + which
|
|
6
6
|
// corners round follow the `side`; everything else is the dialog surface.
|
|
7
|
+
// border-divider on every side: the pane's hairline-edge law — on flat,
|
|
8
|
+
// shadow-lg collapses to none and the sheet's edge was a bare tone step.
|
|
7
9
|
export const sheetVariants = tv({
|
|
8
|
-
base: 'fixed z-50 flex flex-col
|
|
10
|
+
base: 'fixed z-50 flex flex-col border border-divider bg-(--era-surface-bg) shadow-(--era-shadow-lg) glass-blur',
|
|
9
11
|
variants: {
|
|
10
12
|
side: {
|
|
11
|
-
top: 'inset-x-0 top-0 max-h-[85dvh]
|
|
12
|
-
bottom: 'inset-x-0 bottom-0 max-h-[85dvh]
|
|
13
|
-
left: 'inset-y-0 left-0 w-[min(20rem,85vw)]
|
|
14
|
-
right: 'inset-y-0 right-0 w-[min(20rem,85vw)]
|
|
15
|
-
}
|
|
13
|
+
top: 'inset-x-0 top-0 max-h-[85dvh]',
|
|
14
|
+
bottom: 'inset-x-0 bottom-0 max-h-[85dvh]',
|
|
15
|
+
left: 'inset-y-0 left-0 w-[min(20rem,85vw)]',
|
|
16
|
+
right: 'inset-y-0 right-0 w-[min(20rem,85vw)]'
|
|
17
|
+
},
|
|
18
|
+
/**
|
|
19
|
+
* With a header the sheet is sectioned (the bar flush, the BODY scrolls
|
|
20
|
+
* — scrolling the root would carry the bar away with the content) and
|
|
21
|
+
* its detached corners drop to rd-md: they are formed by an md bar
|
|
22
|
+
* holding xxs controls, the pane's own corner law. Without one, the
|
|
23
|
+
* padded rd-lg surface is unchanged.
|
|
24
|
+
*/
|
|
25
|
+
header: { true: '', false: 'gap-(--era-gap) overflow-y-auto p-(--era-pad-md)' }
|
|
16
26
|
},
|
|
17
|
-
|
|
27
|
+
compoundVariants: [
|
|
28
|
+
{ side: 'top', header: false, class: 'rounded-b-(--era-rd-lg)' },
|
|
29
|
+
{ side: 'bottom', header: false, class: 'rounded-t-(--era-rd-lg)' },
|
|
30
|
+
{ side: 'left', header: false, class: 'rounded-r-(--era-rd-lg)' },
|
|
31
|
+
{ side: 'right', header: false, class: 'rounded-l-(--era-rd-lg)' },
|
|
32
|
+
{ side: 'top', header: true, class: 'rounded-b-(--era-rd-md)' },
|
|
33
|
+
{ side: 'bottom', header: true, class: 'rounded-t-(--era-rd-md)' },
|
|
34
|
+
{ side: 'left', header: true, class: 'rounded-r-(--era-rd-md)' },
|
|
35
|
+
{ side: 'right', header: true, class: 'rounded-l-(--era-rd-md)' }
|
|
36
|
+
],
|
|
37
|
+
defaultVariants: { side: 'bottom', header: false }
|
|
18
38
|
});
|
|
19
39
|
</script>
|
|
20
40
|
|
|
21
41
|
<script lang="ts">
|
|
42
|
+
import type { Snippet } from 'svelte';
|
|
22
43
|
import { Dialog } from 'bits-ui';
|
|
23
44
|
|
|
24
45
|
let {
|
|
25
46
|
ref = $bindable(null),
|
|
26
47
|
side = 'bottom',
|
|
27
48
|
children,
|
|
49
|
+
header,
|
|
28
50
|
class: className,
|
|
29
51
|
...restProps
|
|
30
52
|
}: PartProps<Dialog.ContentProps> & {
|
|
31
53
|
/** Screen edge the sheet is anchored to. */
|
|
32
54
|
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
55
|
+
/** A top bar in the pane's grammar — pass `Sheet.Header` holding `Sheet.Title`. */
|
|
56
|
+
header?: Snippet;
|
|
33
57
|
} = $props();
|
|
34
58
|
</script>
|
|
35
59
|
|
|
36
60
|
<Dialog.Portal>
|
|
37
61
|
<Dialog.Overlay class="fixed inset-0 z-50 bg-(--era-overlay-bg)" />
|
|
38
|
-
<Dialog.Content
|
|
39
|
-
|
|
62
|
+
<Dialog.Content
|
|
63
|
+
bind:ref
|
|
64
|
+
class={cn(sheetVariants({ side, header: header != null }), className)}
|
|
65
|
+
{...restProps}
|
|
66
|
+
>
|
|
67
|
+
{#if header}
|
|
68
|
+
{@render header()}
|
|
69
|
+
<div class="flex min-h-0 flex-1 flex-col gap-(--era-gap) overflow-y-auto p-(--era-pad-md)">
|
|
70
|
+
{@render children?.()}
|
|
71
|
+
</div>
|
|
72
|
+
{:else}
|
|
73
|
+
{@render children?.()}
|
|
74
|
+
{/if}
|
|
40
75
|
</Dialog.Content>
|
|
41
76
|
</Dialog.Portal>
|
|
@@ -1,30 +1,66 @@
|
|
|
1
1
|
import { type PartProps } from '../../utils/index.js';
|
|
2
2
|
export declare const sheetVariants: import("tailwind-variants").TVReturnType<{
|
|
3
3
|
side: {
|
|
4
|
-
top: "inset-x-0 top-0 max-h-[85dvh]
|
|
5
|
-
bottom: "inset-x-0 bottom-0 max-h-[85dvh]
|
|
6
|
-
left: "inset-y-0 left-0 w-[min(20rem,85vw)]
|
|
7
|
-
right: "inset-y-0 right-0 w-[min(20rem,85vw)]
|
|
4
|
+
top: "inset-x-0 top-0 max-h-[85dvh]";
|
|
5
|
+
bottom: "inset-x-0 bottom-0 max-h-[85dvh]";
|
|
6
|
+
left: "inset-y-0 left-0 w-[min(20rem,85vw)]";
|
|
7
|
+
right: "inset-y-0 right-0 w-[min(20rem,85vw)]";
|
|
8
8
|
};
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* With a header the sheet is sectioned (the bar flush, the BODY scrolls
|
|
11
|
+
* — scrolling the root would carry the bar away with the content) and
|
|
12
|
+
* its detached corners drop to rd-md: they are formed by an md bar
|
|
13
|
+
* holding xxs controls, the pane's own corner law. Without one, the
|
|
14
|
+
* padded rd-lg surface is unchanged.
|
|
15
|
+
*/
|
|
16
|
+
header: {
|
|
17
|
+
true: "";
|
|
18
|
+
false: "gap-(--era-gap) overflow-y-auto p-(--era-pad-md)";
|
|
19
|
+
};
|
|
20
|
+
}, undefined, "fixed z-50 flex flex-col border border-divider bg-(--era-surface-bg) shadow-(--era-shadow-lg) glass-blur", {
|
|
10
21
|
side: {
|
|
11
|
-
top: "inset-x-0 top-0 max-h-[85dvh]
|
|
12
|
-
bottom: "inset-x-0 bottom-0 max-h-[85dvh]
|
|
13
|
-
left: "inset-y-0 left-0 w-[min(20rem,85vw)]
|
|
14
|
-
right: "inset-y-0 right-0 w-[min(20rem,85vw)]
|
|
22
|
+
top: "inset-x-0 top-0 max-h-[85dvh]";
|
|
23
|
+
bottom: "inset-x-0 bottom-0 max-h-[85dvh]";
|
|
24
|
+
left: "inset-y-0 left-0 w-[min(20rem,85vw)]";
|
|
25
|
+
right: "inset-y-0 right-0 w-[min(20rem,85vw)]";
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* With a header the sheet is sectioned (the bar flush, the BODY scrolls
|
|
29
|
+
* — scrolling the root would carry the bar away with the content) and
|
|
30
|
+
* its detached corners drop to rd-md: they are formed by an md bar
|
|
31
|
+
* holding xxs controls, the pane's own corner law. Without one, the
|
|
32
|
+
* padded rd-lg surface is unchanged.
|
|
33
|
+
*/
|
|
34
|
+
header: {
|
|
35
|
+
true: "";
|
|
36
|
+
false: "gap-(--era-gap) overflow-y-auto p-(--era-pad-md)";
|
|
15
37
|
};
|
|
16
38
|
}, undefined, import("tailwind-variants").TVReturnTypeLike<{
|
|
17
39
|
side: {
|
|
18
|
-
top: "inset-x-0 top-0 max-h-[85dvh]
|
|
19
|
-
bottom: "inset-x-0 bottom-0 max-h-[85dvh]
|
|
20
|
-
left: "inset-y-0 left-0 w-[min(20rem,85vw)]
|
|
21
|
-
right: "inset-y-0 right-0 w-[min(20rem,85vw)]
|
|
40
|
+
top: "inset-x-0 top-0 max-h-[85dvh]";
|
|
41
|
+
bottom: "inset-x-0 bottom-0 max-h-[85dvh]";
|
|
42
|
+
left: "inset-y-0 left-0 w-[min(20rem,85vw)]";
|
|
43
|
+
right: "inset-y-0 right-0 w-[min(20rem,85vw)]";
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* With a header the sheet is sectioned (the bar flush, the BODY scrolls
|
|
47
|
+
* — scrolling the root would carry the bar away with the content) and
|
|
48
|
+
* its detached corners drop to rd-md: they are formed by an md bar
|
|
49
|
+
* holding xxs controls, the pane's own corner law. Without one, the
|
|
50
|
+
* padded rd-lg surface is unchanged.
|
|
51
|
+
*/
|
|
52
|
+
header: {
|
|
53
|
+
true: "";
|
|
54
|
+
false: "gap-(--era-gap) overflow-y-auto p-(--era-pad-md)";
|
|
22
55
|
};
|
|
23
56
|
}, undefined>>;
|
|
57
|
+
import type { Snippet } from 'svelte';
|
|
24
58
|
import { Dialog } from 'bits-ui';
|
|
25
59
|
type $$ComponentProps = PartProps<Dialog.ContentProps> & {
|
|
26
60
|
/** Screen edge the sheet is anchored to. */
|
|
27
61
|
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
62
|
+
/** A top bar in the pane's grammar — pass `Sheet.Header` holding `Sheet.Title`. */
|
|
63
|
+
header?: Snippet;
|
|
28
64
|
};
|
|
29
65
|
declare const SheetContent: import("svelte").Component<$$ComponentProps, {}, "ref">;
|
|
30
66
|
type SheetContent = ReturnType<typeof SheetContent>;
|