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
package/README.md CHANGED
@@ -21,8 +21,8 @@ You install one package, add one line to your CSS, and import components. There
21
21
  - **Accessible by construction** — real roles, labels, focus management and keyboard support, not `div`s with click handlers.
22
22
  - **Dark mode with no work** — follows the system, and can be forced either way per subtree.
23
23
  - **A design language, not a theme file** — a translucent acrylic surface with a hairline edge, one deliberate motion signature, and shadows that are opt-in.
24
- - **ESM only**, TypeScript declarations included, and genuinely tree-shakeable — every component compiles to its own module, and importing one costs about what one costs. A `Button` is ~5 kB gzipped including its Base UI parts, a `Chip` is ~3 kB, and a twelve-component app is ~67 kB; the whole library, all one hundred and seventeen exports at once, is ~207 kB.
25
- - **One runtime dependency.** React 18 or 19, Node.js 18 or later.
24
+ - **ESM only**, TypeScript declarations included, and genuinely tree-shakeable — every component compiles to its own module, and importing one costs about what one costs. A `Button` is ~5 kB gzipped including its Base UI parts, a `Chip` is ~3 kB, and a twelve-component app is ~67 kB; the whole library, all one hundred and twenty-six exports at once, is ~215 kB.
25
+ - **Two runtime dependencies** — Base UI, and `highlight.js`, which only [CodeBlock](https://neba.cdget.com/components/display/code-block) reaches and only through a dynamic import, so it never lands in a bundle that did not ask for it. React 18 or 19, Node.js 18 or later.
26
26
 
27
27
  ## Documentation
28
28
 
@@ -115,7 +115,7 @@ Call it once, at module scope, before your first render. Then a `locale` prop tr
115
115
  <Dialog locale="ko" title="설정" showClose />
116
116
  ```
117
117
 
118
- A registered language costs about 1.7 kB gzipped and you pay only for the ones you name. Tags are matched by script, then by region, then by language — registering `ko` answers `ko-KR`, and `zhHans` registered as `zh-hans` answers `zh-CN` and a bare `zh`. Available: `ko`, `ja`, `zhHans`, `zhHant`, `es`, `pt`, `fr`, `de`, `it`, `nl`, `pl`, `ru`, `tr`, `ar`, `hi`, `id`, `vi`, `th`, each also its own entry point (`neba/locales/ko`).
118
+ A registered language costs about 1.9 kB gzipped and you pay only for the ones you name. Tags are matched by script, then by region, then by language — registering `ko` answers `ko-KR`, and `zhHans` registered as `zh-hans` answers `zh-CN` and a bare `zh`. Available: `ko`, `ja`, `zhHans`, `zhHant`, `es`, `pt`, `fr`, `de`, `it`, `nl`, `pl`, `ru`, `tr`, `ar`, `hi`, `id`, `vi`, `th`, each also its own entry point (`neba/locales/ko`).
119
119
 
120
120
  Anything the platform already knows — month names, weekday names, AM/PM, number and date formats — comes from `Intl` and needs no registration. And every string a component invents also has a prop that overrides it, so a language Neba does not carry is never a dead end.
121
121
 
@@ -142,19 +142,19 @@ Placement props are logical, not physical — `start`/`end` rather than `left`/`
142
142
 
143
143
  **Inputs** — Button, IconButton, ButtonGroup, SegmentedButton, FloatingActionButton (with FloatingAction), TextField, NumberField, OtpField, Select, Combobox, Checkbox, RadioGroup, Switch, Slider, Rating, Menu (with submenus, checkbox and radio items), ContextMenu, FilePicker, Pagination, BottomNavigation, FloatingBottomNavigation, ColorPicker, DatePicker, TimePicker, DateTimePicker, DateRangePicker
144
144
 
145
- **Surfaces** — Box, Card, Accordion, Collapsible, Tabs, Carousel, Toolbar, Pill, Spoiler, ChatBubble, Drawer, Popover, Mockup, WindowPane
145
+ **Surfaces** — Box, Card, Accordion, Collapsible, Tabs, Carousel, Toolbar, Pill, Spoiler, HowToSteps, ChatBubble, Drawer, Popover, Mockup, WindowPane
146
146
 
147
- **Display** — Typography, TextLink, Blockquote, Highlight, Divider, Chip, Badge, Avatar, Icon, Shortcut, List, Table, DataTable, Timeline, Breadcrumb, TreeView
147
+ **Display** — Typography, TextLink, Blockquote, Highlight, Divider, Chip, Badge, Avatar, AppLogo, Icon, Shortcut, List, Table, DataTable, CodeBlock, Timeline, Breadcrumb, TreeView
148
148
 
149
149
  **Charts** — Statistic, Sparkline, LineChart, AreaChart, BarChart, PieChart, ScatterChart, TimelineChart, HeatmapChart
150
150
 
151
151
  **Feedback** — Alert, Dialog, Toast, Tooltip, Overlay, Skeleton, Empty, ProgressLinear, ProgressCircular, ProgressBox
152
152
 
153
- **Layout** — Container, Grid (with GridContainer), Panes, AspectRatio, ScrollZone
153
+ **Layout** — PageLayout (with Header, Footer and Sidebar), Container, Grid (with GridContainer), Panes, AspectRatio, ScrollZone
154
154
 
155
155
  **Transitions** — AnimateFade, AnimateGrow, AnimateZoom, AnimateSlide, AnimateRotate, AnimateBlink, AnimateAppear, AnimateTyping, AnimateLighting, AnimateMarquee, AnimateHeadline
156
156
 
157
- **Recently added** — ScrollZone, FloatingBottomNavigation, WindowPane, Collapsible, Rating, BottomNavigation, FloatingActionButton, the charts (Sparkline, LineChart, AreaChart, BarChart, PieChart, ScatterChart, TimelineChart, HeatmapChart), DataTable, Empty, Mockup, the eleven `Animate*` wrappers, ColorPicker, Drawer, Popover, Skeleton, AspectRatio
157
+ **Recently added** — CodeBlock, HowToSteps, ScrollZone, FloatingBottomNavigation, WindowPane, Collapsible, Rating, BottomNavigation, FloatingActionButton, the charts (Sparkline, LineChart, AreaChart, BarChart, PieChart, ScatterChart, TimelineChart, HeatmapChart), DataTable, Empty, Mockup, the eleven `Animate*` wrappers, ColorPicker, Drawer, Popover, Skeleton, AspectRatio
158
158
 
159
159
  Each one has its own page — live previews, every prop, and the variations worth seeing — under [**All components**](https://neba.cdget.com/components/).
160
160
 
@@ -0,0 +1,148 @@
1
+ import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
3
+ import type { NebaColor, NebaElevation, NebaSize, NebaVariant } from '../../types.js';
4
+ /**
5
+ * How the artwork is *framed*, which is the one question this component exists
6
+ * to answer.
7
+ *
8
+ * - `bare` — drawn as it was given, at the height `size` asks for and whatever
9
+ * width that comes to. No plate, no crop, no padding. This is the default,
10
+ * and it is the only one that is correct for a logo that was drawn with its
11
+ * own background, its own margin, or the product's name set into it.
12
+ * - `app` — an app icon: a filled tile with the artwork inset in it and the
13
+ * corners cut off. What a mark that was drawn as a bare glyph needs before it
14
+ * can sit next to anything else.
15
+ * - `circle` — the same tile, round. For the products whose icon is a disc.
16
+ *
17
+ * There is no `square`. A tile with the corners left on is the one shape the
18
+ * design language does not draw, and an `app` icon at a small size is already
19
+ * so close to a square that a fourth value would be a value nobody could see.
20
+ */
21
+ export type AppLogoShape = 'bare' | 'app' | 'circle';
22
+ export interface AppLogoProps extends Omit<React.ComponentPropsWithoutRef<'a'>, 'color' | 'href'> {
23
+ /**
24
+ * The artwork, as an image.
25
+ *
26
+ * Beaten by `children`, so a project that inlines its SVG and a project that
27
+ * links a PNG use the same component. A logo file very often has the
28
+ * product's name set into it — that is what `shape="bare"` is the default
29
+ * for, since it keeps the file's own aspect ratio instead of squeezing a
30
+ * wordmark into a square, and why `name` is read out rather than drawn a
31
+ * second time beside it.
32
+ */
33
+ src?: string;
34
+ /** Candidate images at other resolutions, as on any `<img>`. */
35
+ srcSet?: string;
36
+ /**
37
+ * What the artwork says for a reader who cannot see it. Defaults to `name`,
38
+ * which is almost always the right answer: a logo means the product.
39
+ */
40
+ alt?: string;
41
+ /**
42
+ * The product's name.
43
+ *
44
+ * One prop doing three jobs, as on Avatar: it names the artwork, it is drawn
45
+ * as the logotype when there is no artwork at all, and its initials are what
46
+ * a tile falls back to. It is what makes `<AppLogo name="Neba" />` — with no
47
+ * file, no icon and no markup — still a logo.
48
+ */
49
+ name?: string;
50
+ /** The initials on a tile, written out, for when the rule derived the wrong ones. */
51
+ initials?: string;
52
+ /**
53
+ * Draws the name beside the artwork, as the words half of a lockup.
54
+ *
55
+ * Off by default, because the common case is a file that already says the
56
+ * name. Turn it on for a bare mark — the icon in a header with the product
57
+ * next to it — and the name stops being read out twice: what is drawn *is*
58
+ * the accessible name from then on.
59
+ *
60
+ * Ignored when the name is already the whole logo, which is what a `bare`
61
+ * logo with no artwork is.
62
+ * @default false
63
+ */
64
+ showName?: boolean;
65
+ /** @default 'bare' */
66
+ shape?: AppLogoShape;
67
+ /**
68
+ * Weight of the tile behind the artwork. Nothing at all on `bare`, which
69
+ * draws no tile.
70
+ * @default 'solid'
71
+ */
72
+ variant?: NebaVariant;
73
+ /**
74
+ * How tall the mark is — the control heights, so a logo and the button beside
75
+ * it in a header are the same height. On `bare` only the height is set and
76
+ * the width is whatever the artwork's own proportions come to; on a tile both
77
+ * are, because a tile is square.
78
+ * @default 'md'
79
+ */
80
+ size?: NebaSize;
81
+ /** @default 'primary' */
82
+ color?: NebaColor;
83
+ /**
84
+ * Drop shadow depth. `0` (the default) is flat: an app icon is a sticker on
85
+ * the page, not a thing hovering over it.
86
+ * @default 0
87
+ */
88
+ elevation?: NebaElevation;
89
+ /**
90
+ * Insets the artwork from the tile's edge, the way an app icon's glyph is
91
+ * inset from its own corners. Turn it off for a mark that was drawn to fill
92
+ * the tile — a favicon, a photograph.
93
+ *
94
+ * No effect on `bare`, which has no tile to inset from, and none on a tile
95
+ * showing initials, which are sized by their own type scale.
96
+ * @default true
97
+ */
98
+ padded?: boolean;
99
+ /**
100
+ * An exact height for the mark, overriding `size`. A number is pixels.
101
+ *
102
+ * The one escape hatch this component needs: a brand's artwork is drawn at a
103
+ * height somebody chose, and rounding it to the nearest step of a ladder is
104
+ * how a logo ends up half a pixel off the type beside it.
105
+ */
106
+ height?: number | string;
107
+ /**
108
+ * Makes the whole lockup a link. A logo in a header is nearly always the way
109
+ * back to the front page, and a `<span>` inside an `<a>` the caller wrote is
110
+ * the same thing with one more element in it.
111
+ */
112
+ href?: string;
113
+ /** Anything else the `<img>` needs — `loading`, `decoding`, `crossOrigin`. */
114
+ imageProps?: Omit<React.ComponentPropsWithoutRef<'img'>, 'src' | 'srcSet' | 'alt'>;
115
+ /**
116
+ * Renders something other than a `<span>` — or than the `<a>` an `href` makes
117
+ * it. `render={<Link to="/" />}` for a router's own link, `render={<h1 />}`
118
+ * for the one page where the product's name is the page's heading.
119
+ */
120
+ render?: useRender.RenderProp;
121
+ /**
122
+ * The artwork, as markup. An inline `<svg>` is the usual one, and it is worth
123
+ * preferring to `src`: a mark that is part of the document takes the page's
124
+ * own colours, needs no second request, and cannot arrive late.
125
+ */
126
+ children?: React.ReactNode;
127
+ }
128
+ /**
129
+ * A product's mark, at a known size, that is never an empty box.
130
+ *
131
+ * Four things can be the mark and exactly one of them is at a time: markup
132
+ * handed to `children`, an image at `src`, the initials of `name` on a tile, or
133
+ * — with no tile to put them on — the name itself, set as the logotype. That
134
+ * last one is the point of the component: a product that has not drawn a logo
135
+ * yet still has a logo, and swapping it for the real file later is one prop.
136
+ *
137
+ * What it adds over an `<img>` is the framing. A mark drawn as a bare glyph and
138
+ * a mark drawn with its own background need opposite treatment, and which one a
139
+ * given file is cannot be worked out from the file — so `shape` is the decision
140
+ * a caller makes once, and everything else follows from it: `bare` keeps the
141
+ * artwork's own proportions and draws nothing behind it, `app` and `circle`
142
+ * inset it into a tile of the page's own colour.
143
+ *
144
+ * It carries no tagline and no version. A logo with a line of text under it is
145
+ * a logo next to a [Typography], and inventing a second spelling for that would
146
+ * give the library two of them.
147
+ */
148
+ export declare const AppLogo: React.ForwardRefExoticComponent<AppLogoProps & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,Fragment as r,jsxs as n}from"react/jsx-runtime";import*as t from"react";import{useRender as s}from"@base-ui/react/use-render";import{initialsOf as a}from"../../internal/initials.js";import{controlHeightClasses as l,controlSlots as i,controlSquareClasses as o,cx as m,gapClasses as d,hasContent as c,srOnlyClasses as u,surfaceClasses as x,toLength as f,transitionClasses as g}from"../../internal/styles.js";const h={xs:"text-[0.75rem]",sm:"text-[0.875rem]",md:"text-[1.0625rem]",lg:"text-[1.375rem]",xl:"text-[1.625rem]"},p={xs:"text-[0.75rem]",sm:"text-[0.875rem]",md:"text-[1.0625rem]",lg:"text-[1.3125rem]",xl:"text-[1.5625rem]"},v={xs:"rounded-[0.375rem]",sm:"rounded-[0.4375rem]",md:"rounded-[0.5625rem]",lg:"rounded-[0.6875rem]",xl:"rounded-[0.875rem]"},b={solid:[x,"text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[x,"border text-(--n-accent) bg-(--n-panel)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:"text-(--n-accent) bg-(--n-soft-press) [box-shadow:var(--n-elev)]"};export const AppLogo=/*@__PURE__*/t.forwardRef(function({src:t,srcSet:x,alt:w,name:j,initials:_,showName:N=!1,shape:y="bare",variant:k="solid",size:S="md",color:z="primary",elevation:A=0,padded:F=!0,height:L,href:P,imageProps:R,render:$,className:q,style:B,children:C,...D},E){const G="bare"!==y,H=c(C)?C:t?"image":null,I=G&&F,J=null===H&&!G,K=N&&!J&&c(j),M=w??j,O=_??(j?a(j):""),Q="image"===H&&!K&&c(M),T=J||Q,U=!T&&!K&&c(M),V=f(L),W=V?{height:V,width:G?V:void 0}:null,X=e("span",{"aria-hidden":!T||void 0,className:m("flex shrink-0 items-center justify-center overflow-hidden","font-semibold tracking-tight whitespace-nowrap",V?"":l[S],G?m(V?"":o[S],"circle"===y?"rounded-full":v[S],p[S],b[k]):m("w-auto text-(--neba-fg)",h[S]),"[&_svg]:w-auto [&_svg]:shrink-0",I?"[&_svg]:h-[72%] [&_svg]:max-w-[72%]":"[&_svg]:h-full [&_svg]:max-w-full",g),style:{...G?i(z,A,k):null,...W},children:"image"===H?e("img",{src:t,srcSet:x,alt:Q?M??"":"",className:m("w-auto object-contain",I?"h-[72%] max-w-[72%]":"h-full max-w-full"),...R}):H??(J?j:O)});return s({render:$??e(P?"a":"span",{}),ref:E,props:{href:P,className:m("inline-flex max-w-full min-w-0 items-center align-middle","text-(--neba-fg) no-underline select-none",d[S],P?"cursor-pointer rounded-(--neba-radius-sm)":"",P?"focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2":"",q),style:{"--n-ring":`var(--neba-${z}-ring)`,...B},children:n(r,{children:[X,K?e("span",{className:m("min-w-0 truncate font-semibold",h[S]),children:j}):null,U?e("span",{className:u,children:M}):null]}),...D}})});
@@ -0,0 +1,2 @@
1
+ export { AppLogo } from './AppLogo.js';
2
+ export type { AppLogoProps, AppLogoShape } from './AppLogo.js';
@@ -0,0 +1 @@
1
+ export{AppLogo}from"./AppLogo.js";
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as r from"react";import{Avatar as n}from"@base-ui/react/avatar";import{transitionProps as a}from"../../internal/animate.js";import{controlHeightClasses as o,controlSlots as s,controlSquareClasses as l,hasContent as i,srOnlyClasses as d,surfaceClasses as c,transitionClasses as m}from"../../internal/styles.js";const f={xs:"text-[0.5625rem]",sm:"text-[0.6875rem]",md:"text-[0.8125rem]",lg:"text-[1rem]",xl:"text-[1.1875rem]"},u={xs:"rounded-[0.375rem]",sm:"rounded-[0.4375rem]",md:"rounded-[0.5625rem]",lg:"rounded-[0.6875rem]",xl:"rounded-[0.875rem]"},x={solid:[c,"text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--n-elev)]"].join(" "),outline:[c,"border text-(--n-accent) bg-(--n-panel)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev)]"].join(" "),text:"text-(--n-accent) bg-(--n-soft-press) [box-shadow:var(--n-elev)]"},h="after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit]",v={solid:`${h} after:[box-shadow:var(--neba-plate-solid)]`,outline:`${h} after:[box-shadow:var(--neba-plate-glass)]`,text:""},p=["relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden","align-middle font-semibold tracking-wide whitespace-nowrap leading-none","[&_svg]:pointer-events-none [&_svg]:size-[55%]",m].join(" ");function g(){return t("svg",{viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":"true",children:[e("path",{d:"M12 12a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Z"}),e("path",{d:"M12 14.25c-4.28 0-7.75 2.42-7.75 5.4 0 .75.6 1.35 1.35 1.35h12.8c.75 0 1.35-.6 1.35-1.35 0-2.98-3.47-5.4-7.75-5.4Z"})]})}export const Avatar=/*@__PURE__*/r.forwardRef(function({src:r,srcSet:c,alt:m,name:h,initials:b,shape:j="circle",variant:w="text",size:y="md",color:N="primary",elevation:z=0,delay:C,imageProps:A,onLoadingStatusChange:B,transition:S,className:k,style:L,children:F,...M},R){const Z=h?function(e){const t=e.normalize("NFC").trim().split(/\s+/).filter(Boolean);return 0===t.length?"":((Array.from(t[0])[0]??"")+(t.length>1?Array.from(t[t.length-1])[0]??"":"")).toLocaleUpperCase()}(h):"",$=a(S),_=m??h,I=i(F)?F:(b??Z)||e(g,{}),P=i(F)||Boolean(b??Z),U=[p,o[y],l[y],f[y],"circle"===j?"rounded-full":u[y],x[w],v[w],$.className,k??""].filter(Boolean).join(" ");return t(n.Root,{ref:R,className:U,style:{...s(N,z,w),...$.style,...L},...M,children:[r?e(n.Image,{src:r,srcSet:c,alt:_??"",className:"size-full object-cover",onLoadingStatusChange:B,...A}):null,t(n.Fallback,{delay:r?C:void 0,className:"flex size-full items-center justify-center",children:[_&&P?e("span",{className:d,children:_}):null,e("span",{"aria-hidden":!(!_||!P)||void 0,className:"contents",children:I})]})]})});
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as n from"react";import{Avatar as r}from"@base-ui/react/avatar";import{transitionProps as a}from"../../internal/animate.js";import{initialsOf as o}from"../../internal/initials.js";import{controlHeightClasses as s,controlSlots as i,controlSquareClasses as l,hasContent as d,srOnlyClasses as c,surfaceClasses as m,transitionClasses as f}from"../../internal/styles.js";const u={xs:"text-[0.5625rem]",sm:"text-[0.6875rem]",md:"text-[0.8125rem]",lg:"text-[1rem]",xl:"text-[1.1875rem]"},x={xs:"rounded-[0.375rem]",sm:"rounded-[0.4375rem]",md:"rounded-[0.5625rem]",lg:"rounded-[0.6875rem]",xl:"rounded-[0.875rem]"},v={solid:[m,"text-(--n-on-solid) bg-(--n-fill)","[box-shadow:var(--n-elev)]"].join(" "),outline:[m,"border text-(--n-accent) bg-(--n-panel)","[border-color:var(--n-line)]","[box-shadow:var(--n-elev)]"].join(" "),text:"text-(--n-accent) bg-(--n-soft-press) [box-shadow:var(--n-elev)]"},h="after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit]",p={solid:`${h} after:[box-shadow:var(--neba-plate-solid)]`,outline:`${h} after:[box-shadow:var(--neba-plate-glass)]`,text:""},g=["relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden","align-middle font-semibold tracking-wide whitespace-nowrap leading-none","[&_svg]:pointer-events-none [&_svg]:size-[55%]",f].join(" ");function b(){return t("svg",{viewBox:"0 0 24 24",fill:"currentColor","aria-hidden":"true",children:[e("path",{d:"M12 12a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Z"}),e("path",{d:"M12 14.25c-4.28 0-7.75 2.42-7.75 5.4 0 .75.6 1.35 1.35 1.35h12.8c.75 0 1.35-.6 1.35-1.35 0-2.98-3.47-5.4-7.75-5.4Z"})]})}export const Avatar=/*@__PURE__*/n.forwardRef(function({src:n,srcSet:m,alt:f,name:h,initials:j,shape:w="circle",variant:y="text",size:N="md",color:z="primary",elevation:S=0,delay:k,imageProps:B,onLoadingStatusChange:C,transition:A,className:L,style:M,children:R,...Z},$){const _=h?o(h):"",F=a(A),I=f??h,P=d(R)?R:(j??_)||e(b,{}),q=d(R)||Boolean(j??_),D=[g,s[N],l[N],u[N],"circle"===w?"rounded-full":x[N],v[y],p[y],F.className,L??""].filter(Boolean).join(" ");return t(r.Root,{ref:$,className:D,style:{...i(z,S,y),...F.style,...M},...Z,children:[n?e(r.Image,{src:n,srcSet:m,alt:I??"",className:"size-full object-cover",onLoadingStatusChange:C,...B}):null,t(r.Fallback,{delay:n?k:void 0,className:"flex size-full items-center justify-center",children:[I&&q?e("span",{className:c,children:I}):null,e("span",{"aria-hidden":!(!I||!q)||void 0,className:"contents",children:P})]})]})});
@@ -1 +1 @@
1
- import{jsx as e,Fragment as t,jsxs as a}from"react/jsx-runtime";import*as n from"react";import{useRender as i}from"@base-ui/react/use-render";import{barMinHeightClasses as r,BottomNavigationContext as l}from"../../internal/bottom-navigation.js";import{cx as o,hasContent as s,iconSizeClasses as d,metaTextClasses as c,paddingXClasses as m,radiusClasses as u,srOnlyClasses as p,surfaceClasses as f,surfaceSlots as g,transitionClasses as b}from"../../internal/styles.js";const v={solid:[f,"text-(--neba-fg) bg-(--n-panel-hover)","[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"},x={static:"",sticky:"sticky bottom-0 z-20",fixed:"fixed inset-x-0 bottom-0 z-30"},h={default:{xs:"p-1",sm:"p-1",md:"p-1.5",lg:"p-2",xl:"p-2.5"},compact:{xs:"p-0.5",sm:"p-0.5",md:"p-1",lg:"p-1",xl:"p-1.5"}},y={xs:"gap-0.5",sm:"gap-0.5",md:"gap-1",lg:"gap-1",xl:"gap-1.5"};export const BottomNavigation=/*@__PURE__*/n.forwardRef(function({variant:t="outline",size:a="md",color:s="primary",density:d="default",elevation:c=0,value:m,defaultValue:p=null,onValueChange:f,position:y="fixed",labels:w="all",divider:N=!0,safeArea:z=!0,disabled:j=!1,label:k,render:C,className:B,style:R,children:V,..._},A){const[D,F]=n.useState(p),I=void 0!==m,M=I?m:D,P=n.useCallback(e=>{I||F(e),f?.(e)},[I,f]),S=n.useMemo(()=>({value:M??null,change:P,size:a,density:d,labels:w,disabled:j,floating:!1}),[M,P,a,d,w,j]),q=o("w-full min-w-0","static"===y?u[a]:"",v[t],"outline"===t&&"static"===y?"border [border-color:var(--n-line)]":"",N?"border-t [border-color:var(--n-line)]":"",x[y],z?"pb-[env(safe-area-inset-bottom)]":"",b,B);return i({render:C??e("nav",{}),ref:A,props:{"aria-label":k,className:q,style:{...g(s,c),...R},children:e(l.Provider,{value:S,children:e("div",{className:o("flex w-full items-stretch",r[a],h[d][a]),children:V})}),..._}})});export const BottomNavigationItem=/*@__PURE__*/n.forwardRef(function({value:i,icon:r,href:f,disabled:g=!1,className:v,children:x,onClick:h,...w},N){const z=n.useContext(l),j=g||z.disabled,k=null!==z.value&&z.value===i,C="all"===z.labels||"selected"===z.labels&&k,B=o("flex min-w-0 flex-col items-center justify-center py-1.5",z.floating?o("relative z-10",m[z.density][z.size],"rounded-full"):o("flex-1 px-1",u[z.size]),y[z.size],"[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",b,"focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:[outline-offset:-2px]",j?"cursor-not-allowed text-(--neba-disabled-fg)":k?z.floating?"cursor-pointer font-medium text-(--n-accent)":"cursor-pointer font-medium text-(--n-accent) bg-(--n-soft) hover:bg-(--n-soft-hover)":"cursor-pointer text-(--neba-muted-fg) hover:text-(--neba-fg) hover:bg-(--n-panel-hover)",v),R=a(t,{children:[s(r)?e("span",{className:o("flex shrink-0 items-center justify-center",d[z.size]),children:r}):null,s(x)?z.floating?e("span",{"data-drawn":C?"":void 0,className:o("grid justify-items-center","[transition-property:grid-template-rows,grid-template-columns,opacity]","[transition-duration:var(--neba-duration)]","[transition-timing-function:var(--neba-ease)]","motion-reduce:[transition-duration:0ms]",C?"[grid-template-columns:1fr] [grid-template-rows:1fr] opacity-100":"[grid-template-columns:0fr] [grid-template-rows:0fr] opacity-0"),children:e("span",{className:o("min-h-0 min-w-0 truncate leading-tight",c[z.size]),children:x})}):e("span",{"data-drawn":C?"":void 0,className:C?o("max-w-full truncate leading-tight",c[z.size]):p,children:x}):null]}),V=e=>{j?e.preventDefault():(z.change(i),h?.(e))};return f?e("a",{ref:N,"data-nav-item":"",href:j?void 0:f,"aria-current":k?"page":void 0,"aria-disabled":j||void 0,className:B,onClick:V,...w,children:R}):e("button",{ref:N,"data-nav-item":"",type:"button",disabled:j,"aria-current":k?"page":void 0,className:B,onClick:V,...w,children:R})});
1
+ import{jsx as e,Fragment as t,jsxs as a}from"react/jsx-runtime";import*as n from"react";import{useRender as i}from"@base-ui/react/use-render";import{barMinHeightClasses as l,BottomNavigationContext as r}from"../../internal/bottom-navigation.js";import{cx as o,hasContent as s,iconSizeClasses as d,metaTextClasses as c,paddingXClasses as u,radiusClasses as m,srOnlyClasses as p,surfaceClasses as f,surfaceSlots as b,transitionClasses as g}from"../../internal/styles.js";const v={solid:[f,"text-(--neba-fg) bg-(--n-panel-hover)","[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"},x={static:"",sticky:"sticky bottom-0 z-20",fixed:"fixed inset-x-0 bottom-0 z-30"},h={default:{xs:"p-1",sm:"p-1",md:"p-1.5",lg:"p-2",xl:"p-2.5"},compact:{xs:"p-0.5",sm:"p-0.5",md:"p-1",lg:"p-1",xl:"p-1.5"}},y={xs:"gap-0.5",sm:"gap-0.5",md:"gap-1",lg:"gap-1",xl:"gap-1.5"};export const BottomNavigation=/*@__PURE__*/n.forwardRef(function({variant:t="outline",size:a="md",color:s="primary",density:d="default",elevation:c=0,value:u,defaultValue:p=null,onValueChange:f,position:y="fixed",labels:w="all",divider:N=!0,safeArea:z=!0,disabled:j=!1,label:k,render:C,className:B,style:R,children:V,..._},A){const[D,F]=n.useState(p),I=void 0!==u,M=I?u:D,P=n.useCallback(e=>{I||F(e),f?.(e)},[I,f]),S=n.useMemo(()=>({value:M??null,change:P,size:a,density:d,labels:w,disabled:j,floating:!1}),[M,P,a,d,w,j]),q=o("w-full min-w-0","static"===y?m[a]:"",v[t],"outline"===t&&"static"===y?"border [border-color:var(--n-line)]":"",N?"border-t [border-color:var(--n-line)]":"",x[y],z?"pb-[env(safe-area-inset-bottom)]":"",g,B);return i({render:C??e("nav",{}),ref:A,props:{"aria-label":k,className:q,style:{...b(s,c),...R},children:e(r.Provider,{value:S,children:e("div",{className:o("flex w-full items-stretch",l[a],h[d][a]),children:V})}),..._}})});export const BottomNavigationItem=/*@__PURE__*/n.forwardRef(function({value:i,icon:l,href:f,disabled:b=!1,className:v,children:x,onClick:h,...w},N){const z=n.useContext(r),j=b||z.disabled,k=null!==z.value&&z.value===i,C="all"===z.labels||"selected"===z.labels&&k,B=o("flex min-w-0 flex-col items-center justify-center py-1.5",z.floating?o("relative z-10",u[z.density][z.size],"rounded-full"):o("flex-1 px-1",m[z.size]),y[z.size],"[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",g,"focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:[outline-offset:-2px]",j?"cursor-not-allowed text-(--neba-disabled-fg)":k?z.floating?"cursor-pointer font-medium text-(--n-accent)":"cursor-pointer font-medium text-(--n-accent) bg-(--n-soft) hover:bg-(--n-soft-hover)":"cursor-pointer text-(--neba-muted-fg) hover:text-(--neba-fg) hover:bg-(--n-panel-hover)",v),R=a(t,{children:[s(l)?e("span",{className:o("flex shrink-0 items-center justify-center",d[z.size]),children:l}):null,s(x)?z.floating&&"selected"===z.labels?e("span",{"data-drawn":C?"":void 0,className:o("grid justify-items-center [grid-template-rows:1fr]","[transition-property:grid-template-columns,opacity]","[transition-duration:var(--neba-duration)]","[transition-timing-function:var(--neba-ease)]","motion-reduce:[transition-duration:0ms]",C?"[grid-template-columns:1fr] opacity-100":"[grid-template-columns:0fr] opacity-0"),children:e("span",{className:o("min-w-0 truncate leading-tight",c[z.size]),children:x})}):e("span",{"data-drawn":C?"":void 0,className:C?o("max-w-full truncate leading-tight",c[z.size]):p,children:x}):null]}),V=e=>{j?e.preventDefault():(z.change(i),h?.(e))};return f?e("a",{ref:N,"data-nav-item":"",href:j?void 0:f,"aria-current":k?"page":void 0,"aria-disabled":j||void 0,className:B,onClick:V,...w,children:R}):e("button",{ref:N,"data-nav-item":"",type:"button",disabled:j,"aria-current":k?"page":void 0,className:B,onClick:V,...w,children:R})});
@@ -0,0 +1,170 @@
1
+ import * as React from 'react';
2
+ import type { NebaColor, NebaDensity, NebaElevation, NebaSize } from '../../types.js';
3
+ export { registerLanguage } from '../../internal/highlight.js';
4
+ /**
5
+ * Which palette the block wears.
6
+ *
7
+ * The four house themes come first. `dark` is the default and is the only one
8
+ * that is not a preference: code has been read on a dark ground since
9
+ * terminals, and a block that matched the page would be the one element on it
10
+ * whose colours were chosen by something other than the code. `auto` is the
11
+ * opt-out, and `mono` has no hue in it at all.
12
+ *
13
+ * The eight after them are ports, kept at their published values. They exist
14
+ * because a code block is the one component whose colours a reader already has
15
+ * an opinion about: someone who writes in One Dark all day reads a Dracula
16
+ * block as a different product's documentation.
17
+ *
18
+ * The type is open on purpose. A theme is a set of `--n-code-*` custom
19
+ * properties under a `[data-code-theme]` selector and nothing else, so a
20
+ * consumer who writes one in their own stylesheet has a theme — with nothing to
21
+ * register, nothing to import, and no cost to anybody who did not.
22
+ */
23
+ export type CodeBlockTheme = 'dark' | 'light' | 'auto' | 'mono' | 'one-dark' | 'dracula' | 'monokai' | 'nord' | 'night-owl' | 'gruvbox' | 'github' | 'solarized-light';
24
+ export interface CodeBlockProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'title' | 'prefix' | 'children' | 'onCopy'> {
25
+ /**
26
+ * The code. Trailing whitespace is trimmed off the end of the block — a
27
+ * template literal is almost always written with a newline before its closing
28
+ * backtick, and that newline is a blank line at the bottom of every block.
29
+ */
30
+ code: string;
31
+ /**
32
+ * What it is written in — `ts`, `bash`, `yml`, `dockerfile`. The common
33
+ * spellings and file extensions are understood, so a value copied off a
34
+ * fenced code block works as-is.
35
+ *
36
+ * A language nothing here knows is drawn plain rather than refused; teach it
37
+ * one with `registerLanguage`.
38
+ */
39
+ language?: string;
40
+ /**
41
+ * The palette. Independent of the page's light and dark, except on `auto`.
42
+ *
43
+ * Any other string works too, and is how a project brings its own: write
44
+ * `[data-code-theme='ours'] { --n-code-bg: …; --n-code-keyword: … }` in your
45
+ * own CSS and pass the name. Sixteen slots, five of which are derived from
46
+ * the other two and need no declaration.
47
+ * @default 'dark'
48
+ */
49
+ theme?: CodeBlockTheme | (string & {});
50
+ /** The type scale and the air around the code. @default 'md' */
51
+ size?: NebaSize;
52
+ /** @default 'primary' */
53
+ color?: NebaColor;
54
+ /** @default 'default' */
55
+ density?: NebaDensity;
56
+ /** Drop shadow depth. `0` (the default) is flat. @default 0 */
57
+ elevation?: NebaElevation;
58
+ /**
59
+ * Colours the code.
60
+ *
61
+ * Off, nothing is fetched at all: the grammar engine is behind a dynamic
62
+ * import, so a block that does not highlight costs no more than the text in
63
+ * it. On, the block draws plain on the first frame and colours itself when
64
+ * the grammar lands — a few milliseconds, and never a blank space where the
65
+ * code should be.
66
+ * @default true
67
+ */
68
+ highlight?: boolean;
69
+ /**
70
+ * The bar over the code, and the master switch for it: with it off there is
71
+ * no bar and none of `showLanguage`, `copyable` or `rawToggle` draws
72
+ * anything, whatever they say.
73
+ * @default true
74
+ */
75
+ toolbar?: boolean;
76
+ /**
77
+ * A name at the start of the bar — a file path, usually. Takes the place the
78
+ * language would otherwise have; both can be shown at once.
79
+ */
80
+ title?: React.ReactNode;
81
+ /** Names the language at the start of the bar. @default true */
82
+ showLanguage?: boolean;
83
+ /** The button that puts the code on the clipboard. @default true */
84
+ copyable?: boolean;
85
+ /**
86
+ * The toggle that drops the colouring and shows the characters as they are.
87
+ * Off by default: it is a second control on a bar that usually wants one, and
88
+ * it means nothing at all when `highlight` is off.
89
+ * @default false
90
+ */
91
+ rawToggle?: boolean;
92
+ /**
93
+ * Lines to mark: a tinted row with a rule down its leading edge.
94
+ *
95
+ * A number is one line, a string is a list of lines and ranges —
96
+ * `'4'`, `'4-9'`, `'1,4-9,12'` — and an array is any mix of the two. They
97
+ * are counted the way the gutter counts, so `startLine={286}` means
98
+ * `highlightLines={288}` marks the line the gutter calls 288.
99
+ *
100
+ * The tint is mixed from the theme's own ink rather than from the page's
101
+ * colour family, so it is legible on all twelve palettes and never the one
102
+ * colour on a Dracula block that nobody chose.
103
+ */
104
+ highlightLines?: number | string | Array<number | string>;
105
+ /** Numbers down the side. @default false */
106
+ lineNumbers?: boolean;
107
+ /** What the first line is numbered. @default 1 */
108
+ startLine?: number;
109
+ /**
110
+ * A shell prompt in front of every line that has something on it — `$`, `#`,
111
+ * `C:\>`, `>>>`.
112
+ *
113
+ * It is drawn but never *present*: the symbol is generated content, so it
114
+ * cannot be selected, cannot be found by find-in-page and is not what `copy`
115
+ * puts on the clipboard. A transcript stays a transcript and still pastes
116
+ * into a shell.
117
+ */
118
+ prompt?: string;
119
+ /** Wraps long lines instead of scrolling them sideways. @default false */
120
+ wrap?: boolean;
121
+ /**
122
+ * How tall the block may get before the code scrolls inside it. A number is
123
+ * pixels; any CSS length works. Left out, the block is as tall as the code.
124
+ */
125
+ maxHeight?: number | string;
126
+ /** The typeface. Defaults to the page's own monospace stack. */
127
+ fontFamily?: string;
128
+ /** Overrides the size the `size` ladder chose. A number is pixels. */
129
+ fontSize?: number | string;
130
+ /** Overrides the leading. A bare number is a ratio, as in CSS. */
131
+ lineHeight?: number | string;
132
+ /** Tracking. A number is pixels; `-0.01em` and the like work too. */
133
+ letterSpacing?: number | string;
134
+ /**
135
+ * Which language the block's own words are in — the copy button, the raw
136
+ * toggle, the name of the region. A BCP 47 tag such as `ko`, `pt-BR` or
137
+ * `zh-Hant`; unsupported tags fall back to English.
138
+ */
139
+ locale?: string;
140
+ /** The copy button's label. Defaults to the `locale`'s word for it. */
141
+ copyLabel?: string;
142
+ /** And what it says once the code is on the clipboard. */
143
+ copiedLabel?: string;
144
+ /** The raw toggle's label. */
145
+ rawLabel?: string;
146
+ /** Fires with the copied text once the clipboard has taken it. */
147
+ onCopy?: (code: string) => void;
148
+ }
149
+ /**
150
+ * A viewer for one line of code or a thousand.
151
+ *
152
+ * Everything it draws above the code is optional and off one prop each, because
153
+ * the same component has to be a snippet inside a sentence — no bar, no
154
+ * numbers, no chrome — and the full transcript at the top of a README, and
155
+ * those are the same block with different things turned on rather than two
156
+ * components.
157
+ *
158
+ * The colouring is highlight.js, and it is the one thing in the library reached
159
+ * through a dynamic import: the grammars are forty kilobytes and there are
160
+ * thirty-four of them, so they arrive as their own chunk, one language at a
161
+ * time, and only for a block that asked to be coloured. See
162
+ * `internal/highlight.ts` for why that is a `dependencies` entry rather than an
163
+ * optional peer.
164
+ *
165
+ * The block is rendered as lines rather than as one run of text — even with no
166
+ * numbers and no prompt — because a line is what carries a number, a prompt and
167
+ * a place in the scroll, and a component that switched between two renderings
168
+ * would have two sets of wrapping behaviour to keep in step.
169
+ */
170
+ export declare const CodeBlock: React.ForwardRefExoticComponent<CodeBlockProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as n from"react";import{CheckIcon as o,CodeIcon as l,CopyIcon as r}from"../../internal/icons.js";import{codeMessages as a,useMessages as i}from"../../internal/i18n.js";import{canonicalLanguage as s,highlight as c,plainLines as d}from"../../internal/highlight.js";import{cx as p,hasContent as m,metaTextClasses as u,radiusClasses as x,srOnlyClasses as f,surfaceSlots as g,toLength as h,transitionClasses as y}from"../../internal/styles.js";export{registerLanguage}from"../../internal/highlight.js";const v={xs:"text-[0.6875rem]/[1.55]",sm:"text-[0.75rem]/[1.6]",md:"text-[0.8125rem]/[1.65]",lg:"text-[0.875rem]/[1.7]",xl:"text-[1rem]/[1.7]"},b={default:{xs:"py-2",sm:"py-3",md:"py-3.5",lg:"py-4",xl:"py-5"},compact:{xs:"py-1.5",sm:"py-2",md:"py-2.5",lg:"py-3",xl:"py-3.5"}},w={default:{xs:"px-2",sm:"px-3",md:"px-3.5",lg:"px-4",xl:"px-5"},compact:{xs:"px-1.5",sm:"px-2",md:"px-2.5",lg:"px-3",xl:"px-3.5"}},N={default:{xs:"px-2.5 py-1",sm:"px-3.5 py-1",md:"px-4 py-1.5",lg:"px-4.5 py-2",xl:"px-5.5 py-2"},compact:{xs:"px-2 py-0.5",sm:"px-2.5 py-0.5",md:"px-3 py-1",lg:"px-3.5 py-1",xl:"px-4 py-1.5"}};export const CodeBlock=/*@__PURE__*/n.forwardRef(function({code:k,language:S,theme:j="dark",size:L="md",color:M="primary",density:T="default",elevation:_=0,highlight:C=!0,toolbar:F=!0,title:R,showLanguage:A=!0,copyable:z=!0,rawToggle:H=!1,highlightLines:K,lineNumbers:E=!1,startLine:$=1,prompt:D,wrap:B=!1,maxHeight:I,fontFamily:q,fontSize:G,lineHeight:J,letterSpacing:O,locale:P,copyLabel:Q,copiedLabel:U,rawLabel:V,onCopy:W,className:X,style:Y,...Z},ee){const te=i(a,P),ne=n.useMemo(()=>k.replace(/\r\n?/g,"\n").replace(/\s+$/,""),[k]),oe=s(S),[le,re]=n.useState(!1),[ae,ie]=n.useState(null),[se,ce]=n.useState(null),de=C&&!le&&null!==oe;n.useEffect(()=>{if(!de||!oe)return void ce(null);let e=!1;return c(ne,oe).then(t=>{e||ce(t)},()=>{e||ce(null)}),()=>{e=!0}},[ne,oe,de]);const pe=n.useMemo(()=>de&&se?se:d(ne),[de,se,ne]),me=`${String($+Math.max(pe.length-1,0)).length}ch`,ue=n.useRef(void 0);n.useEffect(()=>()=>clearTimeout(ue.current),[]);const xe=n.useMemo(()=>function(e){const t=new Set;if(void 0===e)return t;for(const n of Array.isArray(e)?e:[e])if("number"!=typeof n)for(const e of n.split(",")){const n=/^\s*(\d+)\s*(?:-\s*(\d+)\s*)?$/.exec(e);if(!n)continue;const o=Number(n[1]),l=void 0===n[2]?o:Number(n[2]);for(let e=Math.min(o,l);e<=Math.max(o,l);e+=1)t.add(e)}else Number.isFinite(n)&&t.add(Math.trunc(n));return t}(K),[K]),fe=n.useRef(null),ge=Q??te.copy,he=U??te.copied,ye=V??te.raw,ve=p("inline-flex shrink-0 cursor-pointer items-center gap-1 border-0 bg-transparent","px-1.5 py-1 text-(--n-code-dim) hover:text-(--n-code-fg) hover:bg-(--n-code-hover)",x.xs,u[L],"[&_svg]:pointer-events-none [&_svg]:size-[1.15em] [&_svg]:shrink-0",y,"focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-1"),be=m(R)?void 0:oe??te.code,we=e("div",{role:"region","aria-label":"string"==typeof R?R:be,tabIndex:0,onKeyDown:e=>{if("a"!==e.key&&"A"!==e.key)return;if(!e.metaKey&&!e.ctrlKey||e.altKey)return;const t=fe.current,n="undefined"==typeof window?null:window.getSelection();if(!t||!n)return;e.preventDefault();const o=document.createRange();o.selectNodeContents(t),n.removeAllRanges(),n.addRange(o)},className:p("min-h-0 overflow-auto",b[T][L],"focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:-outline-offset-2"),style:void 0===I?void 0:{maxHeight:h(I)},children:e("pre",{ref:fe,className:p("m-0 bg-transparent p-0 font-mono",B?"w-full":"w-max min-w-full"),children:pe.map((t,o)=>{const l=$+o;return e("div",{className:p("neba-code-line",w[T][L]),"data-line":E?l:void 0,"data-mark":xe.has(l)?"":void 0,"data-prompt":D&&t.length>0?D:void 0,children:e("code",{children:t.map((t,o)=>t.token?e("span",{className:t.token,children:t.text},o):e(n.Fragment,{children:t.text},o))})},o)})})});return t("div",{ref:ee,className:p("neba-code flex min-w-0 flex-col overflow-hidden",x[L],"border bg-(--n-code-bg) text-(--n-code-fg) [border-color:var(--n-code-rule)]","[box-shadow:var(--n-elev)]",y,X),"data-code-theme":j,"data-code-wrap":B?"true":void 0,style:{...g(M,_),"--n-code-gutter":me,...q?{fontFamily:q}:null,...void 0===G?null:{fontSize:h(G)},...void 0===J?null:{lineHeight:J},...void 0===O?null:{letterSpacing:h(O)},...Y},...Z,children:[F&&(A||z||H||m(R))?t("div",{className:p("flex min-w-0 items-center gap-1 border-b [border-color:var(--n-code-rule)]",N[T][L]),children:[m(R)?e("span",{className:p("min-w-0 truncate font-mono",u[L]),children:R}):null,A&&oe?e("span",{className:p("min-w-0 truncate font-mono tracking-wide text-(--n-code-dim) uppercase select-none",u[L]),children:oe}):null,e("span",{className:"flex-1"}),H&&C?e("button",{type:"button","aria-pressed":le,"aria-label":ye,title:ye,onClick:()=>re(e=>!e),className:p(ve,le?"text-(--n-code-fg) bg-(--n-code-hover)":""),children:e(l,{})}):null,z?t("button",{type:"button",onClick:async()=>{const e=await async function(e){try{if(navigator.clipboard?.writeText)return await navigator.clipboard.writeText(e),!0}catch{}try{const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly",""),t.style.cssText="position:fixed;top:0;left:0;opacity:0;pointer-events:none",document.body.append(t),t.select();const n=document.execCommand("copy");return t.remove(),n}catch{return!1}}(ne);clearTimeout(ue.current),ie(e),ue.current=setTimeout(()=>ie(null),2e3),e&&W?.(ne)},className:ve,children:[e(ae?o:r,{}),e("span",{children:null===ae?ge:ae?he:te.copyFailed})]}):null]}):null,e("div",{className:p("flex min-h-0 flex-col",v[L]),children:we}),e("span",{"aria-live":"polite",className:f,children:null===ae?"":ae?he:te.copyFailed})]})});
@@ -0,0 +1,2 @@
1
+ export { CodeBlock, registerLanguage } from './CodeBlock.js';
2
+ export type { CodeBlockProps, CodeBlockTheme } from './CodeBlock.js';
@@ -0,0 +1 @@
1
+ export{CodeBlock,registerLanguage}from"./CodeBlock.js";
@@ -97,6 +97,6 @@ export interface ColorPickerProps extends NebaStyleProps, Omit<React.ComponentPr
97
97
  *
98
98
  * There is no colour library under this. The conversions are in
99
99
  * `internal/color.ts`, which is a hundred lines of arithmetic — the whole
100
- * reason the package still has one runtime dependency.
100
+ * reason no colour library comes with it.
101
101
  */
102
102
  export declare const ColorPicker: React.ForwardRefExoticComponent<ColorPickerProps & React.RefAttributes<HTMLDivElement>>;
@@ -1 +1 @@
1
- import{jsx as e,jsxs as r,Fragment as a}from"react/jsx-runtime";import{Dialog as l}from"@base-ui/react/dialog";import{boxPaddingXClasses as n,boxPaddingYClasses as o}from"../box/Box.js";import{actionMessages as s,useMessages as i}from"../../internal/i18n.js";import{CloseIcon as d}from"../../internal/icons.js";import{hasContent as t,metaTextClasses as u,sheetBodyClasses as b,sheetHeaderGapClasses as m,sheetSectionGapClasses as c,sheetTitleClasses as f,surfaceClasses as x,surfaceSlots as p}from"../../internal/styles.js";const g={xs:"w-56",sm:"w-64",md:"w-80",lg:"w-96",xl:"w-[28rem]"},h={left:{xs:"rounded-r-(--neba-radius-xs)",sm:"rounded-r-(--neba-radius-sm)",md:"rounded-r-(--neba-radius-md)",lg:"rounded-r-(--neba-radius-lg)",xl:"rounded-r-(--neba-radius-xl)"},right:{xs:"rounded-l-(--neba-radius-xs)",sm:"rounded-l-(--neba-radius-sm)",md:"rounded-l-(--neba-radius-md)",lg:"rounded-l-(--neba-radius-lg)",xl:"rounded-l-(--neba-radius-xl)"},top:{xs:"rounded-b-(--neba-radius-xs)",sm:"rounded-b-(--neba-radius-sm)",md:"rounded-b-(--neba-radius-md)",lg:"rounded-b-(--neba-radius-lg)",xl:"rounded-b-(--neba-radius-xl)"},bottom:{xs:"rounded-t-(--neba-radius-xs)",sm:"rounded-t-(--neba-radius-sm)",md:"rounded-t-(--neba-radius-md)",lg:"rounded-t-(--neba-radius-lg)",xl:"rounded-t-(--neba-radius-xl)"}},v={left:"border-r",right:"border-l",top:"border-b",bottom:"border-t"},y={left:"flex-row justify-start",right:"flex-row justify-end",top:"flex-col justify-start",bottom:"flex-col justify-end"},w=[x,"relative flex flex-col overflow-hidden","text-(--neba-fg) bg-(--n-panel-press)","[border-color:var(--n-line)]","[outline:none]"].join(" "),j=["[transition:opacity_var(--neba-duration)_var(--neba-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" "),N=["fixed inset-0 z-50 bg-(--neba-scrim)","[backdrop-filter:blur(2px)]",j].join(" "),$="border-t [border-color:var(--n-line)]",_=["flex size-[1.6em] shrink-0 cursor-pointer items-center justify-center","rounded-full text-(--neba-muted-fg)","[&_svg]:size-[1.1em] [&_svg]:shrink-0","[transition:background-color_var(--neba-duration)_var(--neba-ease),color_var(--neba-duration)_var(--neba-ease)]","hover:bg-(--n-soft) hover:text-(--neba-fg)","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"].join(" ");export const DrawerClose=l.Close;export function Drawer({side:x="left",mode:k="overlay",size:C="md",color:z="primary",density:B="default",open:D,defaultOpen:O,onOpenChange:P,trigger:T,title:F,description:L,actions:R,dividers:V=!1,showClose:q,locale:A,closeLabel:E,extent:G,rounded:H=!0,modal:I=!0,dismissible:J=!0,className:K,style:M,children:Q,...S}){const U=i(s,A),W="overlay"===k,X="left"===x||"right"===x,Y=q??W,Z=n[B][C],ee=o[B][C],re=V?`${Z} ${ee}`:Z,ae=t(F)||t(L),le=t(R),ne=void 0===G?null:{[X?"width":"height"]:"number"==typeof G?`${G}px`:G},oe=[w,b[C],v[x],H?h[x][C]:"",W?"[box-shadow:var(--neba-shadow-3),var(--neba-plate-glass)]":"[box-shadow:var(--neba-plate-glass)]",W?j:"",X?`h-full max-w-full ${void 0===G?g[C]:""}`:"w-full "+(void 0===G?"max-h-[85%]":""),V?"":`${ee} ${c[C]}`,K??""].filter(Boolean).join(" "),se=W?l.Title:"h2",ie=W?l.Description:"p",de=r(a,{children:[ae||Y?r("div",{className:`flex shrink-0 items-start gap-3 ${re}`,children:[r("div",{className:`flex min-w-0 flex-1 flex-col ${m[C]}`,children:[t(F)?e(se,{className:`m-0 font-semibold ${f[C]}`,children:F}):null,t(L)?e(ie,{className:`m-0 text-(--neba-muted-fg) ${u[C]}`,children:L}):null]}),Y?W?e(l.Close,{"aria-label":E??U.close,className:_,children:e(d,{})}):e("button",{type:"button","aria-label":E??U.close,className:_,onClick:()=>P?.(!1),children:e(d,{})}):null]}):null,t(Q)?e("div",{className:["min-h-0 flex-1 overflow-y-auto overscroll-contain",re,V&&(ae||Y)?$:"",V?"":"py-1 -my-1"].filter(Boolean).join(" "),children:Q}):null,le?e("div",{className:["flex shrink-0 flex-wrap items-center justify-end gap-2",re,V?$:""].filter(Boolean).join(" "),children:R}):null]});return W?r(l.Root,{open:D,defaultOpen:O,modal:I,disablePointerDismissal:!J,onOpenChange:(e,r)=>{J||e||"escape-key"!==r.reason?P?.(e):r.cancel()},children:[T?e(l.Trigger,{render:T}):null,r(l.Portal,{children:[e(l.Backdrop,{className:`neba-portal ${N}`}),e(l.Viewport,{className:`neba-portal fixed inset-0 z-50 flex ${y[x]}`,children:e(l.Popup,{className:oe,style:{...p(z,3),...ne,...M},...S,children:de})})]})]}):D??O??1?e("div",{className:oe,style:{...p(z,0),...ne,...M},children:de}):null}
1
+ import{jsx as e,jsxs as r,Fragment as a}from"react/jsx-runtime";import{Dialog as l}from"@base-ui/react/dialog";import{boxPaddingXClasses as n,boxPaddingYClasses as o}from"../box/Box.js";import{actionMessages as s,useMessages as i}from"../../internal/i18n.js";import{CloseIcon as d}from"../../internal/icons.js";import{hasContent as t,metaTextClasses as u,sheetBodyClasses as b,sheetHeaderGapClasses as m,sheetSectionGapClasses as c,sheetTitleClasses as f,surfaceClasses as x,surfaceSlots as p}from"../../internal/styles.js";const g={xs:"w-56",sm:"w-64",md:"w-80",lg:"w-96",xl:"w-[28rem]"},h={left:{xs:"rounded-r-(--neba-radius-xs)",sm:"rounded-r-(--neba-radius-sm)",md:"rounded-r-(--neba-radius-md)",lg:"rounded-r-(--neba-radius-lg)",xl:"rounded-r-(--neba-radius-xl)"},right:{xs:"rounded-l-(--neba-radius-xs)",sm:"rounded-l-(--neba-radius-sm)",md:"rounded-l-(--neba-radius-md)",lg:"rounded-l-(--neba-radius-lg)",xl:"rounded-l-(--neba-radius-xl)"},top:{xs:"rounded-b-(--neba-radius-xs)",sm:"rounded-b-(--neba-radius-sm)",md:"rounded-b-(--neba-radius-md)",lg:"rounded-b-(--neba-radius-lg)",xl:"rounded-b-(--neba-radius-xl)"},bottom:{xs:"rounded-t-(--neba-radius-xs)",sm:"rounded-t-(--neba-radius-sm)",md:"rounded-t-(--neba-radius-md)",lg:"rounded-t-(--neba-radius-lg)",xl:"rounded-t-(--neba-radius-xl)"}},v={left:"border-r",right:"border-l",top:"border-b",bottom:"border-t"},y={left:"flex-row justify-start",right:"flex-row justify-end",top:"flex-col justify-start",bottom:"flex-col justify-end"},w=[x,"relative flex flex-col overflow-hidden","text-(--neba-fg) bg-(--n-panel-press)","[border-color:var(--n-line)]","[outline:none]"].join(" "),j=["[transition:opacity_var(--neba-duration)_var(--neba-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" "),N=["fixed inset-0 z-50 bg-(--neba-scrim)","[backdrop-filter:blur(2px)]",j].join(" "),$="border-t [border-color:var(--n-line)]",_=["flex size-[1.6em] shrink-0 cursor-pointer items-center justify-center","rounded-full text-(--neba-muted-fg)","[&_svg]:size-[1.1em] [&_svg]:shrink-0","[transition:background-color_var(--neba-duration)_var(--neba-ease),color_var(--neba-duration)_var(--neba-ease)]","hover:bg-(--n-soft) hover:text-(--neba-fg)","focus-visible:[outline:2px_solid_var(--n-ring)] focus-visible:outline-offset-2"].join(" ");export const DrawerClose=l.Close;export function Drawer({side:x="left",mode:k="overlay",size:C="md",color:z="primary",density:B="default",open:D,defaultOpen:O,onOpenChange:P,trigger:T,title:F,description:L,actions:R,dividers:V=!1,showClose:q,locale:A,closeLabel:E,extent:G,rounded:H=!0,modal:I=!0,dismissible:J=!0,className:K,style:M,children:Q,...S}){const U=i(s,A),W="overlay"===k,X="left"===x||"right"===x,Y=q??W,Z=n[B][C],ee=o[B][C],re=V?`${Z} ${ee}`:Z,ae=t(F)||t(L),le=t(R),ne=void 0===G?null:{[X?"width":"height"]:"number"==typeof G?`${G}px`:G},oe=[w,b[C],v[x],H?h[x][C]:"",W?"[box-shadow:var(--neba-shadow-3),var(--neba-plate-glass)]":"[box-shadow:var(--neba-plate-glass)]",W?j:"",X?`h-full max-w-full ${void 0===G?g[C]:""}`:"w-full "+(void 0===G?"max-h-[85%]":""),V?"":`${ee} ${c[C]}`,K??""].filter(Boolean).join(" "),se=W?l.Title:"h2",ie=W?l.Description:"p",de=r(a,{children:[ae||Y?r("div",{className:`flex shrink-0 items-start gap-3 ${re}`,children:[r("div",{className:`flex min-w-0 flex-1 flex-col ${m[C]}`,children:[t(F)?e(se,{className:`m-0 font-semibold ${f[C]}`,children:F}):null,t(L)?e(ie,{className:`m-0 text-(--neba-muted-fg) ${u[C]}`,children:L}):null]}),Y?W?e(l.Close,{"aria-label":E??U.close,className:_,children:e(d,{})}):e("button",{type:"button","aria-label":E??U.close,className:_,onClick:()=>P?.(!1),children:e(d,{})}):null]}):null,t(Q)?e("div",{className:["min-h-0 flex-1 overflow-y-auto overscroll-contain",re,V&&(ae||Y)?$:"",V?"":"py-1 -my-1"].filter(Boolean).join(" "),children:Q}):null,le?e("div",{className:["flex shrink-0 flex-wrap items-center justify-end gap-2",re,V?$:""].filter(Boolean).join(" "),children:R}):null]});return W?r(l.Root,{open:D,defaultOpen:O,modal:I,disablePointerDismissal:!J,onOpenChange:(e,r)=>{J||e||"escape-key"!==r.reason?P?.(e):r.cancel()},children:[T?e(l.Trigger,{render:T}):null,r(l.Portal,{children:[e(l.Backdrop,{className:`neba-portal ${N}`}),e(l.Viewport,{className:`neba-portal fixed inset-0 z-50 flex ${y[x]}`,children:e(l.Popup,{className:oe,style:{...p(z,3),...ne,...M},...S,children:de})})]})]}):D??O??!0?e("div",{className:oe,style:{...p(z,0),...ne,...M},children:de}):null}
@@ -0,0 +1,85 @@
1
+ import * as React from 'react';
2
+ import { useRender } from '@base-ui/react/use-render';
3
+ import type { NebaColor, NebaDensity, NebaElevation, NebaPosition, NebaSize, NebaVariant } from '../../types.js';
4
+ export interface FooterProps extends Omit<React.ComponentPropsWithoutRef<'footer'>, 'color' | 'title'> {
5
+ /**
6
+ * How the bar sits in the page's scroll. `static` — the default, and the
7
+ * opposite of [Header]'s — is what a footer is: the thing at the end of the
8
+ * document, reached by scrolling to it. `sticky` and `fixed` are for the bar
9
+ * that has to stay in reach — a form's save row, a cookie notice — and a
10
+ * [PageLayout] reserves the height a `fixed` one takes out of the flow.
11
+ * @default 'static'
12
+ */
13
+ position?: NebaPosition;
14
+ /**
15
+ * Weight of the sheet, said the way a *container* says it: the bar is never
16
+ * dyed, because what is on it arrives with colours of its own.
17
+ * @default 'outline'
18
+ */
19
+ variant?: NebaVariant;
20
+ /**
21
+ * The bar's scale — its gutter and the air above and below its content. As on
22
+ * Box, `size` here is the size of the *sheet*.
23
+ * @default 'md'
24
+ */
25
+ size?: NebaSize;
26
+ /** @default 'primary' */
27
+ color?: NebaColor;
28
+ /** @default 'default' */
29
+ density?: NebaDensity;
30
+ /** Drop shadow depth. `0` (the default) is flat. @default 0 */
31
+ elevation?: NebaElevation;
32
+ /**
33
+ * Draws a hairline along the top edge. On by default: a footer is the one
34
+ * sheet on the page with content directly above it and nothing below, so the
35
+ * line is the whole of what says the document ended.
36
+ * @default true
37
+ */
38
+ divider?: boolean;
39
+ /**
40
+ * Holds the content to a measure and centres it, while the sheet itself still
41
+ * spans the window. On the same ladder Container's own `maxWidth` uses.
42
+ * @default 'none'
43
+ */
44
+ maxWidth?: NebaSize | 'none';
45
+ /** The gutter and the air above and below. @default true */
46
+ padded?: boolean;
47
+ /**
48
+ * The name the bar is announced by. Worth writing when a page has more than
49
+ * one `<footer>` in it — an article's own and the site's.
50
+ */
51
+ label?: string;
52
+ /**
53
+ * Renders something other than a `<footer>`. Base UI's own escape hatch, and
54
+ * rarely what you want: at the top level of a document that tag is the
55
+ * `contentinfo` landmark, and it is what says "this is the site's own
56
+ * information" rather than "this is more of the article".
57
+ */
58
+ render?: useRender.RenderProp;
59
+ /**
60
+ * Everything in it. A footer's content is columns of links, a copyright line,
61
+ * a logo — all of it the caller's, none of it something a component could
62
+ * guess at, which is why this one has slots for nothing and space for
63
+ * anything.
64
+ */
65
+ children?: React.ReactNode;
66
+ }
67
+ /**
68
+ * The sheet at the end of a page.
69
+ *
70
+ * A real `<footer>`, which is the whole reason it is a component rather than a
71
+ * div: at the top level of a document that tag is the `contentinfo` landmark —
72
+ * the region a screen reader offers as "the site's own information" and a
73
+ * search engine reads the copyright, the address and the site map out of.
74
+ *
75
+ * It has no slots on purpose, which is the difference between it and [Header].
76
+ * A header's three regions are a fixed arrangement worth writing once; a
77
+ * footer's content is four columns on one site, one line on the next, and a
78
+ * component that guessed at the arrangement would be a component every second
79
+ * site fights. What it decides is the sheet: the surface, the gutter, the
80
+ * hairline that says the document ended, and whether it stays in reach.
81
+ *
82
+ * Inside a [PageLayout] it also registers itself, so a `fixed` footer's height
83
+ * is reserved rather than sitting on top of the last paragraph.
84
+ */
85
+ export declare const Footer: React.ForwardRefExoticComponent<FooterProps & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1 @@
1
+ import{jsx as e}from"react/jsx-runtime";import*as r from"react";import{useRender as t}from"@base-ui/react/use-render";import{boxPaddingXClasses as a,boxPaddingYClasses as o}from"../box/Box.js";import{PageLayoutContext as n}from"../../internal/page-layout.js";import{cx as s,surfaceClasses as i,surfaceSlots as l,transitionClasses as m}from"../../internal/styles.js";const d={solid:[i,"text-(--neba-fg) bg-(--n-panel-press)","[box-shadow:var(--n-elev),var(--neba-plate-solid)]"].join(" "),outline:[i,"text-(--neba-fg) bg-(--n-panel)","[box-shadow:var(--n-elev),var(--neba-plate-glass)]"].join(" "),text:"text-(--neba-fg) bg-transparent"},x={static:"",sticky:"sticky bottom-0 z-30",fixed:"fixed inset-x-0 bottom-0 z-40"},c={xs:"max-w-[30rem]",sm:"max-w-[40rem]",md:"max-w-[48rem]",lg:"max-w-[64rem]",xl:"max-w-[80rem]"};export const Footer=/*@__PURE__*/r.forwardRef(function({position:i="static",variant:f="outline",size:p="md",color:b="primary",density:u="default",elevation:v=0,divider:w=!0,maxWidth:g="none",padded:y=!0,label:j,render:h,className:k,style:z,children:N,...C},B){const F=r.useContext(n),{register:R}=F,W=r.useCallback(e=>{R("footer",e),"function"==typeof B?B(e):B&&(B.current=e)},[R,B]),q=s("w-full min-w-0",d[f],w?"border-t [border-color:var(--n-line)]":"",x[i],m,k);return t({render:h??e("footer",{}),ref:W,props:{"aria-label":j,className:q,style:{...l(b,v),...z},children:e("div",{className:s("w-full",y?s(a[u][p],o[u][p]):"","none"===g?"":s(c[g],"mx-auto")),children:N}),...C}})});
@@ -0,0 +1,2 @@
1
+ export { Footer } from './Footer.js';
2
+ export type { FooterProps } from './Footer.js';
@@ -0,0 +1 @@
1
+ export{Footer}from"./Footer.js";