@estiva-app/ui 0.36.0 → 0.37.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/dist/Panel.d.ts +47 -0
- package/dist/Panel.d.ts.map +1 -0
- package/dist/ScrollArea.d.ts +7 -2
- package/dist/ScrollArea.d.ts.map +1 -1
- package/dist/eslint/index.js +16 -3
- package/dist/eslint/index.js.map +3 -3
- package/dist/eslint/no-handmade-header.d.ts +5 -0
- package/dist/eslint/no-handmade-header.d.ts.map +1 -1
- package/dist/eslint/no-native-title.d.ts +1 -1
- package/dist/eslint/no-native-title.d.ts.map +1 -1
- package/dist/gates/app-checks.d.ts +1 -1
- package/dist/gates/app-checks.d.ts.map +1 -1
- package/dist/gates/index.js +5 -2
- package/dist/gates/index.js.map +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +63 -36
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/registry.json +77 -3
- package/src/Panel.mdx +78 -0
- package/src/Panel.stories.tsx +111 -0
- package/src/Panel.tsx +83 -0
- package/src/ScrollArea.mdx +2 -2
- package/src/ScrollArea.stories.tsx +1 -1
- package/src/ScrollArea.tsx +9 -4
- package/src/eslint/no-handmade-header.test.ts +9 -0
- package/src/eslint/no-handmade-header.ts +24 -2
- package/src/eslint/no-native-title.ts +1 -1
- package/src/gates/app-checks.ts +5 -3
- package/src/index.ts +1 -0
- package/src/registry/app.test.ts +3 -1
- package/src/registry/registry.test.ts +4 -4
- package/stories/Choosing.mdx +4 -3
package/dist/Panel.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ReactNode, Ref, UIEventHandler } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* A panel of a page: its name in a `ContainerHeader`, a body under it that
|
|
4
|
+
* scrolls whenever it is taller than the room it has, and, when there is one,
|
|
5
|
+
* a row fixed at the bottom that never scrolls — a reply box.
|
|
6
|
+
*
|
|
7
|
+
* Made so that scrolling comes from the package, not from each app remembering
|
|
8
|
+
* it (Katerina, 26 September 2026). The apps built their panels from the
|
|
9
|
+
* package's header and a box of their own, and a box without a `ScrollArea`
|
|
10
|
+
* simply cut off what did not fit: Peek's widget panel on a Ship file lost the
|
|
11
|
+
* end of a long description and the status control under it, with no bar and
|
|
12
|
+
* nothing to scroll. Here the body is always a `ScrollArea`, so the bar shows
|
|
13
|
+
* as soon as there is more, and an empty panel or a short one has none.
|
|
14
|
+
*
|
|
15
|
+
* It takes the room it is given, never its content's height, so the body is
|
|
16
|
+
* what scrolls, not the page: the rest of a flex column (`flex-1 min-h-0`), or
|
|
17
|
+
* the whole of a plain box with a height (`h-full`). The second was missing in
|
|
18
|
+
* 0.37.0, and a panel in a plain box grew past it: Peek's thread story pushed
|
|
19
|
+
* its reply box out of its frame. Two panels in one column share it; a
|
|
20
|
+
* `max-h-*` in `className` caps one of them.
|
|
21
|
+
*
|
|
22
|
+
* It keeps a crash inside itself, as ListColumn does: if its body, its actions
|
|
23
|
+
* or its footer break, the panel keeps its title and shows `ErrorBoundary`'s
|
|
24
|
+
* message in the room the body had.
|
|
25
|
+
*/
|
|
26
|
+
export interface PanelProps {
|
|
27
|
+
/** The panel's name, in its header. A node for a title that is more than words. */
|
|
28
|
+
title: ReactNode;
|
|
29
|
+
/** A chevron after the title, as `ContainerHeader` draws it. */
|
|
30
|
+
chevron?: boolean;
|
|
31
|
+
/** The panel's own actions, at the header's right — a `Toolbar` of `ToolbarButton`s, or one `IconButton`. */
|
|
32
|
+
actions?: ReactNode;
|
|
33
|
+
/** The body. It scrolls when it is taller than the panel. */
|
|
34
|
+
children: ReactNode;
|
|
35
|
+
/** A row fixed under the body that never scrolls — a reply box. */
|
|
36
|
+
footer?: ReactNode;
|
|
37
|
+
/** The body's own box: its padding, gap and layout — `px-4 pt-3 pb-4`, `flex flex-col gap-2`. */
|
|
38
|
+
bodyClassName?: string;
|
|
39
|
+
/** The body's scrolling box, for a panel that reads or drives its scroll: a thread that opens at its newest reply. */
|
|
40
|
+
bodyRef?: Ref<HTMLDivElement>;
|
|
41
|
+
/** Fires as the body scrolls. */
|
|
42
|
+
onBodyScroll?: UIEventHandler<HTMLDivElement>;
|
|
43
|
+
/** Placement only: a cap such as `max-h-[60%]` when it shares a column. */
|
|
44
|
+
className?: string;
|
|
45
|
+
}
|
|
46
|
+
export declare function Panel(props: PanelProps): import("react").JSX.Element;
|
|
47
|
+
//# sourceMappingURL=Panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Panel.d.ts","sourceRoot":"","sources":["../src/Panel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAM3D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,UAAU;IACzB,mFAAmF;IACnF,KAAK,EAAE,SAAS,CAAA;IAChB,gEAAgE;IAChE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,6GAA6G;IAC7G,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,6DAA6D;IAC7D,QAAQ,EAAE,SAAS,CAAA;IACnB,mEAAmE;IACnE,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,iGAAiG;IACjG,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,sHAAsH;IACtH,OAAO,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAA;IAC7B,iCAAiC;IACjC,YAAY,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAA;IAC7C,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAmBD,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,+BActC"}
|
package/dist/ScrollArea.d.ts
CHANGED
|
@@ -7,8 +7,13 @@ import type { ReactNode, Ref, UIEventHandler } from 'react';
|
|
|
7
7
|
* right-hand padding looks wider than the left. Katerina saw it in every
|
|
8
8
|
* scrolling surface of both apps (2026-09-08). Base UI's `ScrollArea` hides
|
|
9
9
|
* the native bar and draws its own over the content, so nothing moves when
|
|
10
|
-
* it appears
|
|
11
|
-
*
|
|
10
|
+
* it appears.
|
|
11
|
+
*
|
|
12
|
+
* The bar shows whenever the region has more to scroll to, at rest too
|
|
13
|
+
* (Katerina, 26 September: a long folder list in Peek's side column looked
|
|
14
|
+
* complete, because the bar waited for the pointer). Base UI writes
|
|
15
|
+
* `data-has-overflow-y` / `-x` on the bar while that axis overflows; a region
|
|
16
|
+
* with nothing more to show keeps no bar at all.
|
|
12
17
|
*
|
|
13
18
|
* Three boxes, and each class prop lands on one:
|
|
14
19
|
*
|
package/dist/ScrollArea.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScrollArea.d.ts","sourceRoot":"","sources":["../src/ScrollArea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAI3D
|
|
1
|
+
{"version":3,"file":"ScrollArea.d.ts","sourceRoot":"","sources":["../src/ScrollArea.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAI3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,EAAE,UAAU,GAAG,YAAY,GAAG,MAAM,CAAA;IAChD,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAA;IACjC,uFAAuF;IACvF,QAAQ,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAA;IACzC,QAAQ,EAAE,SAAS,CAAA;CACpB;AAKD,wBAAgB,UAAU,CAAC,EAAE,WAAwB,EAAE,SAAS,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,eAAe,+BA4CxJ"}
|
package/dist/eslint/index.js
CHANGED
|
@@ -991,15 +991,28 @@ var INTERACTIVE = ["onClick", "href", "role", "onKeyDown", "onPointerDown"];
|
|
|
991
991
|
var noHandmadeHeader = {
|
|
992
992
|
meta: {
|
|
993
993
|
type: "problem",
|
|
994
|
-
docs: { description: "A column's header bar drawn by hand where
|
|
994
|
+
docs: { description: "A column's header bar drawn by hand, or the package's header on its own in an app, where Panel is the part" },
|
|
995
995
|
schema: [],
|
|
996
996
|
messages: {
|
|
997
|
-
handmade: "A column's header bar drawn by hand. Use `
|
|
997
|
+
handmade: "A column's header bar drawn by hand. Use `Panel` from @estiva-app/ui: its header (48px, the title, the column's buttons at the right edge in `actions`, a hairline under it) and a body under it that scrolls. For a list beside the page, `ListColumn`.",
|
|
998
|
+
bare: "A panel put together by hand: `ContainerHeader` over a box of your own, which cuts off whatever does not fit. Use `Panel` from @estiva-app/ui: the same header (`title`, `actions`), a body that scrolls whenever it is taller, and a `footer` that stays put. For a list beside the page, `ListColumn`.",
|
|
998
999
|
...ESCAPE_MESSAGES
|
|
999
1000
|
}
|
|
1000
1001
|
},
|
|
1001
1002
|
create(context) {
|
|
1003
|
+
const bare2 = /* @__PURE__ */ new Set();
|
|
1002
1004
|
return {
|
|
1005
|
+
ImportDeclaration(node) {
|
|
1006
|
+
const declaration = node;
|
|
1007
|
+
if (declaration.source.value !== "@estiva-app/ui") return;
|
|
1008
|
+
for (const specifier of declaration.specifiers) if (specifier.type === "ImportSpecifier" && specifier.imported?.name === "ContainerHeader") bare2.add(specifier.local.name);
|
|
1009
|
+
},
|
|
1010
|
+
JSXOpeningElement(node) {
|
|
1011
|
+
const element = node;
|
|
1012
|
+
if (element.name.type !== "JSXIdentifier" || !bare2.has(element.name.name ?? "")) return;
|
|
1013
|
+
if (isEscaped(context, element)) return;
|
|
1014
|
+
context.report({ loc: element.loc, messageId: "bare" });
|
|
1015
|
+
},
|
|
1003
1016
|
JSXElement(node) {
|
|
1004
1017
|
const column = node;
|
|
1005
1018
|
const kids = meaningful(column);
|
|
@@ -1389,7 +1402,7 @@ var noCopiedLook = {
|
|
|
1389
1402
|
};
|
|
1390
1403
|
|
|
1391
1404
|
// src/eslint/no-native-title.ts
|
|
1392
|
-
var PARTS_WITH_A_TITLE = ["CollapsibleSection", "ConfirmDialog", "ContainerHeader", "DialogShell", "ListColumn", "SectionHeader"];
|
|
1405
|
+
var PARTS_WITH_A_TITLE = ["CollapsibleSection", "ConfirmDialog", "ContainerHeader", "DialogShell", "ListColumn", "Panel", "SectionHeader"];
|
|
1393
1406
|
var child3 = (node, key) => node[key];
|
|
1394
1407
|
var nameOf4 = (node) => node?.type === "JSXIdentifier" || node?.type === "Identifier" ? node.name : void 0;
|
|
1395
1408
|
var noNativeTitle = {
|