@signal9/era-ui 4.14.0 → 4.15.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.
@@ -7,11 +7,20 @@
7
7
  let {
8
8
  ref = $bindable(null),
9
9
  children,
10
+ center,
11
+ trail,
10
12
  class: className,
11
13
  ...restProps
12
14
  }: HTMLAttributes<HTMLDivElement> & {
13
15
  ref?: HTMLDivElement | null;
14
16
  children?: Snippet;
17
+ /** Content centred on the BAR itself (a document title, a breadcrumb).
18
+ * Presence switches the handle to its three-track grid — see below. */
19
+ center?: Snippet;
20
+ /** Trailing cluster. With `center` it is the grid's third track; without,
21
+ * it renders as the familiar ml-auto cluster. The close/window controls
22
+ * belong here, always LAST — extra trailing content goes before them. */
23
+ trail?: Snippet;
15
24
  } = $props();
16
25
  </script>
17
26
 
@@ -49,9 +58,35 @@
49
58
  // bar itself. It still follows the bottom radius, so the divider curves up
50
59
  // at the ends exactly as before.
51
60
  'shrink-0 rounded-t-none rounded-b-(--era-rd-md) [box-shadow:0_1px_0_var(--color-divider-faded)] select-none',
61
+ // THE CENTRE LAW — [minmax(0,1fr) minmax(0,auto) minmax(0,1fr)].
62
+ //
63
+ // A centred title must be centred on the BAR, not on whatever space the
64
+ // sides happened to leave (a flex-1 spacer centres on the leftovers, so the
65
+ // title drifts every time the lead or trail grows — the reference terminal
66
+ // app has exactly that drift). Equal fr tracks pin the middle to the true
67
+ // centre no matter how unequal the sides are; when a side outgrows its
68
+ // share it TRUNCATES (minmax 0) instead of shoving the title, and only when
69
+ // both sides are exhausted does the centre itself start to yield. Nothing
70
+ // ever overlaps and nothing ever jumps.
71
+ //
72
+ // Grid only when centred content exists: the flex flow is the right model
73
+ // for every other handle, and children/trail render in it untouched.
74
+ center && 'grid grid-cols-[minmax(0,1fr)_minmax(0,auto)_minmax(0,1fr)]',
52
75
  className
53
76
  )}
54
77
  {...restProps}
55
78
  >
56
- {@render children?.()}
79
+ {#if center}
80
+ <div class="flex min-w-0 items-center gap-(--era-gap)">{@render children?.()}</div>
81
+ <!-- Anything interactive dropped in here (an editable title, a picker)
82
+ carries data-pane-control itself: the bar is the drag zone, and only
83
+ the control can know that a press on it means caret, not drag. -->
84
+ <div class="flex min-w-0 items-center justify-center gap-(--era-gap)">{@render center()}</div>
85
+ <div class="flex min-w-0 items-center justify-end gap-(--era-gap)">{@render trail?.()}</div>
86
+ {:else}
87
+ {@render children?.()}
88
+ {#if trail}
89
+ <div class="ml-auto flex shrink-0 items-center gap-(--era-gap)">{@render trail()}</div>
90
+ {/if}
91
+ {/if}
57
92
  </Bar>
@@ -3,6 +3,13 @@ import type { HTMLAttributes } from 'svelte/elements';
3
3
  type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
4
4
  ref?: HTMLDivElement | null;
5
5
  children?: Snippet;
6
+ /** Content centred on the BAR itself (a document title, a breadcrumb).
7
+ * Presence switches the handle to its three-track grid — see below. */
8
+ center?: Snippet;
9
+ /** Trailing cluster. With `center` it is the grid's third track; without,
10
+ * it renders as the familiar ml-auto cluster. The close/window controls
11
+ * belong here, always LAST — extra trailing content goes before them. */
12
+ trail?: Snippet;
6
13
  };
7
14
  declare const PaneHandle: import("svelte").Component<$$ComponentProps, {}, "ref">;
8
15
  type PaneHandle = ReturnType<typeof PaneHandle>;
@@ -23,6 +23,7 @@
23
23
  onDragEnd,
24
24
  onClose,
25
25
  header,
26
+ center,
26
27
  children,
27
28
  class: className,
28
29
  ...restProps
@@ -51,6 +52,8 @@
51
52
  onClose?: () => void;
52
53
  /** Extra handle-bar content, rendered after the title. */
53
54
  header?: Snippet;
55
+ /** Content centred on the bar itself — Pane.Handle's three-track grid. */
56
+ center?: Snippet;
54
57
  children?: Snippet;
55
58
  } = $props();
56
59
  </script>
@@ -58,6 +61,11 @@
58
61
  <!-- The ergonomic single-component pane: a titled handle + body, composed from
59
62
  the same Pane.Root / Handle / Content / Close parts you can assemble by hand
60
63
  for richer layouts (e.g. tabs in the handle — see Pane.Tabs). -->
64
+ <!-- Declared OUTSIDE <Root> — a snippet that is a direct child of a component
65
+ becomes one of its props, and Root has no `closeTrail`. -->
66
+ {#snippet closeTrail()}
67
+ <Close onclick={onClose} />
68
+ {/snippet}
61
69
  <Root
62
70
  bind:ref
63
71
  bind:position
@@ -71,11 +79,13 @@
71
79
  class={className}
72
80
  {...restProps}
73
81
  >
74
- <Handle>
82
+ <!-- The close cluster rides the `trail` slot, so it lands in the grid's third
83
+ track when `center` is present and in the ml-auto cluster when it isn't —
84
+ one close button, correct in both geometries. -->
85
+ <Handle {center} trail={onClose ? closeTrail : undefined}>
75
86
  {#if icon}{@const Icon = icon}<Icon class="size-(--era-h-xs) shrink-0 text-muted" />{/if}
76
87
  {#if title}<span class="text-body text-bright">{title}</span>{/if}
77
88
  {@render header?.()}
78
- {#if onClose}<Close onclick={onClose} class="ml-auto" />{/if}
79
89
  </Handle>
80
90
  {#if children}
81
91
  <Content>
@@ -33,6 +33,8 @@ type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
33
33
  onClose?: () => void;
34
34
  /** Extra handle-bar content, rendered after the title. */
35
35
  header?: Snippet;
36
+ /** Content centred on the bar itself — Pane.Handle's three-track grid. */
37
+ center?: Snippet;
36
38
  children?: Snippet;
37
39
  };
38
40
  declare const Pane: Component<$$ComponentProps, {}, "position" | "size" | "ref">;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signal9/era-ui",
3
- "version": "4.14.0",
3
+ "version": "4.15.0",
4
4
  "scripts": {
5
5
  "dev": "vite dev --host",
6
6
  "build": "vite build && npm run prepack",