neba 1.7.0 → 1.8.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.
Files changed (74) hide show
  1. package/README.md +7 -7
  2. package/dist/components/app-logo/AppLogo.d.ts +148 -0
  3. package/dist/components/app-logo/AppLogo.js +1 -0
  4. package/dist/components/app-logo/index.d.ts +2 -0
  5. package/dist/components/app-logo/index.js +1 -0
  6. package/dist/components/avatar/Avatar.js +1 -1
  7. package/dist/components/bottom-navigation/BottomNavigation.js +1 -1
  8. package/dist/components/code-block/CodeBlock.d.ts +170 -0
  9. package/dist/components/code-block/CodeBlock.js +1 -0
  10. package/dist/components/code-block/index.d.ts +2 -0
  11. package/dist/components/code-block/index.js +1 -0
  12. package/dist/components/color-picker/ColorPicker.d.ts +1 -1
  13. package/dist/components/drawer/Drawer.js +1 -1
  14. package/dist/components/footer/Footer.d.ts +85 -0
  15. package/dist/components/footer/Footer.js +1 -0
  16. package/dist/components/footer/index.d.ts +2 -0
  17. package/dist/components/footer/index.js +1 -0
  18. package/dist/components/header/Header.d.ts +114 -0
  19. package/dist/components/header/Header.js +1 -0
  20. package/dist/components/header/index.d.ts +2 -0
  21. package/dist/components/header/index.js +1 -0
  22. package/dist/components/how-to-steps/HowToSteps.d.ts +167 -0
  23. package/dist/components/how-to-steps/HowToSteps.js +1 -0
  24. package/dist/components/how-to-steps/index.d.ts +2 -0
  25. package/dist/components/how-to-steps/index.js +1 -0
  26. package/dist/components/page-layout/PageLayout.d.ts +144 -0
  27. package/dist/components/page-layout/PageLayout.js +1 -0
  28. package/dist/components/page-layout/index.d.ts +2 -0
  29. package/dist/components/page-layout/index.js +1 -0
  30. package/dist/components/sidebar/Sidebar.d.ts +144 -0
  31. package/dist/components/sidebar/Sidebar.js +1 -0
  32. package/dist/components/sidebar/SidebarTrigger.d.ts +36 -0
  33. package/dist/components/sidebar/SidebarTrigger.js +1 -0
  34. package/dist/components/sidebar/index.d.ts +4 -0
  35. package/dist/components/sidebar/index.js +1 -0
  36. package/dist/index.d.ts +7 -0
  37. package/dist/index.js +1 -1
  38. package/dist/internal/bottom-navigation.d.ts +4 -3
  39. package/dist/internal/chart.d.ts +3 -2
  40. package/dist/internal/color.d.ts +2 -2
  41. package/dist/internal/date.d.ts +3 -4
  42. package/dist/internal/highlight.d.ts +97 -0
  43. package/dist/internal/highlight.js +1 -0
  44. package/dist/internal/i18n.d.ts +85 -0
  45. package/dist/internal/i18n.js +1 -1
  46. package/dist/internal/icons.d.ts +20 -0
  47. package/dist/internal/icons.js +1 -1
  48. package/dist/internal/initials.d.ts +24 -0
  49. package/dist/internal/initials.js +1 -0
  50. package/dist/internal/page-layout.d.ts +143 -0
  51. package/dist/internal/page-layout.js +1 -0
  52. package/dist/internal/styles.d.ts +11 -0
  53. package/dist/internal/styles.js +1 -1
  54. package/dist/locales/ar.js +1 -1
  55. package/dist/locales/de.js +1 -1
  56. package/dist/locales/es.js +1 -1
  57. package/dist/locales/fr.js +1 -1
  58. package/dist/locales/hi.js +1 -1
  59. package/dist/locales/id.js +1 -1
  60. package/dist/locales/it.js +1 -1
  61. package/dist/locales/ja.js +1 -1
  62. package/dist/locales/ko.js +1 -1
  63. package/dist/locales/nl.js +1 -1
  64. package/dist/locales/pl.js +1 -1
  65. package/dist/locales/pt.js +1 -1
  66. package/dist/locales/ru.js +1 -1
  67. package/dist/locales/th.js +1 -1
  68. package/dist/locales/tr.js +1 -1
  69. package/dist/locales/vi.js +1 -1
  70. package/dist/locales/zh-hans.js +1 -1
  71. package/dist/locales/zh-hant.js +1 -1
  72. package/dist/styles.css +1 -1
  73. package/dist/tailwind.css +473 -0
  74. package/package.json +8 -7
@@ -0,0 +1,114 @@
1
+ import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
3
+ import type { NebaAlign, NebaColor, NebaDensity, NebaElevation, NebaPosition, NebaSize, NebaVariant } from '../../types.js';
4
+ export interface HeaderProps extends Omit<React.ComponentPropsWithoutRef<'header'>, 'color' | 'title'> {
5
+ /**
6
+ * The leading slot: the logo, the product's name, the thing that is the same
7
+ * on every page. An [AppLogo] is what usually goes here.
8
+ *
9
+ * It is a slot rather than the first of `children` because the three regions
10
+ * of a bar are laid out against each other — the middle can only be centred
11
+ * in the bar if the two ends are measured — and a caller writing three
12
+ * wrappers by hand is a caller whose header drifts from the next one.
13
+ */
14
+ brand?: React.ReactNode;
15
+ /**
16
+ * The trailing slot: the account menu, the theme switch, the call to action.
17
+ * Laid out end-aligned, so a row of buttons needs no wrapper of its own.
18
+ */
19
+ actions?: React.ReactNode;
20
+ /**
21
+ * Where the middle slot sits.
22
+ *
23
+ * - `start` — packed against the brand, taking whatever is left. The
24
+ * arrangement of an application's toolbar, and the default.
25
+ * - `center` — centred in the bar itself, not in the space left over. The two
26
+ * ends are given equal shares for this, so the middle stays on the bar's
27
+ * own midline however wide the brand is.
28
+ * - `end` — packed against the actions.
29
+ * @default 'start'
30
+ */
31
+ align?: NebaAlign;
32
+ /**
33
+ * How the bar sits in the page's scroll, spelled the way CSS spells it.
34
+ * `sticky` — the default — holds it against the top of the window once the
35
+ * page has scrolled to it, while leaving it in the flow so nothing has to be
36
+ * padded out of its way. `fixed` takes it out of the flow entirely, which a
37
+ * [PageLayout] answers by reserving its height. `static` lets it scroll away.
38
+ * @default 'sticky'
39
+ */
40
+ position?: NebaPosition;
41
+ /**
42
+ * Weight of the sheet, said the way a *container* says it: the bar is never
43
+ * dyed, because what is on it arrives with colours of its own.
44
+ * @default 'outline'
45
+ */
46
+ variant?: NebaVariant;
47
+ /**
48
+ * The bar's scale — its height floor, its gutter and the air around its
49
+ * slots. As on Box, `size` here is the size of the *sheet*.
50
+ * @default 'md'
51
+ */
52
+ size?: NebaSize;
53
+ /** @default 'primary' */
54
+ color?: NebaColor;
55
+ /** @default 'default' */
56
+ density?: NebaDensity;
57
+ /**
58
+ * Drop shadow depth. `0` (the default) is flat: a header is attached to the
59
+ * top of the window rather than floating over the middle of it, and `divider`
60
+ * is what separates it from the content.
61
+ * @default 0
62
+ */
63
+ elevation?: NebaElevation;
64
+ /**
65
+ * Draws a hairline along the bottom edge, against the content the bar is
66
+ * over. On by default, for BottomNavigation's reason: a bar pinned over a
67
+ * scrolling page has content passing underneath it at every moment, and a
68
+ * translucent sheet with nothing marking its edge reads as part of that.
69
+ * @default true
70
+ */
71
+ divider?: boolean;
72
+ /**
73
+ * Holds the row of slots to a measure and centres it, while the sheet itself
74
+ * still spans the window. On the same ladder Container's own `maxWidth` uses,
75
+ * so a header and the [Container] under it line up on the same edge.
76
+ * @default 'none'
77
+ */
78
+ maxWidth?: NebaSize | 'none';
79
+ /** The gutter down each side of the row. @default true */
80
+ padded?: boolean;
81
+ /**
82
+ * The name the bar is announced by. Worth writing when a page has more than
83
+ * one `<header>` in it — an article's own header and the site's — because
84
+ * "banner" twice tells a reader which is which not at all.
85
+ */
86
+ label?: string;
87
+ /**
88
+ * Renders something other than a `<header>`. Base UI's own escape hatch, and
89
+ * rarely what you want: the bar at the top of a page is a banner, and the tag
90
+ * is what says so to a search engine and to a screen reader's landmark list.
91
+ */
92
+ render?: useRender.RenderProp;
93
+ /** The middle slot. */
94
+ children?: React.ReactNode;
95
+ }
96
+ /**
97
+ * The bar across the top of a page.
98
+ *
99
+ * A real `<header>`, which is the whole reason it is a component rather than a
100
+ * row of divs: at the top level of a document that tag is the `banner`
101
+ * landmark, and it is what a screen reader's landmark list, a reader mode and a
102
+ * search engine's understanding of the page are all built out of.
103
+ *
104
+ * Its three slots are props rather than compound sub-components, for Card's and
105
+ * Dialog's reason: the arrangement is fixed — brand, middle, actions — and what
106
+ * a caller wants to decide is what goes in each. That the middle can be centred
107
+ * on the bar's own midline is only possible because the ends are the
108
+ * component's to measure.
109
+ *
110
+ * Inside a [PageLayout] it also registers itself, so a sidebar that holds its
111
+ * place knows how far down the window to start. Outside one it is simply a bar,
112
+ * and everything above still works.
113
+ */
114
+ export declare const Header: React.ForwardRefExoticComponent<HeaderProps & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as r from"react";import{useRender as n}from"@base-ui/react/use-render";import{boxPaddingXClasses as t}from"../box/Box.js";import{PageLayoutContext as s}from"../../internal/page-layout.js";import{cx as i,hasContent as l,surfaceClasses as m,surfaceSlots as o,transitionClasses as d}from"../../internal/styles.js";const c={xs:"min-h-10",sm:"min-h-12",md:"min-h-14",lg:"min-h-16",xl:"min-h-20"},x={xs:"gap-1.5",sm:"gap-2",md:"gap-3",lg:"gap-4",xl:"gap-5"},f={xs:"gap-3",sm:"gap-4",md:"gap-6",lg:"gap-8",xl:"gap-10"},p={xs:"max-w-[30rem]",sm:"max-w-[40rem]",md:"max-w-[48rem]",lg:"max-w-[64rem]",xl:"max-w-[80rem]"},u={solid:[m,"text-(--neba-fg) bg-(--n-panel-press)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[m,"text-(--neba-fg) bg-(--n-panel)","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:"text-(--neba-fg) bg-transparent"},g={static:"",sticky:"sticky top-0 z-30",fixed:"fixed inset-x-0 top-0 z-40"},h={start:"shrink-0",center:"flex-1 basis-0",end:"shrink-0"},b={start:"flex min-w-0 flex-1 items-center justify-start",center:"flex min-w-0 shrink items-center justify-center",end:"flex min-w-0 flex-1 items-center justify-end"};export const Header=/*@__PURE__*/r.forwardRef(function({brand:m,actions:v,align:w="start",position:y="sticky",variant:j="outline",size:N="md",color:k="primary",density:z="default",elevation:C=0,divider:B=!0,maxWidth:H="none",padded:R=!0,label:W,render:q,className:A,style:D,children:E,...F},G){const I=r.useContext(s),{register:J}=I,K=r.useCallback(e=>{J("header",e),"function"==typeof G?G(e):G&&(G.current=e)},[J,G]),L=i("w-full min-w-0",u[j],B?"border-b [border-color:var(--n-line)]":"",g[y],d,A);return n({render:q??e("header",{}),ref:K,props:{"aria-label":W,className:L,style:{...o(k,C),...D},children:a("div",{className:i("flex w-full items-center",c[N],f[N],R?t[z][N]:"","none"===H?"":i(p[H],"mx-auto")),children:[l(m)?e("div",{className:i("flex min-w-0 items-center",h[w],x[N]),children:m}):"center"===w?e("div",{"aria-hidden":"true",className:h[w]}):null,l(E)?e("div",{className:i(b[w],x[N]),children:E}):null,l(v)?e("div",{className:i("flex min-w-0 items-center justify-end",h[w],x[N]),children:v}):"center"===w?e("div",{"aria-hidden":"true",className:h[w]}):null]}),...F}})});
@@ -0,0 +1,2 @@
1
+ export { Header } from './Header.js';
2
+ export type { HeaderProps } from './Header.js';
@@ -0,0 +1 @@
1
+ export{Header}from"./Header.js";
@@ -0,0 +1,167 @@
1
+ import * as React from 'react';
2
+ import type { NebaColor, NebaDensity, NebaElevation, NebaOrientation, NebaSize, NebaTransition, NebaVariant } from '../../types.js';
3
+ /** One step of the guide. */
4
+ export interface HowToStep {
5
+ /** The heading, shown both in the list and over the step's own body. */
6
+ title: React.ReactNode;
7
+ /**
8
+ * A glyph before the title, over the step's own body.
9
+ *
10
+ * Only there, and not in the list: a row there already carries a numbered
11
+ * disc, and a glyph beside it is a second mark making the same claim about
12
+ * the same row. What an icon is good for is telling a reader *what kind* of
13
+ * step this is — a terminal, a file, a warning — which is a thing to say
14
+ * once, where the step is stated at full size.
15
+ */
16
+ icon?: React.ReactNode;
17
+ /** What the reader has to do. Anything — prose, a [CodeBlock], a screenshot. */
18
+ content?: React.ReactNode;
19
+ /** A picture above the content, for a step that is easier shown than said. */
20
+ image?: string;
21
+ /** What that picture says for a reader who cannot see it. Defaults to `title`. */
22
+ imageAlt?: string;
23
+ }
24
+ export interface HowToStepsProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'title' | 'content'> {
25
+ /**
26
+ * The steps, in the order they are to be done.
27
+ *
28
+ * An array rather than children, and this is the one place the component
29
+ * genuinely could not be built the other way: the list beside the body and
30
+ * the body itself are two renderings of the same data, and the panel is sized
31
+ * against *every* step rather than the one showing. A component that had to
32
+ * find its steps among its children could do neither.
33
+ */
34
+ steps: HowToStep[];
35
+ /** The guide's own heading, over both columns. */
36
+ title?: React.ReactNode;
37
+ /** Which step is showing. Pass it to drive the guide yourself. */
38
+ step?: number;
39
+ /** Where an uncontrolled guide starts. @default 0 */
40
+ defaultStep?: number;
41
+ /** Fires with the index whenever the step changes, however it changed. */
42
+ onStepChange?: (step: number) => void;
43
+ /** Whether the guide is finished. Pass it to drive that yourself too. */
44
+ completed?: boolean;
45
+ /** Whether an uncontrolled guide starts finished. @default false */
46
+ defaultCompleted?: boolean;
47
+ /** Fires when the guide is finished, and again when it is started over. */
48
+ onCompletedChange?: (completed: boolean) => void;
49
+ /**
50
+ * Which way the list of steps runs.
51
+ *
52
+ * `vertical` is the default: the numbers run down one side with the body
53
+ * beside them, which takes any number of steps and any amount to say about
54
+ * each. Below `sm` it stacks, because a rail and a paragraph side by side on
55
+ * a phone is two columns too narrow for either. `horizontal` runs the numbers
56
+ * across the top, and is only honest while every title is short.
57
+ * @default 'vertical'
58
+ */
59
+ orientation?: NebaOrientation;
60
+ /**
61
+ * How tall the guide may get before it scrolls. A number is pixels.
62
+ *
63
+ * Both the list and the body scroll inside it rather than the sheet growing.
64
+ * A guide with twenty steps is what this is for, and twenty rows that pushed
65
+ * the buttons off the bottom of the card would be a guide with no way
66
+ * forward.
67
+ */
68
+ maxHeight?: number | string;
69
+ /**
70
+ * How wide the list is while it is a column. A number is pixels.
71
+ * @default '15rem'
72
+ */
73
+ railWidth?: number | string;
74
+ /**
75
+ * The row of buttons under the body. Off, the list is the only way to move,
76
+ * which is what a guide inside a page that has navigation of its own wants.
77
+ * @default true
78
+ */
79
+ navigation?: boolean;
80
+ /**
81
+ * Draws a hairline between the list and the body — down the inner edge while
82
+ * they are two columns, along the bottom of the list once they have stacked.
83
+ *
84
+ * On by default. The two are different kinds of thing — one is a map, the
85
+ * other is the place the map points at — and space alone leaves that to be
86
+ * inferred from a gap that a narrow screen is about to take away.
87
+ * @default true
88
+ */
89
+ divider?: boolean;
90
+ /**
91
+ * How a step arrives when the reader moves to it, from the same vocabulary
92
+ * `transition` uses everywhere: an effect name, or the object form for the
93
+ * duration, the easing and the rest. `'none'` turns it off.
94
+ *
95
+ * It runs on the panel rather than on anything that is pressed, which is what
96
+ * keeps it inside the library's rule against moving a control: the buttons
97
+ * and the list rows hold still, and what animates is the content they
98
+ * changed.
99
+ *
100
+ * A reduced-motion preference switches it off entirely, as it does every
101
+ * other effect in the library.
102
+ * @default 'fade'
103
+ */
104
+ transition?: NebaTransition | 'none';
105
+ /**
106
+ * Whether there is a finished state at all.
107
+ *
108
+ * On, the last step's button says "Done" and pressing it replaces the body
109
+ * with a panel that says so and offers to start again. Off, the last step is
110
+ * simply the last step.
111
+ * @default true
112
+ */
113
+ completion?: boolean;
114
+ /** What the finished panel says, in place of the `locale`'s own sentence. */
115
+ completedContent?: React.ReactNode;
116
+ /**
117
+ * Weight of the sheet, said the way a *container* says it: the guide is never
118
+ * dyed, because what is in it arrives with colours of its own.
119
+ * @default 'outline'
120
+ */
121
+ variant?: NebaVariant;
122
+ /** @default 'md' */
123
+ size?: NebaSize;
124
+ /** The family the numbers, the connector and the buttons wear. @default 'primary' */
125
+ color?: NebaColor;
126
+ /** @default 'default' */
127
+ density?: NebaDensity;
128
+ /** Drop shadow depth. `0` (the default) is flat. @default 0 */
129
+ elevation?: NebaElevation;
130
+ /**
131
+ * Which language the guide's own words are in — the four buttons and the
132
+ * sentence at the end. A BCP 47 tag such as `ko`, `pt-BR` or `zh-Hant`;
133
+ * unsupported tags fall back to English.
134
+ */
135
+ locale?: string;
136
+ /** The four button labels, written out over the `locale`. */
137
+ previousLabel?: string;
138
+ nextLabel?: string;
139
+ doneLabel?: string;
140
+ restartLabel?: string;
141
+ }
142
+ /**
143
+ * A guide the reader walks through: numbered steps down one side, one step's
144
+ * instructions at a time beside them, and a way forward under those.
145
+ *
146
+ * It is [Timeline]'s interactive sibling, and the two are deliberately not one
147
+ * component. A Timeline *reports* — this happened, then this did, and here is
148
+ * where things have got to — and nothing in it is pressed. A HowToSteps *asks*:
149
+ * the reader is meant to do the thing on the screen and then say they have,
150
+ * which needs a current step, a way to change it, and an end.
151
+ *
152
+ * Two things about how it is built are load-bearing rather than incidental.
153
+ *
154
+ * **Every step's body is rendered into the same grid cell**, with the ones not
155
+ * showing left in the document, `invisible` and `inert`. The panel is therefore
156
+ * as tall as the tallest step at every moment, so moving between a one-line
157
+ * step and a five-line one does not resize the card the guide sits in — which,
158
+ * on a page the reader has already scrolled, moves everything under it. The
159
+ * finished panel is in that cell too, for the same reason.
160
+ *
161
+ * **The list is a list of buttons and not a tablist.** A stepper looks like
162
+ * tabs and is not one: the panels are ordered, the reader is expected to arrive
163
+ * at them in that order, and `aria-current="step"` is the attribute that says
164
+ * so. A tablist's roving focus would tell a screen reader that these are
165
+ * interchangeable views of one thing.
166
+ */
167
+ export declare const HowToSteps: React.ForwardRefExoticComponent<HowToStepsProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as t,Fragment as n}from"react/jsx-runtime";import*as l from"react";import{Button as r}from"../button/Button.js";import{boxPaddingClasses as a}from"../box/Box.js";import{CheckIcon as i,ChevronIcon as o,RestartIcon as s,SuccessIcon as c}from"../../internal/icons.js";import{stepsMessages as m,useMessages as d}from"../../internal/i18n.js";import{transitionProps as p}from"../../internal/animate.js";import{cx as f,hasContent as x,iconClasses as u,metaTextClasses as b,radiusClasses as h,sheetBodyClasses as g,sheetSectionGapClasses as v,sheetTitleClasses as N,srOnlyClasses as w,surfaceClasses as k,surfaceSlots as y,toLength as j,transitionClasses as C}from"../../internal/styles.js";const z={xs:{box:"1.25rem",text:"text-[0.625rem]"},sm:{box:"1.5rem",text:"text-[0.6875rem]"},md:{box:"1.75rem",text:"text-[0.75rem]"},lg:{box:"2rem",text:"text-[0.8125rem]"},xl:{box:"2.25rem",text:"text-[0.875rem]"}},S={default:{xs:"gap-0.5",sm:"gap-1",md:"gap-1",lg:"gap-1.5",xl:"gap-2"},compact:{xs:"gap-0",sm:"gap-0",md:"gap-0.5",lg:"gap-0.5",xl:"gap-1"}},L={solid:[k,"text-(--neba-fg) bg-(--n-panel-hover)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[k,"border text-(--neba-fg) bg-(--n-panel)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:"text-(--neba-fg) bg-transparent"};function I(e,t){return e.replace(/\{(\w+)\}/g,(e,n)=>t[n]??e)}function R(e){return"string"==typeof e?e:""}export const HowToSteps=/*@__PURE__*/l.forwardRef(function({steps:k,title:B,step:_,defaultStep:H=0,onStepChange:M,completed:T,defaultCompleted:$=!1,onCompletedChange:A,orientation:E="vertical",maxHeight:F,railWidth:W="15rem",navigation:q=!0,divider:D=!0,transition:G="fade",completion:J=!0,completedContent:K,variant:O="outline",size:P="md",color:Q="primary",density:U="default",elevation:V=0,locale:X,previousLabel:Y,nextLabel:Z,doneLabel:ee,restartLabel:te,className:ne,style:le,...re},ae){const ie=d(m,X),oe=l.useId(),[se,ce]=l.useState(H),[me,de]=l.useState($),pe=void 0!==_,fe=void 0!==T,xe=k.length,ue=Math.min(Math.max(pe?_:se,0),Math.max(xe-1,0)),be=J&&(fe?T:me),he=void 0!==F,ge="vertical"===E,ve=l.useRef(null),Ne=l.useRef(null);if(l.useEffect(()=>{const e=ve.current,t=Ne.current;if(!e||!t)return;const n=e.getBoundingClientRect(),l=t.getBoundingClientRect();ge?l.top<n.top?e.scrollTop-=n.top-l.top:l.bottom>n.bottom&&(e.scrollTop+=l.bottom-n.bottom):l.left<n.left?e.scrollLeft-=n.left-l.left:l.right>n.right&&(e.scrollLeft+=l.right-n.right)},[ue,ge]),0===xe)return null;const we=(e,t=!1)=>{fe||de(t),be!==t&&A?.(t),t||(pe||ce(e),e!==ue&&M?.(e))},ke=0===ue,ye=ue===xe-1,je="none"===G?null:p(G),Ce=t=>{const n=be||t<ue,l=!be&&t===ue;return e("span",{"aria-hidden":"true",className:f("z-1 flex shrink-0 items-center justify-center rounded-full border font-medium","size-(--n-step-mark) [&_svg]:size-[1.15em]",z[P].text,C,n?"bg-(--n-fill) text-(--n-on-solid) [border-color:transparent]":l?"bg-(--neba-surface) text-(--n-accent) [border-color:var(--n-accent)]":"bg-(--neba-surface) text-(--neba-muted-fg) [border-color:var(--n-line)]"),children:n?e(i,{}):t+1})},ze=e("ol",{ref:ve,"aria-label":ie.steps,className:f("m-0 flex list-none p-0",ge?"flex-col":"flex-row",S[U][P],he&&ge?"min-h-0 overflow-y-auto overscroll-contain":"",ge?"":"overflow-x-auto overscroll-contain"),children:k.map((n,l)=>{const r=be||l<ue,a=!be&&l===ue;return t("li",{ref:a?Ne:void 0,className:f("relative",ge?"":"min-w-0 flex-1"),children:[l<xe-1?e("span",{"aria-hidden":"true",className:f("absolute",C,r?"bg-(--n-fill)":"bg-(--n-line)",ge?["w-px","[inset-inline-start:calc(0.25rem+var(--n-step-mark)/2)]","[top:calc(0.25rem+var(--n-step-mark))]","[height:calc(100%-var(--n-step-mark))]"].join(" "):["h-px","[inset-inline-start:calc(50%+var(--n-step-mark)/2)]","[top:calc(0.25rem+var(--n-step-mark)/2)]","[width:calc(100%-var(--n-step-mark))]"].join(" "))}):null,t("button",{type:"button",onClick:()=>we(l),"aria-current":a?"step":void 0,className:f("flex w-full cursor-pointer items-center p-1 text-start",ge?"gap-3":"flex-col gap-1.5 text-center",h.sm,"hover:bg-(--n-soft)",C,"focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-1"),children:[Ce(l),e("span",{className:f("min-w-0",ge?"truncate":"",b[P],a?"font-medium text-(--neba-fg)":"text-(--neba-muted-fg)"),children:n.title}),e("span",{className:w,children:I(ie.step,{index:String(l+1),title:R(n.title)})})]})]},l)})}),Se=t("div",{className:f("grid flex-1 grid-cols-1",he?"min-h-0":""),children:[k.map((n,l)=>{const r=be||l!==ue;return t("div",{"aria-hidden":r,inert:r||void 0,className:f("col-start-1 row-start-1 min-w-0",he?"overflow-y-auto overscroll-contain":"",r?"invisible":je?.className??""),style:r?void 0:je?.style,children:[t("div",{className:"mb-3 flex items-baseline gap-3",children:[x(n.icon)?e("span",{"aria-hidden":"true",className:f("flex h-[1lh] shrink-0 items-center text-(--n-accent)",N[P],u),children:n.icon}):null,e("h4",{className:f("m-0 min-w-0 flex-1 font-medium",N[P]),children:n.title}),e("span",{className:f("shrink-0 text-(--neba-muted-fg) tabular-nums",b[P]),children:I(ie.position,{index:String(l+1),total:String(xe)})})]}),n.image?e("img",{src:n.image,alt:n.imageAlt??R(n.title),className:f("mb-3 max-h-72 w-full object-contain",h[P])}):null,x(n.content)?e("div",{className:f("min-w-0",g[P]),children:n.content}):null]},l)}),J?t("div",{"aria-hidden":!be,inert:!be||void 0,className:f("col-start-1 row-start-1 flex min-w-0 flex-col items-center justify-center gap-2 py-4 text-center",be?je?.className??"":"invisible"),style:be?je?.style:void 0,children:[e("span",{"aria-hidden":"true",className:"text-(--n-accent) [&_svg]:size-9",children:e(c,{})}),e("p",{className:f("m-0 font-medium",g[P]),children:K??ie.completed})]}):null]});return t("div",{ref:ae,"aria-labelledby":x(B)?oe:void 0,className:f("flex min-w-0 flex-col",h[P],a[U][P],v[P],L[O],C,ne),style:{...y(Q,V),"--n-fill":`var(--neba-${Q}-fill)`,"--n-on-solid":`var(--neba-${Q}-on-solid)`,"--n-step-mark":z[P].box,"--n-step-rail":j(W),...he?{maxHeight:j(F)}:null,...le},...re,children:[x(B)?e("h3",{id:oe,className:f("m-0 shrink-0 font-medium",N[P]),children:B}):null,t("div",{className:f("flex min-w-0 flex-1 flex-col",he?"min-h-0":"",ge?"gap-4 sm:flex-row sm:gap-5":"gap-4"),children:[e("div",{className:f("flex min-w-0 flex-col",he?"min-h-0":"",ge?"sm:w-(--n-step-rail) sm:shrink-0":"",D?ge?"border-b pb-4 sm:border-b-0 sm:border-e sm:pb-0 sm:pe-5":"border-b pb-4":"",D?"[border-color:var(--n-line)]":""),children:ze}),t("div",{className:f("flex min-w-0 flex-1 flex-col",he?"min-h-0":"",v[P]),children:[Se,q?e("div",{className:"flex shrink-0 flex-wrap items-center justify-end gap-2",children:be?e(r,{size:P,variant:"outline",color:Q,startIcon:e(s,{}),onClick:()=>we(0),children:te??ie.restart}):t(n,{children:[e(r,{size:P,variant:"outline",color:Q,disabled:ke,startIcon:e("span",{className:"rotate-90 rtl:-rotate-90",children:e(o,{})}),onClick:()=>we(ue-1),children:Y??ie.previous}),e(r,ye&&J?{size:P,variant:"solid",color:Q,startIcon:e(i,{}),onClick:()=>we(ue,!0),children:ee??ie.done}:{size:P,variant:"solid",color:Q,disabled:ye,endIcon:e("span",{className:"-rotate-90 rtl:rotate-90",children:e(o,{})}),onClick:()=>we(ue+1),children:Z??ie.next})]})}):null]})]})]})});
@@ -0,0 +1,2 @@
1
+ export { HowToSteps } from './HowToSteps.js';
2
+ export type { HowToStep, HowToStepsProps } from './HowToSteps.js';
@@ -0,0 +1 @@
1
+ export{HowToSteps}from"./HowToSteps.js";
@@ -0,0 +1,144 @@
1
+ import * as React from 'react';
2
+ import { type PageLayoutCollapse, type PageLayoutScroll, type PageLayoutSpan } from '../../internal/page-layout.js';
3
+ import type { NebaColor } from '../../types.js';
4
+ export type { PageLayoutCollapse, PageLayoutScroll, PageLayoutSpan } from '../../internal/page-layout.js';
5
+ export interface PageLayoutProps extends React.ComponentPropsWithoutRef<'div'> {
6
+ /** The bar across the top. A [Header], usually. */
7
+ header?: React.ReactNode;
8
+ /** The sheet at the end. A [Footer], usually. */
9
+ footer?: React.ReactNode;
10
+ /**
11
+ * The leading column — the left of an English page, the right of an Arabic
12
+ * one. A [Sidebar], which is told which end it is on and needs no `side` prop
13
+ * of its own here.
14
+ */
15
+ sidebar?: React.ReactNode;
16
+ /**
17
+ * The trailing column, for the layouts that have two: navigation down one
18
+ * side and a table of contents, an inspector or a filter panel down the
19
+ * other. Each is a Sidebar with its own width, its own drawer and its own
20
+ * trigger.
21
+ */
22
+ endSidebar?: React.ReactNode;
23
+ /**
24
+ * Which of the header and the sidebars takes the top corner.
25
+ *
26
+ * - `full` — the header spans the whole width and the sidebars begin
27
+ * underneath it. The arrangement of a website. The default.
28
+ * - `content` — the sidebars run the full height of the window and the header
29
+ * sits between them, belonging to the view rather than to the site. The
30
+ * arrangement of an application.
31
+ * @default 'full'
32
+ */
33
+ headerSpan?: PageLayoutSpan;
34
+ /**
35
+ * The same question for the footer, and it is worth answering separately: a
36
+ * dashboard with a full-height navigation rail still usually wants its
37
+ * copyright line under the content rather than under the rail.
38
+ * @default 'full'
39
+ */
40
+ footerSpan?: PageLayoutSpan;
41
+ /**
42
+ * What scrolls: the document, or only the region between the header and the
43
+ * footer.
44
+ *
45
+ * `page` is the default and is what almost every page wants — the browser's
46
+ * own address bar hides on a phone, the scroll position is restored on a back
47
+ * navigation, and the header holds its place with `position: sticky` without
48
+ * anything having to be padded out of its way. Reach for `content` when the
49
+ * page is a workspace rather than a document.
50
+ * @default 'page'
51
+ */
52
+ scroll?: PageLayoutScroll;
53
+ /**
54
+ * How tall the layout is.
55
+ *
56
+ * - `viewport` — the window's, which is what a page wants: a short page still
57
+ * pushes its footer to the bottom of the screen, and with `scroll="content"`
58
+ * the layout is exactly one screen tall. The default.
59
+ * - `auto` — its parent's, for a layout that is not the page. An app shell
60
+ * inside a [Mockup]'s screen, a preview, a pane of a larger tool.
61
+ * - a length — a number in pixels, or any CSS length.
62
+ *
63
+ * It sets a floor while the page scrolls and an exact height while only the
64
+ * content does, which is the same difference `scroll` makes everywhere else.
65
+ * @default 'viewport'
66
+ */
67
+ height?: 'viewport' | 'auto' | number | string;
68
+ /**
69
+ * The window width below which the sidebars stop being columns and become
70
+ * drawers, with a [SidebarTrigger] as the way to open them. `none` keeps them
71
+ * as columns at every width.
72
+ * @default 'md'
73
+ */
74
+ collapseBelow?: PageLayoutCollapse;
75
+ /**
76
+ * Whether the leading sidebar's drawer is open. Use with
77
+ * `onSidebarOpenChange` for a controlled layout — a route change that should
78
+ * close the drawer behind it, a state the app already stores.
79
+ */
80
+ sidebarOpen?: boolean;
81
+ /** Which state it starts in. @default false */
82
+ defaultSidebarOpen?: boolean;
83
+ onSidebarOpenChange?: (open: boolean) => void;
84
+ /** The same three for the trailing sidebar. */
85
+ endSidebarOpen?: boolean;
86
+ defaultEndSidebarOpen?: boolean;
87
+ onEndSidebarOpenChange?: (open: boolean) => void;
88
+ /**
89
+ * Puts a "Skip to content" link first in the document, drawn only while it
90
+ * holds the focus.
91
+ *
92
+ * On by default, and it is the one thing here that is not a style decision. A
93
+ * keyboard reader arriving on a page whose navigation holds forty links has
94
+ * to walk past all forty on every page before reaching the article, and this
95
+ * is the one link that spares them. It costs a sighted reader nothing,
96
+ * because it is invisible until it is tabbed to.
97
+ * @default true
98
+ */
99
+ skipLink?: boolean;
100
+ /** What that link says. Defaults to the `locale`'s word for it. */
101
+ skipLabel?: string;
102
+ /**
103
+ * The `id` the skip link jumps to, put on the `<main>`.
104
+ * @default 'main'
105
+ */
106
+ mainId?: string;
107
+ /** Anything else the `<main>` needs — a `className`, an `aria-label`. */
108
+ mainProps?: Omit<React.ComponentPropsWithoutRef<'main'>, 'id' | 'children'>;
109
+ /**
110
+ * Which language the layout's own words are in — a BCP 47 tag such as `ko`,
111
+ * `pt-BR` or `zh-Hant`. Inherited by every Sidebar and SidebarTrigger inside
112
+ * it, so it is written once per page.
113
+ */
114
+ locale?: string;
115
+ /** The colour family the skip link and the focus rings light up in. @default 'primary' */
116
+ color?: NebaColor;
117
+ /** The page. Rendered inside the `<main>`. */
118
+ children?: React.ReactNode;
119
+ }
120
+ /**
121
+ * The skeleton a page is hung on: a header, a footer, one sidebar or two, and
122
+ * the content between them.
123
+ *
124
+ * What it is really for is the landmarks. A page assembled out of divs is a
125
+ * page a screen reader offers as one undifferentiated region and a search
126
+ * engine reads as one undifferentiated blob; the same page built out of
127
+ * `<header>`, `<nav>`, `<aside>`, `<main>` and `<footer>` is a page with a
128
+ * table of contents. Those tags come from the four components this one arranges
129
+ * — it draws no surface of its own and contributes exactly one element to the
130
+ * document, plus the `<main>` and the skip link that jumps to it.
131
+ *
132
+ * The arrangement is flexbox and media queries, which is deliberate rather than
133
+ * incidental: everything that decides where a column goes is stated in CSS, so
134
+ * the layout is right in the first frame the browser paints and right in a page
135
+ * with JavaScript turned off. The only things measured are the header's and the
136
+ * footer's heights, and only because a sidebar that holds its place has to
137
+ * start below a bar whose height nobody but the bar knows.
138
+ *
139
+ * It draws no gutter and no measure. That is [Container]'s job, and a layout
140
+ * that also did it would be a second spelling of one idea — put a Container
141
+ * inside, where a page can have a wide dashboard on one route and a narrow
142
+ * article on the next.
143
+ */
144
+ export declare const PageLayout: React.ForwardRefExoticComponent<PageLayoutProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as n}from"react/jsx-runtime";import*as o from"react";import{layoutMessages as l,useMessages as t}from"../../internal/i18n.js";import{PageLayoutContext as r,SidebarSideContext as s}from"../../internal/page-layout.js";import{controlSlots as a,cx as i,hasContent as u,toLength as c}from"../../internal/styles.js";const d=["header","footer"];export const PageLayout=/*@__PURE__*/o.forwardRef(function({header:f,footer:p,sidebar:h,endSidebar:m,headerSpan:v="full",footerSpan:x="full",scroll:y="page",height:b="viewport",collapseBelow:w="md",sidebarOpen:g,defaultSidebarOpen:S=!1,onSidebarOpenChange:k,endSidebarOpen:C,defaultEndSidebarOpen:P=!1,onEndSidebarOpenChange:O,skipLink:N=!0,skipLabel:j,mainId:$="main",mainProps:R,locale:z,color:E="primary",className:L,style:B,children:H,...M},_){const I=t(l,z),[T,q]=o.useState(S),[A,D]=o.useState(P),F=o.useMemo(()=>({start:g??T,end:C??A}),[g,T,C,A]),G=o.useCallback((e,n)=>{if("start"===e)return void 0===g&&q(n),void k?.(n);void 0===C&&D(n),O?.(n)},[g,C,k,O]),J=o.useRef(null),K=o.useCallback(e=>{J.current=e,"function"==typeof _?_(e):_&&(_.current=e)},[_]),Q=o.useRef({header:null,footer:null}),U=o.useRef(null),V=o.useCallback(()=>{const e=J.current;if(e)for(const n of d){const o=Q.current[n],l="header"===n?v:x;if(!o){e.style.setProperty(`--n-layout-${n}`,"0px"),e.style.setProperty(`--n-layout-${n}-inset`,"0px");continue}const t=getComputedStyle(o).position,r=`${o.offsetHeight}px`,s="sticky"===t||"fixed"===t;e.style.setProperty(`--n-layout-${n}`,s&&"full"===l?r:"0px"),e.style.setProperty(`--n-layout-${n}-inset`,"fixed"===t?r:"0px")}},[v,x]),W=o.useCallback(()=>{const e=U.current;if(e){e.disconnect();for(const n of d){const o=Q.current[n];o&&e.observe(o)}}V()},[V]);o.useEffect(()=>(U.current=new ResizeObserver(()=>V()),W(),()=>{U.current?.disconnect(),U.current=null}),[V,W]);const X=o.useCallback((e,n)=>{Q.current[e]=n,W()},[W]),Y=o.useMemo(()=>({present:!0,register:X,collapseBelow:w,open:F,setOpen:G,scroll:y,locale:z}),[X,w,F,G,y,z]),Z="content"===y,ee=c("viewport"===b||"auto"===b?void 0:b),ne=void 0!==ee?"":"auto"===b?Z?"h-full":"min-h-full":Z?"h-dvh":"min-h-dvh",oe=u(f)?f:null,le=u(p)?p:null;return e(r.Provider,{value:Y,children:n("div",{ref:K,className:i("relative flex w-full flex-col",Z?"overflow-hidden":"",ne,"full"===v?"[padding-top:var(--n-layout-header-inset,0px)]":"","full"===x?"[padding-bottom:var(--n-layout-footer-inset,0px)]":"",L),style:void 0===ee?B:{...Z?{height:ee}:{minHeight:ee},...B},...M,children:[N?e("a",{href:`#${$}`,className:i("absolute start-3 top-3 z-50 size-px overflow-hidden whitespace-nowrap","[clip-path:inset(50%)] focus:size-auto focus:overflow-visible focus:[clip-path:none]","focus:rounded-(--neba-radius-md) focus:bg-(--n-fill) focus:px-4 focus:py-2","focus:font-medium focus:text-(--n-on-solid) focus:no-underline","focus:[box-shadow:var(--neba-shadow-2),var(--neba-plate-solid)]","focus:[outline:2px_solid_var(--n-ring)] focus:outline-offset-2"),style:a(E,2,"solid"),children:j??I.skipToContent}):null,"full"===v?oe:null,n("div",{className:i("flex w-full flex-1",Z?"min-h-0":""),children:[u(h)?e(s.Provider,{value:"start",children:h}):null,n("div",{className:i("flex min-w-0 flex-1 flex-col",Z?"min-h-0":"","content"===v?"[padding-top:var(--n-layout-header-inset,0px)]":"","content"===x?"[padding-bottom:var(--n-layout-footer-inset,0px)]":""),children:["content"===v?oe:null,e("main",{...R,id:$,className:i("min-w-0 flex-1",Z?"min-h-0 overflow-y-auto":"",R?.className),children:H}),"content"===x?le:null]}),u(m)?e(s.Provider,{value:"end",children:m}):null]}),"full"===x?le:null]})})});
@@ -0,0 +1,2 @@
1
+ export { PageLayout } from './PageLayout.js';
2
+ export type { PageLayoutCollapse, PageLayoutProps, PageLayoutScroll, PageLayoutSpan } from './PageLayout.js';
@@ -0,0 +1 @@
1
+ export{PageLayout}from"./PageLayout.js";
@@ -0,0 +1,144 @@
1
+ import * as React from 'react';
2
+ import type { PageLayoutCollapse, SidebarSide } from '../../internal/page-layout.js';
3
+ import type { NebaColor, NebaDensity, NebaElevation, NebaSize, NebaVariant } from '../../types.js';
4
+ export type { SidebarSide } from '../../internal/page-layout.js';
5
+ export interface SidebarProps extends Omit<React.ComponentPropsWithoutRef<'aside'>, 'color' | 'title'> {
6
+ /**
7
+ * Which end of the band it takes. Logical rather than physical — `start` is
8
+ * the left of an English page and the right of an Arabic one — because a
9
+ * navigation rail is beside the text it belongs to in every writing
10
+ * direction.
11
+ *
12
+ * Inside a [PageLayout] this is already decided by which slot the sidebar was
13
+ * handed to, and setting it again is only a way of disagreeing with the
14
+ * layout.
15
+ * @default 'start'
16
+ */
17
+ side?: SidebarSide;
18
+ /**
19
+ * How wide the column is — a number in pixels or any CSS length. Left out, it
20
+ * is the width `size` implies.
21
+ *
22
+ * With `resizable` it is only the width the sidebar *starts* at: dragging
23
+ * writes over it, and the caller hears about it through `onResize`.
24
+ */
25
+ width?: number | string;
26
+ /** How narrow it may be dragged. @default 160 */
27
+ minWidth?: number | string;
28
+ /** And how wide. @default 480 */
29
+ maxWidth?: number | string;
30
+ /**
31
+ * Lets the reader drag the inner edge to change the column's width.
32
+ *
33
+ * Off by default. A sidebar that can be resized is a sidebar whose width is
34
+ * the reader's to remember, which means a caller who turns this on usually
35
+ * also wants to store what `onResizeEnd` reports.
36
+ * @default false
37
+ */
38
+ resizable?: boolean;
39
+ /** Fires with the width in pixels while the edge is being dragged. */
40
+ onResize?: (width: number) => void;
41
+ /** Fires once, with the same number, when it is let go. */
42
+ onResizeEnd?: (width: number) => void;
43
+ /**
44
+ * The window width below which the sidebar stops being a column and becomes a
45
+ * drawer that is opened — with a [SidebarTrigger] somewhere on the page as
46
+ * the way to open it. `none` keeps it a column at every width.
47
+ *
48
+ * Defaults to the [PageLayout]'s own `collapseBelow`, and to `none` outside
49
+ * one: a sidebar that collapsed with nothing on the page able to bring it
50
+ * back would be a sidebar the reader has lost.
51
+ */
52
+ collapseBelow?: PageLayoutCollapse;
53
+ /**
54
+ * Whether the drawer is open. Only meaningful once the sidebar has collapsed;
55
+ * a column is not opened, it is there.
56
+ *
57
+ * Inside a [PageLayout] the layout owns this — it is what a SidebarTrigger
58
+ * anywhere on the page talks to — so control it there rather than here.
59
+ * `onOpenChange` still fires either way.
60
+ */
61
+ open?: boolean;
62
+ /** Which state it starts in, for an uncontrolled standalone sidebar. @default false */
63
+ defaultOpen?: boolean;
64
+ onOpenChange?: (open: boolean) => void;
65
+ /**
66
+ * Whether the column holds its place while the page scrolls past it.
67
+ *
68
+ * On by default, and it costs nothing when it is not needed: with the page
69
+ * scrolling it becomes a `sticky` column as tall as what is left of the
70
+ * window under the header, and with only the content scrolling it is already
71
+ * as tall as the layout and this changes nothing.
72
+ * @default true
73
+ */
74
+ sticky?: boolean;
75
+ /**
76
+ * The heading, drawn only while the sidebar is a drawer. A column has the
77
+ * page around it to say what it is; a panel that has covered the page does
78
+ * not.
79
+ */
80
+ title?: React.ReactNode;
81
+ /**
82
+ * Weight of the sheet, said the way a *container* says it: the panel is never
83
+ * dyed, because what is on it arrives with colours of its own.
84
+ * @default 'outline'
85
+ */
86
+ variant?: NebaVariant;
87
+ /** The panel's scale — its default width and the air around its content. @default 'md' */
88
+ size?: NebaSize;
89
+ /** @default 'primary' */
90
+ color?: NebaColor;
91
+ /** @default 'default' */
92
+ density?: NebaDensity;
93
+ /** Drop shadow depth. `0` (the default) is flat. @default 0 */
94
+ elevation?: NebaElevation;
95
+ /**
96
+ * Draws a hairline down the inner edge — the one facing the content. The
97
+ * outer edge is against the window, where there is nothing on the other side
98
+ * to be separated from.
99
+ * @default true
100
+ */
101
+ divider?: boolean;
102
+ /** The gutter and the air above and below the content. @default true */
103
+ padded?: boolean;
104
+ /**
105
+ * The name the region is announced by. Every `<aside>` on a page should have
106
+ * one, and a page with two sidebars *must*, or a screen reader offers two
107
+ * regions called "complementary".
108
+ *
109
+ * Defaults to the `locale`'s word for "Sidebar".
110
+ */
111
+ label?: string;
112
+ /**
113
+ * Which language the sidebar's own words are in — a BCP 47 tag such as `ko`,
114
+ * `pt-BR` or `zh-Hant`. Unsupported tags fall back to English. Inherited from
115
+ * the [PageLayout] when there is one.
116
+ */
117
+ locale?: string;
118
+ /** Everything in it: a nav, a filter panel, a table of contents. */
119
+ children?: React.ReactNode;
120
+ }
121
+ /**
122
+ * A column beside the page's content, and a drawer once the window is too
123
+ * narrow to hold one.
124
+ *
125
+ * Two presentations of one panel, exactly as [Drawer] is: above `collapseBelow`
126
+ * it is an `<aside>` in the layout that the content is laid out around, and
127
+ * below it the same children are a drawer over a scrim with a focus trap, an
128
+ * Escape and a way back to the trigger. They are one component because they are
129
+ * one thing — a caller should not have to swap components at a breakpoint — and
130
+ * because the children only exist once either way, so nothing inside is
131
+ * rendered twice into the document for a screen reader to read twice.
132
+ *
133
+ * Which of the two is showing is a media query, and it is answered in CSS for
134
+ * the first paint and in JavaScript from then on. That split is deliberate: the
135
+ * markup a server sends is the column, so a narrow screen would draw a full
136
+ * width sidebar and throw it away a moment later — the class that hides it
137
+ * below the breakpoint is what stops that, and `matchMedia` is what decides,
138
+ * once there is a window to ask, that the drawer should exist at all.
139
+ *
140
+ * A real `<aside>`, which is the `complementary` landmark: the region a screen
141
+ * reader offers as "related to the page but not the page", and what a search
142
+ * engine reads as navigation chrome rather than as the article.
143
+ */
144
+ export declare const Sidebar: React.ForwardRefExoticComponent<SidebarProps & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as r from"react";import{boxPaddingXClasses as n,boxPaddingYClasses as o}from"../box/Box.js";import{Drawer as s}from"../drawer/Drawer.js";import{layoutMessages as i,useMessages as a}from"../../internal/i18n.js";import{drawerSide as l,expandedOnlyClasses as d,PageLayoutContext as c,SidebarSideContext as u,useCollapsed as p}from"../../internal/page-layout.js";import{cx as m,surfaceClasses as f,surfaceSlots as b,toLength as v,transitionClasses as y}from"../../internal/styles.js";const g={xs:"11rem",sm:"13rem",md:"16rem",lg:"18rem",xl:"21rem"},w={solid:[f,"text-(--neba-fg) bg-(--n-panel-press)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[f,"text-(--neba-fg) bg-(--n-panel)","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:"text-(--neba-fg) bg-transparent"};function x(e,t){if(null==e)return t;if("number"==typeof e)return e;const r=/^\s*(-?[\d.]+)\s*(px|rem|em|%)\s*$/.exec(e);if(!r)return t;const n=Number(r[1]);if(Number.isNaN(n))return t;switch(r[2]){case"px":return n;case"%":return"undefined"==typeof window?t:window.innerWidth*n/100;default:return n*parseFloat(("undefined"==typeof document?"":getComputedStyle(document.documentElement).fontSize)||"16")}}export const Sidebar=/*@__PURE__*/r.forwardRef(function({side:f,width:h,minWidth:k=160,maxWidth:C=480,resizable:j=!1,onResize:z,onResizeEnd:E,collapseBelow:N,open:R,defaultOpen:L=!1,onOpenChange:S,sticky:P=!0,title:B,variant:D="outline",size:O="md",color:A="primary",density:M="default",elevation:W=0,divider:I=!0,padded:T=!0,label:X,locale:$,className:_,style:F,children:K,...V},q){const G=r.useContext(c),H=r.useContext(u),J=f??H??"start",Q=$??G.locale,U=a(i,Q),Y=N??(G.present?G.collapseBelow:"none"),Z=p(Y),[ee,te]=r.useState(L),re=void 0!==R,ne=re?R:G.present?G.open[J]:ee,oe=e=>{re||(G.present?G.setOpen(J,e):te(e)),S?.(e)},se=v(h)??g[O],ie=r.useRef(null),ae=r.useCallback(e=>{ie.current=e,"function"==typeof q?q(e):q&&(q.current=e)},[q]),le=r.useRef(null);r.useEffect(()=>()=>le.current?.(),[]);const de=e=>{const t=ie.current;if(!t)return e;const r=Math.min(x(C,480),Math.max(x(k,160),Math.round(e)));return t.style.setProperty("--n-sidebar-w",`${r}px`),r},ce=e("div",{className:m("min-h-0 flex-1 overflow-y-auto overscroll-contain",T?m(n[M][O],o[M][O]):""),children:K});return Z?e(s,{side:l(J),mode:"overlay",open:ne,onOpenChange:oe,title:B,size:O,color:A,density:M,locale:Q,closeLabel:U.closeSidebar,extent:void 0===h?void 0:se,"aria-label":B?void 0:X??U.sidebar,className:_,style:F,children:K}):t("aside",{ref:ae,"aria-label":X??U.sidebar,className:m("relative flex min-w-0 shrink-0 flex-col","w-(--n-sidebar-w)",w[D],I?m("start"===J?"border-e":"border-s","[border-color:var(--n-line)]"):"","content"===G.scroll?"h-full":P?m("self-start","sticky [top:var(--n-layout-header,0px)]","[height:calc(100dvh-var(--n-layout-header,0px)-var(--n-layout-footer,0px))]"):"",d[Y],y,_),style:{...b(A,W),"--n-sidebar-w":se,...F},...V,children:[ce,j?e("div",{role:"separator","aria-orientation":"vertical","aria-label":U.resizeSidebar,tabIndex:0,className:m("absolute inset-y-0 z-1 w-2 cursor-col-resize","start"===J?"end-0 -me-1":"start-0 -ms-1","bg-transparent hover:bg-(--n-soft) data-[dragging]:bg-(--n-soft)",y,"[outline:none] focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-0"),onPointerDown:e=>{const t=ie.current;if(!t||0!==e.button)return;const r=e.currentTarget;r.setPointerCapture(e.pointerId),r.dataset.dragging="true";const n=document.body.style.getPropertyValue("-webkit-user-select");document.body.style.setProperty("-webkit-user-select","none");const o=e.clientX,s=t.getBoundingClientRect().width,i="rtl"===getComputedStyle(t).direction,a="start"===J===i?-1:1;let l=s;const d=e=>{l=de(s+(e.clientX-o)*a),z?.(l)},c=()=>{le.current=null,r.removeEventListener("pointermove",d),r.removeEventListener("pointerup",u),r.removeEventListener("pointercancel",u),delete r.dataset.dragging,n?document.body.style.setProperty("-webkit-user-select",n):document.body.style.removeProperty("-webkit-user-select")},u=()=>{c(),E?.(l)};le.current=c,r.addEventListener("pointermove",d),r.addEventListener("pointerup",u),r.addEventListener("pointercancel",u)},onKeyDown:e=>{if("ArrowLeft"!==e.key&&"ArrowRight"!==e.key)return;e.preventDefault();const t="rtl"===getComputedStyle(e.currentTarget).direction,r="start"===J===t?-1:1;(e=>{const t=ie.current;if(!t)return;const r=de(t.getBoundingClientRect().width+e);z?.(r),E?.(r)})(("ArrowRight"===e.key?16:-16)*r)}}):null]})});