plass-ui 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +169 -0
- package/README.md +2 -0
- package/dist/components/avatar/PlAvatar.js +1 -1
- package/dist/components/avatar-group/PlAvatarGroup.d.ts +47 -0
- package/dist/components/avatar-group/PlAvatarGroup.js +1 -0
- package/dist/components/avatar-group/index.d.ts +2 -0
- package/dist/components/avatar-group/index.js +1 -0
- package/dist/components/checkbox/PlCheckbox.js +1 -1
- package/dist/components/color-picker/PlColorPicker.d.ts +88 -0
- package/dist/components/color-picker/PlColorPicker.js +1 -0
- package/dist/components/color-picker/index.d.ts +2 -0
- package/dist/components/color-picker/index.js +1 -0
- package/dist/components/combobox/PlCombobox.js +1 -1
- package/dist/components/command-palette/PlCommandPalette.d.ts +83 -0
- package/dist/components/command-palette/PlCommandPalette.js +1 -0
- package/dist/components/command-palette/index.d.ts +2 -0
- package/dist/components/command-palette/index.js +1 -0
- package/dist/components/divider/PlDivider.js +1 -1
- package/dist/components/fieldset/PlFieldset.d.ts +35 -0
- package/dist/components/fieldset/PlFieldset.js +1 -0
- package/dist/components/fieldset/index.d.ts +2 -0
- package/dist/components/fieldset/index.js +1 -0
- package/dist/components/footer/PlFooter.d.ts +90 -0
- package/dist/components/footer/PlFooter.js +1 -0
- package/dist/components/footer/index.d.ts +2 -0
- package/dist/components/footer/index.js +1 -0
- package/dist/components/form/PlForm.d.ts +61 -0
- package/dist/components/form/PlForm.js +1 -0
- package/dist/components/form/index.d.ts +2 -0
- package/dist/components/form/index.js +1 -0
- package/dist/components/header/PlHeader.d.ts +124 -0
- package/dist/components/header/PlHeader.js +1 -0
- package/dist/components/header/index.d.ts +2 -0
- package/dist/components/header/index.js +1 -0
- package/dist/components/menubar/PlMenubar.d.ts +56 -0
- package/dist/components/menubar/PlMenubar.js +1 -0
- package/dist/components/menubar/index.d.ts +2 -0
- package/dist/components/menubar/index.js +1 -0
- package/dist/components/navigation-menu/PlNavigationMenu.d.ts +99 -0
- package/dist/components/navigation-menu/PlNavigationMenu.js +1 -0
- package/dist/components/navigation-menu/index.d.ts +2 -0
- package/dist/components/navigation-menu/index.js +1 -0
- package/dist/components/number-field/PlNumberField.js +1 -1
- package/dist/components/otp-field/PlOtpField.js +1 -1
- package/dist/components/page-layout/PlPageLayout.d.ts +139 -0
- package/dist/components/page-layout/PlPageLayout.js +1 -0
- package/dist/components/page-layout/index.d.ts +2 -0
- package/dist/components/page-layout/index.js +1 -0
- package/dist/components/radio-group/PlRadioGroup.js +1 -1
- package/dist/components/scroll-zone/PlScrollZone.d.ts +35 -15
- package/dist/components/scroll-zone/PlScrollZone.js +1 -1
- package/dist/components/select/PlSelect.js +1 -1
- package/dist/components/sidebar/PlSidebar.d.ts +141 -0
- package/dist/components/sidebar/PlSidebar.js +1 -0
- package/dist/components/sidebar/PlSidebarTrigger.d.ts +34 -0
- package/dist/components/sidebar/PlSidebarTrigger.js +1 -0
- package/dist/components/sidebar/index.d.ts +4 -0
- package/dist/components/sidebar/index.js +1 -0
- package/dist/components/switch/PlSwitch.js +1 -1
- package/dist/components/text-field/PlTextField.js +1 -1
- package/dist/components/text-link/PlTextLink.d.ts +11 -2
- package/dist/components/text-link/PlTextLink.js +1 -1
- package/dist/components/toggle/PlToggle.d.ts +55 -0
- package/dist/components/toggle/PlToggle.js +1 -0
- package/dist/components/toggle/PlToggleGroup.d.ts +48 -0
- package/dist/components/toggle/PlToggleGroup.js +1 -0
- package/dist/components/toggle/index.d.ts +4 -0
- package/dist/components/toggle/index.js +1 -0
- package/dist/components/transfer/PlTransfer.d.ts +55 -0
- package/dist/components/transfer/PlTransfer.js +1 -0
- package/dist/components/transfer/index.d.ts +2 -0
- package/dist/components/transfer/index.js +1 -0
- package/dist/css/avatar-group.css +2 -0
- package/dist/css/color-picker.css +2 -0
- package/dist/css/command-palette.css +2 -0
- package/dist/css/fieldset.css +2 -0
- package/dist/css/footer.css +2 -0
- package/dist/css/form.css +2 -0
- package/dist/css/header.css +2 -0
- package/dist/css/menubar.css +2 -0
- package/dist/css/navigation-menu.css +2 -0
- package/dist/css/page-layout.css +2 -0
- package/dist/css/sidebar.css +2 -0
- package/dist/css/toggle.css +2 -0
- package/dist/css/transfer.css +2 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +1 -1
- package/dist/internal/avatar-group.d.ts +25 -0
- package/dist/internal/avatar-group.js +2 -0
- package/dist/internal/color.d.ts +109 -0
- package/dist/internal/color.js +1 -0
- package/dist/internal/link.d.ts +18 -0
- package/dist/internal/link.js +1 -0
- package/dist/internal/page-layout.d.ts +140 -0
- package/dist/internal/page-layout.js +1 -0
- package/dist/internal/search.d.ts +31 -0
- package/dist/internal/search.js +1 -0
- package/dist/internal/styles.d.ts +9 -0
- package/dist/internal/styles.js +1 -1
- package/dist/styles.css +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassStyleProps } from '../../types.js';
|
|
3
|
+
/** One thing the palette can do. */
|
|
4
|
+
export interface PlCommandItem {
|
|
5
|
+
/** What identifies the command. */
|
|
6
|
+
value: string;
|
|
7
|
+
/** What the row says, and what the query is matched against. */
|
|
8
|
+
label: string;
|
|
9
|
+
/** A second line under it — where the command goes, or what it changes. */
|
|
10
|
+
description?: React.ReactNode;
|
|
11
|
+
/** A glyph before the label. */
|
|
12
|
+
icon?: React.ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* The keystroke that does the same thing, set at the end of the row. Written
|
|
15
|
+
* the way `PlHotKeys` writes them, so `Mod` resolves per platform. The palette
|
|
16
|
+
* **does not bind it** — the application does.
|
|
17
|
+
*/
|
|
18
|
+
shortcut?: string;
|
|
19
|
+
/**
|
|
20
|
+
* The heading this command sits under. Commands are drawn in the order they
|
|
21
|
+
* are given, and a heading is drawn each time the group changes — so a
|
|
22
|
+
* group's commands have to be listed together.
|
|
23
|
+
*/
|
|
24
|
+
group?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Extra words the query is matched against but that are never drawn — the
|
|
27
|
+
* name somebody else's product gives the same command, an abbreviation, the
|
|
28
|
+
* word a reader would have searched for.
|
|
29
|
+
*/
|
|
30
|
+
keywords?: readonly string[];
|
|
31
|
+
/** In the list but not runnable. */
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
/** What running it does. */
|
|
34
|
+
onSelect?: () => void;
|
|
35
|
+
}
|
|
36
|
+
export interface PlCommandPaletteProps extends Pick<PlassStyleProps, 'size' | 'color' | 'density'> {
|
|
37
|
+
/** Everything the palette can do. */
|
|
38
|
+
items: readonly PlCommandItem[];
|
|
39
|
+
/** Whether the palette is open. Use with `onOpenChange` for a controlled one. */
|
|
40
|
+
open?: boolean;
|
|
41
|
+
/** Whether it starts open, for an uncontrolled one. @default false */
|
|
42
|
+
defaultOpen?: boolean;
|
|
43
|
+
onOpenChange?: (open: boolean) => void;
|
|
44
|
+
/**
|
|
45
|
+
* Called when a command is run, after its own `onSelect`. The palette closes
|
|
46
|
+
* either way.
|
|
47
|
+
*/
|
|
48
|
+
onSelect?: (item: PlCommandItem) => void;
|
|
49
|
+
/**
|
|
50
|
+
* The keystroke that opens the palette, bound on the window. Written the way
|
|
51
|
+
* `PlHotKeys` writes them, so `Mod` is Command on a Mac and Control everywhere
|
|
52
|
+
* else. `false` binds nothing.
|
|
53
|
+
* @default 'Mod+K'
|
|
54
|
+
*/
|
|
55
|
+
shortcut?: string | false;
|
|
56
|
+
/** How wide the sheet may get. A number of pixels or any CSS length. */
|
|
57
|
+
width?: number | string;
|
|
58
|
+
/** How tall the list may get before it scrolls. @default 320 */
|
|
59
|
+
maxHeight?: number | string;
|
|
60
|
+
/** The placeholder in the field. @default 'Search commands' */
|
|
61
|
+
placeholder?: string;
|
|
62
|
+
/** The line where the rows would be, when nothing matched. @default 'No commands found' */
|
|
63
|
+
emptyMessage?: React.ReactNode;
|
|
64
|
+
/** The accessible name of the dialog, which has no visible title. @default 'Command palette' */
|
|
65
|
+
label?: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Everything an application can do, behind one field.
|
|
69
|
+
*
|
|
70
|
+
* The shape a keyboard-first product takes once it has more actions than a menu
|
|
71
|
+
* bar can hold: a reader types what they want instead of remembering where it
|
|
72
|
+
* was put.
|
|
73
|
+
*
|
|
74
|
+
* It is not a `PlMenu` — a menu is a short list in one place, and every row is
|
|
75
|
+
* visible before you look for it. It is not a `PlCombobox` either: what comes
|
|
76
|
+
* back is not a value, it is *something happening*.
|
|
77
|
+
*
|
|
78
|
+
* Base UI's Autocomplete owns the list — the highlight the pointer and the arrow
|
|
79
|
+
* keys share, `aria-activedescendant`, Enter running the highlighted row — and
|
|
80
|
+
* its Dialog owns the sheet, the scrim, the focus trap and returning the focus
|
|
81
|
+
* to wherever the reader was.
|
|
82
|
+
*/
|
|
83
|
+
export declare function PlCommandPalette({ items, open, defaultOpen, onOpenChange, onSelect, shortcut, width, maxHeight, placeholder, emptyMessage, label, size, color, density }: PlCommandPaletteProps): React.ReactElement;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{Autocomplete as s}from"@base-ui/react/autocomplete";import{Dialog as l}from"@base-ui/react/dialog";import{PlHotKeys as o}from"../hot-keys/PlHotKeys.js";import{searchHaystack as r,searchText as n}from"../../internal/search.js";import{controlTextLeadingClasses as i,cx as c,glassClasses as p,hasContent as d,metaTextClasses as m,radiusClasses as u,surfaceSlots as h,toLength as f}from"../../internal/styles.js";const x=/* @__PURE__ */["fixed inset-0 z-(--plass-z-portal) bg-(--plass-scrim)","[backdrop-filter:blur(2px)] [-webkit-backdrop-filter:blur(2px)]","[transition:opacity_var(--plass-duration)_var(--plass-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" "),g=/* @__PURE__ */[p,"relative flex w-full flex-col overflow-hidden","border text-(--plass-fg) bg-(--plass-glass-press)","[border-color:var(--plass-glass-line)]","[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]","[outline:none]","[transition:opacity_var(--plass-duration)_var(--plass-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" "),y={xs:"max-w-sm",sm:"max-w-md",md:"max-w-xl",lg:"max-w-2xl",xl:"max-w-3xl"},b={xs:"h-9",sm:"h-10",md:"h-12",lg:"h-14",xl:"h-16"},v={xs:"py-1",sm:"py-1.5",md:"py-2",lg:"py-2.5",xl:"py-3"},w={xs:"px-2.5",sm:"px-3",md:"px-3.5",lg:"px-4",xl:"px-5"},k=/* @__PURE__ */["flex cursor-pointer items-center gap-3 select-none","[transition:background-color_var(--plass-duration)_var(--plass-ease)]","data-[highlighted]:bg-(--p-soft) data-[highlighted]:text-(--p-accent)","data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50","data-[disabled]:saturate-[0.35]"].join(" ");function haystackOf(e){return r([e.label,e.group,...e.keywords??[]])}export function PlCommandPalette({items:r,open:p,defaultOpen:N=!1,onOpenChange:j,onSelect:C,shortcut:K="Mod+K",width:z,maxHeight:S=320,placeholder:_="Search commands",emptyMessage:L="No commands found",label:O="Command palette",size:P="md",color:E="primary",density:M="default"}){const[H,V]=t.useState(N),[D,F]=t.useState(""),I=p??H,R=t.useCallback(e=>{void 0===p&&V(e),j?.(e)},[p,j]);t.useEffect(()=>{if(!1===K)return;const onKeyDown=e=>{(function pressed(e,a){const t=a.toLowerCase().split("+"),s=t[t.length-1],l=new Set(t.slice(0,-1)),o=/mac|iphone|ipad/i.test("undefined"==typeof navigator?"":navigator.platform||navigator.userAgent)?e.metaKey:e.ctrlKey;return!(l.has("mod")!==o||l.has("shift")!==e.shiftKey||l.has("alt")!==e.altKey||!l.has("mod")&&l.has("ctrl")!==e.ctrlKey||!l.has("mod")&&l.has("meta")!==e.metaKey||e.key.toLowerCase()!==s)})(e,K)&&(e.preventDefault(),R(!0))};return window.addEventListener("keydown",onKeyDown),()=>window.removeEventListener("keydown",onKeyDown)},[K,R]);const A=t.useMemo(()=>r.map(haystackOf),[r]),B=t.useMemo(()=>{const e=n(D);return""===e?r:r.filter((a,t)=>A[t].includes(e))},[r,A,D]),T=f(z),W=f(S);return e(l.Root,{open:I,onOpenChange:e=>{e||F(""),R(e)},children:a(l.Portal,{children:[e(l.Backdrop,{className:c("plass-portal",x)}),e(l.Viewport,{className:"plass-portal fixed inset-0 z-(--plass-z-portal) flex justify-center p-4 pt-[12vh]",children:e(l.Popup,{"aria-label":O,className:c(g,u[P],i[P],void 0===T?y[P]:"","self-start"),style:{...h(E,3),...void 0===T?null:{maxWidth:T}},children:a(s.Root,{open:!0,mode:"list",items:B,filter:null,value:D,onValueChange:e=>F(e),itemToStringValue:e=>e.label,children:[e("div",{className:c("flex shrink-0 items-center border-b [border-color:var(--plass-glass-line)]",w[P]),children:e(s.Input,{autoFocus:!0,placeholder:_,className:c("min-w-0 flex-1 bg-transparent [font:inherit] text-inherit [outline:none]","placeholder:text-(--plass-muted-fg) caret-(--p-accent)","selection:bg-(--p-soft-press)",b[P])})}),e(s.List,{className:"min-h-0 flex-1 overflow-y-auto overscroll-contain p-1",style:{maxHeight:W},children:(l,r)=>a(t.Fragment,{children:[l.group&&l.group!==B[r-1]?.group?e("div",{role:"presentation",className:c(w[P],"pt-2 pb-1 font-medium text-(--plass-muted-fg)",m[P]),children:l.group}):null,a(s.Item,{index:r,value:l,disabled:l.disabled,onClick:()=>(e=>{e.disabled||(e.onSelect?.(),C?.(e),R(!1))})(l),className:c(k,u[P],w[P],v["compact"===M?"xs":P]),children:[d(l.icon)?e("span",{className:"flex h-[1lh] shrink-0 items-center [&_svg]:size-[1.15em]",children:l.icon}):null,a("span",{className:"flex min-w-0 flex-1 flex-col",children:[e("span",{className:"truncate",children:l.label}),d(l.description)?e("span",{className:c("truncate text-(--plass-muted-fg)",m[P]),children:l.description}):null]}),l.shortcut?e(o,{size:"xs",keys:l.shortcut,className:"shrink-0"}):null]})]},l.value)}),e(s.Empty,{className:c(w[P],"py-6 text-center text-(--plass-muted-fg)",m[P]),children:L})]})})})]})})}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{PlCommandPalette}from"./PlCommandPalette.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as t from"react";import{Separator as l}from"@base-ui/react/separator";import{metaTextClasses as o}from"../../internal/styles.js";const
|
|
1
|
+
"use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as t from"react";import{Separator as l}from"@base-ui/react/separator";import{metaTextClasses as a,toLength as o}from"../../internal/styles.js";const i="[border-color:var(--p-rule-color)]",s={horizontal:{start:["w-4 shrink-0","flex-1"],center:["flex-1","flex-1"],end:["flex-1","w-4 shrink-0"]},vertical:{start:["h-4 shrink-0","flex-1"],center:["flex-1","flex-1"],end:["flex-1","h-4 shrink-0"]}},n={xs:"gap-1.5",sm:"gap-2",md:"gap-3",lg:"gap-3.5",xl:"gap-4"};export const PlDivider=/* @__PURE__ */t.forwardRef(function PlDivider({orientation:t="horizontal",color:d,size:c="md",length:f,thickness:p,textAlign:h="center",className:m,style:u,children:x,...v},w){const b="vertical"===t,g=null!=x&&!1!==x&&""!==x,j={"--p-rule-color":d?`var(--plass-${d}-line)`:"var(--plass-border)","--p-rule":o(p)??"1px"},$=o(f),k={...j,...void 0===$?null:b?{height:$}:{width:$},...u};if(!g)return e(l,{ref:w,orientation:t,className:[b?"w-0 border-l [border-left-width:var(--p-rule)] "+(void 0===$?"self-stretch":""):"h-0 w-full border-t [border-top-width:var(--p-rule)]",i,m??""].filter(Boolean).join(" "),style:k,...v});const[N,y]=s[t][h],z=b?"w-0 border-l [border-left-width:var(--p-rule)]":"h-0 border-t [border-top-width:var(--p-rule)]";return r(l,{ref:w,orientation:t,"aria-label":"string"==typeof x?x:void 0,className:["flex items-center",b?"w-auto flex-col "+(void 0===$?"self-stretch":""):"w-full",n[c],m??""].filter(Boolean).join(" "),style:k,...v,children:[e("span",{"aria-hidden":"true",className:`${z} ${N} ${i}`}),e("span",{className:["shrink-0 whitespace-nowrap text-(--plass-muted-fg)",a[c],b?"[writing-mode:vertical-rl]":""].filter(Boolean).join(" "),children:x}),e("span",{"aria-hidden":"true",className:`${z} ${y} ${i}`})]})});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassSize } from '../../types.js';
|
|
3
|
+
export interface PlFieldsetProps extends Omit<React.ComponentPropsWithoutRef<'fieldset'>, 'color'> {
|
|
4
|
+
/**
|
|
5
|
+
* What the group is called.
|
|
6
|
+
*
|
|
7
|
+
* It becomes part of the accessible name of every control inside, so it has
|
|
8
|
+
* to be a phrase that still reads correctly in front of each of them —
|
|
9
|
+
* "Billing address", not "Where should we send it?".
|
|
10
|
+
*/
|
|
11
|
+
legend?: React.ReactNode;
|
|
12
|
+
/** A line under the legend. */
|
|
13
|
+
description?: React.ReactNode;
|
|
14
|
+
/** Disables every control inside at once, the way a `<fieldset>` always has. */
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
/** The type scale of the legend and the gap between the controls. @default 'md' */
|
|
17
|
+
size?: PlassSize;
|
|
18
|
+
children?: React.ReactNode;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A group of controls that answer one question together, with a name on it.
|
|
22
|
+
*
|
|
23
|
+
* It draws **no surface**, and that is deliberate: a group of fields is a
|
|
24
|
+
* *grouping* and not a sheet, and the sheet already exists — put this inside a
|
|
25
|
+
* `PlCard` or a `PlBox` when one is wanted. What it owns is the legend, the gap
|
|
26
|
+
* the controls stand at, and the one thing only a real `<fieldset>` can do:
|
|
27
|
+
* `disabled` reaches every control inside it, including ones a component three
|
|
28
|
+
* levels down rendered and never heard of it.
|
|
29
|
+
*
|
|
30
|
+
* The legend is a `<div>` pointed at by `aria-labelledby` rather than a
|
|
31
|
+
* `<legend>` — Base UI's decision, and the one that makes the group a normal
|
|
32
|
+
* flex container: a real rendered legend is lifted out of its fieldset's
|
|
33
|
+
* content box by every browser, so a `gap` would put no space under it at all.
|
|
34
|
+
*/
|
|
35
|
+
export declare const PlFieldset: React.ForwardRefExoticComponent<PlFieldsetProps & React.RefAttributes<HTMLFieldSetElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import*as l from"react";import{Fieldset as r}from"@base-ui/react/fieldset";import{cx as i,hasContent as t,metaTextClasses as a,sheetHeaderGapClasses as n,sheetSectionGapClasses as d,sheetTitleClasses as o}from"../../internal/styles.js";export const PlFieldset=/* @__PURE__ */l.forwardRef(function PlFieldset({legend:l,description:c,disabled:m=!1,size:f="md",className:p,children:u,...x},b){const h=t(l)||t(c);return s(r.Root,{ref:b,disabled:m,className:i("m-0 flex min-w-0 flex-col border-0 p-0",d[f],p),...x,children:[h?s(r.Legend,{className:i("flex min-w-0 flex-col p-0",n[f]),children:[t(l)?e("span",{className:i("font-semibold",o[f]),children:l}):null,t(c)?e("span",{className:i("text-(--plass-muted-fg)",a[f]),children:c}):null]}):null,u]})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{PlFieldset}from"./PlFieldset.js";
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import type { PlassColor, PlassDensity, PlassElevation, PlassPosition, PlassSize, PlassVariant } from '../../types.js';
|
|
4
|
+
/** How wide the content inside the sheet is allowed to get. */
|
|
5
|
+
export type PlFooterWidth = PlassSize | 'none';
|
|
6
|
+
export interface PlFooterProps extends Omit<React.ComponentPropsWithoutRef<'footer'>, 'color' | 'title'> {
|
|
7
|
+
/**
|
|
8
|
+
* How the bar sits in the page's scroll.
|
|
9
|
+
*
|
|
10
|
+
* `static` — the default, and the opposite of `PlHeader`'s — is what a footer
|
|
11
|
+
* is: the thing at the end of the document, reached by scrolling to it.
|
|
12
|
+
* `sticky` and `fixed` are for the bar that has to stay in reach — a form's
|
|
13
|
+
* save row, a cookie notice — and a `PlPageLayout` reserves the height a
|
|
14
|
+
* `fixed` one takes out of the flow.
|
|
15
|
+
* @default 'static'
|
|
16
|
+
*/
|
|
17
|
+
position?: PlassPosition;
|
|
18
|
+
/**
|
|
19
|
+
* What the sheet is made of, said the way a **container** says it: the bar is
|
|
20
|
+
* never dyed, because what is on it arrives with colours of its own.
|
|
21
|
+
* @default 'glass'
|
|
22
|
+
*/
|
|
23
|
+
variant?: PlassVariant;
|
|
24
|
+
/**
|
|
25
|
+
* The bar's scale — its gutter and the air above and below its content. As on
|
|
26
|
+
* `PlBox`, `size` here is the size of the *sheet*.
|
|
27
|
+
* @default 'md'
|
|
28
|
+
*/
|
|
29
|
+
size?: PlassSize;
|
|
30
|
+
/** @default 'primary' */
|
|
31
|
+
color?: PlassColor;
|
|
32
|
+
/** @default 'default' */
|
|
33
|
+
density?: PlassDensity;
|
|
34
|
+
/** Drop shadow depth. `0` — the default — is flat. @default 0 */
|
|
35
|
+
elevation?: PlassElevation;
|
|
36
|
+
/**
|
|
37
|
+
* Draws a hairline along the top edge. On by default: a footer is the one
|
|
38
|
+
* sheet on the page with content directly above it and nothing below, so the
|
|
39
|
+
* line is the whole of what says the document ended.
|
|
40
|
+
* @default true
|
|
41
|
+
*/
|
|
42
|
+
divider?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Holds the content to a measure and centres it, while the sheet itself still
|
|
45
|
+
* spans the window. The same ladder `PlContainer`'s `maxWidth` uses.
|
|
46
|
+
* @default 'none'
|
|
47
|
+
*/
|
|
48
|
+
maxWidth?: PlFooterWidth;
|
|
49
|
+
/** The gutter and the air above and below. @default true */
|
|
50
|
+
padded?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* The name the bar is announced by. Worth writing when a page has more than
|
|
53
|
+
* one `<footer>` in it — an article's own and the site's.
|
|
54
|
+
*/
|
|
55
|
+
label?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Renders something other than a `<footer>`. Base UI's own escape hatch, and
|
|
58
|
+
* rarely what you want: at the top level of a document that tag is the
|
|
59
|
+
* `contentinfo` landmark, and it is what says "this is the site's own
|
|
60
|
+
* information" rather than "this is more of the article".
|
|
61
|
+
*/
|
|
62
|
+
render?: useRender.RenderProp;
|
|
63
|
+
/**
|
|
64
|
+
* Everything in it. A footer's content is columns of links, a copyright line,
|
|
65
|
+
* a logo — all of it the caller's, none of it something a component could
|
|
66
|
+
* guess at, which is why this one has slots for nothing and space for
|
|
67
|
+
* anything.
|
|
68
|
+
*/
|
|
69
|
+
children?: React.ReactNode;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The sheet at the end of a page.
|
|
73
|
+
*
|
|
74
|
+
* A real `<footer>`, which is the whole reason it is a component rather than a
|
|
75
|
+
* `<div>`: at the top level of a document that tag is the `contentinfo`
|
|
76
|
+
* landmark — the region a screen reader offers as "the site's own information"
|
|
77
|
+
* and a search engine reads the copyright, the address and the site map out of.
|
|
78
|
+
*
|
|
79
|
+
* **It has no slots on purpose**, which is the difference between it and
|
|
80
|
+
* `PlHeader`. A header's three regions are a fixed arrangement worth writing
|
|
81
|
+
* once; a footer's content is four columns on one site and one line on the
|
|
82
|
+
* next, and a component that guessed at the arrangement would be a component
|
|
83
|
+
* every second site fights. What it decides is the sheet: the surface, the
|
|
84
|
+
* gutter, the hairline that says the document ended, and whether it stays in
|
|
85
|
+
* reach.
|
|
86
|
+
*
|
|
87
|
+
* Inside a `PlPageLayout` it also registers itself, so a `fixed` footer's
|
|
88
|
+
* height is reserved rather than sitting on top of the last paragraph.
|
|
89
|
+
*/
|
|
90
|
+
export declare const PlFooter: React.ForwardRefExoticComponent<PlFooterProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as e}from"react/jsx-runtime";import*as r from"react";import{useRender as t}from"@base-ui/react/use-render";import{PlPageLayoutContext as o}from"../../internal/page-layout.js";import{cx as a,sheetPaddingXClasses as s,sheetPaddingYClasses as i,sheetRestClasses as l,surfaceSlots as m,transitionClasses as n}from"../../internal/styles.js";const d=l,c={static:"",sticky:"sticky bottom-0 z-20",fixed:"fixed inset-x-0 bottom-0 z-30"},f={xs:"max-w-[30rem]",sm:"max-w-[40rem]",md:"max-w-[48rem]",lg:"max-w-[64rem]",xl:"max-w-[80rem]"};export const PlFooter=/* @__PURE__ */r.forwardRef(function PlFooter({position:l="static",variant:x="glass",size:u="md",color:p="primary",density:w="default",elevation:y=0,divider:b=!0,maxWidth:v="none",padded:g=!0,label:h,render:j,className:k,style:z,children:N,...C},F){const{register:P}=r.useContext(o),R=r.useCallback(e=>{P("footer",e),"function"==typeof F?F(e):F&&(F.current=e)},[P,F]),W=a("w-full min-w-0",d[x],b?"border-t [border-color:var(--plass-divider)]":"",c[l],n,k);return t({render:j??e("footer",{}),ref:R,props:{"aria-label":h,className:W,style:{...m(p,y),...z},children:e("div",{className:a("w-full",g?a(s[w][u],i[w][u]):"","none"===v?"":a(f[v],"mx-auto")),children:N}),...C}})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{PlFooter}from"./PlFooter.js";
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassSize } from '../../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* When a field decides whether it is valid.
|
|
5
|
+
*
|
|
6
|
+
* Base UI's own three, kept under its own spelling because they are what a
|
|
7
|
+
* caller will read about everywhere else and a nicer synonym would only be a
|
|
8
|
+
* word to translate back.
|
|
9
|
+
*/
|
|
10
|
+
export type PlFormValidationMode = 'onSubmit' | 'onBlur' | 'onChange';
|
|
11
|
+
/** Errors that came from somewhere else, keyed by the field's `name`. */
|
|
12
|
+
export type PlFormErrors = Record<string, string | string[]>;
|
|
13
|
+
export interface PlFormProps extends Omit<React.ComponentPropsWithoutRef<'form'>, 'onSubmit'> {
|
|
14
|
+
/**
|
|
15
|
+
* When a field validates.
|
|
16
|
+
*
|
|
17
|
+
* - `onSubmit` — on submit, and on every change afterwards. The default, and
|
|
18
|
+
* the only one that does not tell somebody their email is wrong while they
|
|
19
|
+
* are still typing it.
|
|
20
|
+
* - `onBlur` — when a field loses focus.
|
|
21
|
+
* - `onChange` — on every keystroke.
|
|
22
|
+
* @default 'onSubmit'
|
|
23
|
+
*/
|
|
24
|
+
validationMode?: PlFormValidationMode;
|
|
25
|
+
/**
|
|
26
|
+
* Errors from outside the browser's own validation — a server, a form action,
|
|
27
|
+
* a schema — keyed by the `name` of the field each belongs to. They are shown
|
|
28
|
+
* on the field, and cleared as soon as that field changes.
|
|
29
|
+
*/
|
|
30
|
+
errors?: PlFormErrors;
|
|
31
|
+
/**
|
|
32
|
+
* Called on a valid submit, with the form's values. The native submit event is
|
|
33
|
+
* prevented, so nothing navigates.
|
|
34
|
+
*/
|
|
35
|
+
onSubmit?: (values: Record<string, unknown>) => void;
|
|
36
|
+
/**
|
|
37
|
+
* The gap between the form's children. A form is a stack, and this is which
|
|
38
|
+
* rung of the ladder it stacks on.
|
|
39
|
+
* @default 'md'
|
|
40
|
+
*/
|
|
41
|
+
size?: PlassSize;
|
|
42
|
+
children?: React.ReactNode;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A `<form>` that knows which of its fields is wrong.
|
|
46
|
+
*
|
|
47
|
+
* On its own, a page of `PlTextField`s validates one field at a time and a
|
|
48
|
+
* failed submit leaves the reader to find the red one. What this adds is the
|
|
49
|
+
* part that has to be owned *above* the fields: a submit collects every field's
|
|
50
|
+
* validity at once, focuses the first one that failed, and `errors` puts a
|
|
51
|
+
* server's answer back on the field it belongs to rather than in a banner at
|
|
52
|
+
* the top.
|
|
53
|
+
*
|
|
54
|
+
* It is **not a form library**. There is no schema, no resolver and no field
|
|
55
|
+
* array here — a project that wants those keeps them and hands the result to
|
|
56
|
+
* `errors`, which is the seam this is built around.
|
|
57
|
+
*
|
|
58
|
+
* It draws no surface either. A form is a stack of controls, and the sheet it
|
|
59
|
+
* sits on is a `PlCard` or a `PlBox` when one is wanted.
|
|
60
|
+
*/
|
|
61
|
+
export declare const PlForm: React.ForwardRefExoticComponent<PlFormProps & React.RefAttributes<HTMLFormElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as r}from"react/jsx-runtime";import*as o from"react";import{Form as e}from"@base-ui/react/form";import{cx as m,sheetSectionGapClasses as t}from"../../internal/styles.js";export const PlForm=/* @__PURE__ */o.forwardRef(function PlForm({validationMode:o="onSubmit",errors:i,onSubmit:s,size:a="md",className:n,children:l,...c},f){return r(e,{ref:f,validationMode:o,errors:i,onFormSubmit:r=>s?.(r),className:m("flex flex-col",t[a],n),...c,children:l})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{PlForm}from"./PlForm.js";
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import type { PlassAlign, PlassColor, PlassDensity, PlassElevation, PlassPosition, PlassSize, PlassVariant } from '../../types.js';
|
|
4
|
+
/** How wide the row inside the bar is allowed to get. */
|
|
5
|
+
export type PlHeaderWidth = PlassSize | 'none';
|
|
6
|
+
export interface PlHeaderProps extends Omit<React.ComponentPropsWithoutRef<'header'>, 'color' | 'title'> {
|
|
7
|
+
/**
|
|
8
|
+
* The leading slot: the logo, the product's name, the thing that is the same
|
|
9
|
+
* on every page.
|
|
10
|
+
*
|
|
11
|
+
* It is a slot rather than the first of `children` because the three regions
|
|
12
|
+
* of a bar are laid out against each other — the middle can only be centred
|
|
13
|
+
* in the bar if the two ends are measured — and a caller writing three
|
|
14
|
+
* wrappers by hand is a caller whose header drifts from the next one.
|
|
15
|
+
*/
|
|
16
|
+
brand?: React.ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* The trailing slot: the account menu, the theme switch, the call to action.
|
|
19
|
+
* Laid out end-aligned, so a row of buttons needs no wrapper of its own.
|
|
20
|
+
*/
|
|
21
|
+
actions?: React.ReactNode;
|
|
22
|
+
/**
|
|
23
|
+
* Where the middle slot sits.
|
|
24
|
+
*
|
|
25
|
+
* - `start` — packed against the brand, taking whatever is left. The
|
|
26
|
+
* arrangement of an application's bar, and the default.
|
|
27
|
+
* - `center` — centred in the bar itself, not in the space left over. The two
|
|
28
|
+
* ends are given equal shares for this, so the middle stays on the bar's
|
|
29
|
+
* own midline however wide the brand is.
|
|
30
|
+
* - `end` — packed against the actions.
|
|
31
|
+
* @default 'start'
|
|
32
|
+
*/
|
|
33
|
+
align?: PlassAlign;
|
|
34
|
+
/**
|
|
35
|
+
* How the bar sits in the page's scroll, spelled the way CSS spells it.
|
|
36
|
+
*
|
|
37
|
+
* `sticky` — the default — holds it against the top of the window once the
|
|
38
|
+
* page has scrolled to it, while leaving it in the flow so nothing has to be
|
|
39
|
+
* padded out of its way. `fixed` takes it out of the flow entirely, which a
|
|
40
|
+
* `PlPageLayout` answers by reserving its height. `static` lets it scroll
|
|
41
|
+
* away.
|
|
42
|
+
* @default 'sticky'
|
|
43
|
+
*/
|
|
44
|
+
position?: PlassPosition;
|
|
45
|
+
/**
|
|
46
|
+
* What the sheet is made of, said the way a **container** says it: the bar is
|
|
47
|
+
* never dyed, because what is on it arrives with colours of its own.
|
|
48
|
+
* @default 'glass'
|
|
49
|
+
*/
|
|
50
|
+
variant?: PlassVariant;
|
|
51
|
+
/**
|
|
52
|
+
* The bar's scale — its height floor, its gutter and the air around its
|
|
53
|
+
* slots. As on `PlBox`, `size` here is the size of the *sheet*.
|
|
54
|
+
* @default 'md'
|
|
55
|
+
*/
|
|
56
|
+
size?: PlassSize;
|
|
57
|
+
/** @default 'primary' */
|
|
58
|
+
color?: PlassColor;
|
|
59
|
+
/** @default 'default' */
|
|
60
|
+
density?: PlassDensity;
|
|
61
|
+
/**
|
|
62
|
+
* Drop shadow depth. `0` — the default — is flat: a header is attached to the
|
|
63
|
+
* top of the window rather than floating over the middle of it, and `divider`
|
|
64
|
+
* is what separates it from the content.
|
|
65
|
+
* @default 0
|
|
66
|
+
*/
|
|
67
|
+
elevation?: PlassElevation;
|
|
68
|
+
/**
|
|
69
|
+
* Draws a hairline along the bottom edge, against the content the bar is
|
|
70
|
+
* over. On by default: a bar pinned over a scrolling page has content passing
|
|
71
|
+
* underneath it at every moment, and a translucent sheet with nothing marking
|
|
72
|
+
* its edge reads as part of that.
|
|
73
|
+
* @default true
|
|
74
|
+
*/
|
|
75
|
+
divider?: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Holds the row of slots to a measure and centres it, while the sheet itself
|
|
78
|
+
* still spans the window. The same ladder `PlContainer`'s `maxWidth` uses, so
|
|
79
|
+
* a header and the container under it line up on the same edge.
|
|
80
|
+
* @default 'none'
|
|
81
|
+
*/
|
|
82
|
+
maxWidth?: PlHeaderWidth;
|
|
83
|
+
/** The gutter down each side of the row. @default true */
|
|
84
|
+
padded?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* The name the bar is announced by. Worth writing when a page has more than
|
|
87
|
+
* one `<header>` in it — an article's own header and the site's — because
|
|
88
|
+
* "banner" twice tells a reader which is which not at all.
|
|
89
|
+
*/
|
|
90
|
+
label?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Renders something other than a `<header>`. Base UI's own escape hatch, and
|
|
93
|
+
* rarely what you want: the bar at the top of a page is a banner, and the tag
|
|
94
|
+
* is what says so to a search engine and to a screen reader's landmark list.
|
|
95
|
+
*/
|
|
96
|
+
render?: useRender.RenderProp;
|
|
97
|
+
/** The middle slot. */
|
|
98
|
+
children?: React.ReactNode;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The bar across the top of a page.
|
|
102
|
+
*
|
|
103
|
+
* A real `<header>`, which is the whole reason it is a component rather than a
|
|
104
|
+
* row of `<div>`s: at the top level of a document that tag is the `banner`
|
|
105
|
+
* landmark, and it is what a screen reader's landmark list, a reader mode and a
|
|
106
|
+
* search engine's understanding of the page are all built out of.
|
|
107
|
+
*
|
|
108
|
+
* Its three slots are props rather than compound sub-components, for `PlCard`'s
|
|
109
|
+
* reason: the arrangement is fixed — brand, middle, actions — and what a caller
|
|
110
|
+
* wants to decide is what goes in each. That the middle can be centred on the
|
|
111
|
+
* bar's own midline is only possible because the ends are the component's to
|
|
112
|
+
* measure.
|
|
113
|
+
*
|
|
114
|
+
* Inside a `PlPageLayout` it also registers itself, so a sidebar that holds its
|
|
115
|
+
* place knows how far down the window to start. Outside one it is simply a bar,
|
|
116
|
+
* and everything above still works.
|
|
117
|
+
*
|
|
118
|
+
* It is not a `PlToolbar` with a tag on it. A toolbar is a row of controls
|
|
119
|
+
* anywhere on a screen and takes a height from its padding alone; a header is
|
|
120
|
+
* the page's banner, and it has a height floor, a measure, a brand slot and a
|
|
121
|
+
* place in a layout — none of which mean anything on a row of controls beside a
|
|
122
|
+
* table.
|
|
123
|
+
*/
|
|
124
|
+
export declare const PlHeader: React.ForwardRefExoticComponent<PlHeaderProps & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as s from"react";import{useRender as i}from"@base-ui/react/use-render";import{PlPageLayoutContext as t}from"../../internal/page-layout.js";import{cx as a,hasContent as n,sheetPaddingXClasses as l,sheetRestClasses as m,sheetSectionGapClasses as d,surfaceSlots as c,transitionClasses as o}from"../../internal/styles.js";const x={xs:"min-h-10",sm:"min-h-12",md:"min-h-16",lg:"min-h-20",xl:"min-h-24"},f={xs:"py-2",sm:"py-2",md:"py-3",lg:"py-4",xl:"py-5"},p={xs:"gap-3",sm:"gap-4",md:"gap-6",lg:"gap-7",xl:"gap-8"},u={xs:"max-w-[30rem]",sm:"max-w-[40rem]",md:"max-w-[48rem]",lg:"max-w-[64rem]",xl:"max-w-[80rem]"},h=m,y={static:"",sticky:"sticky top-0 z-20",fixed:"fixed inset-x-0 top-0 z-30"},w={start:"shrink-0",center:"flex-1 basis-0",end:"shrink-0"},g={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 PlHeader=/* @__PURE__ */s.forwardRef(function PlHeader({brand:m,actions:v,align:b="start",position:j="sticky",variant:N="glass",size:k="md",color:z="primary",density:C="default",elevation:H=0,divider:P=!0,maxWidth:R="none",padded:W=!0,label:q,render:A,className:B,style:D,children:E,...F},G){const{register:I}=s.useContext(t),J=s.useCallback(e=>{I("header",e),"function"==typeof G?G(e):G&&(G.current=e)},[I,G]),K=a("w-full min-w-0",h[N],P?"border-b [border-color:var(--plass-divider)]":"",y[j],o,B);return i({render:A??e("header",{}),ref:J,props:{"aria-label":q,className:K,style:{...c(z,H),...D},children:r("div",{className:a("flex w-full items-center",x[k],f[k],p[k],W?l[C][k]:"","none"===R?"":a(u[R],"mx-auto")),children:[n(m)?e("div",{className:a("flex min-w-0 items-center",w[b],d[k]),children:m}):"center"===b?e("div",{"aria-hidden":"true",className:w[b]}):null,n(E)?e("div",{className:a(g[b],d[k]),children:E}):null,n(v)?e("div",{className:a("flex min-w-0 items-center justify-end",w[b],d[k]),children:v}):"center"===b?e("div",{"aria-hidden":"true",className:w[b]}):null]}),...F}})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{PlHeader}from"./PlHeader.js";
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassOrientation, PlassStyleProps } from '../../types.js';
|
|
3
|
+
export interface PlMenubarProps extends Pick<PlassStyleProps, 'size' | 'color' | 'density'>, Omit<React.ComponentPropsWithoutRef<'div'>, 'color'> {
|
|
4
|
+
/**
|
|
5
|
+
* Which way the bar runs. `vertical` is the shape a side rail of menus takes;
|
|
6
|
+
* the arrow keys follow it either way.
|
|
7
|
+
* @default 'horizontal'
|
|
8
|
+
*/
|
|
9
|
+
orientation?: PlassOrientation;
|
|
10
|
+
/**
|
|
11
|
+
* Whether an open menu takes the page away. On — the default, and Base UI's —
|
|
12
|
+
* an open menu is what the pointer is talking to.
|
|
13
|
+
* @default true
|
|
14
|
+
*/
|
|
15
|
+
modal?: boolean;
|
|
16
|
+
/** Whether the arrow keys wrap around at the ends of the bar. @default true */
|
|
17
|
+
loopFocus?: boolean;
|
|
18
|
+
/** Disables every menu on the bar at once. */
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
/** The menus. */
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
}
|
|
23
|
+
export interface PlMenubarMenuProps {
|
|
24
|
+
/** The word on the bar. */
|
|
25
|
+
label: React.ReactNode;
|
|
26
|
+
/** Content before the label. Sized in `em`, so it tracks it. */
|
|
27
|
+
startIcon?: React.ReactNode;
|
|
28
|
+
/** Unavailable. The word stays on the bar and opens nothing. */
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
/** The rows, written exactly as they are inside a `PlMenu`. */
|
|
31
|
+
children?: React.ReactNode;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* One menu on the bar: the word, and the rows behind it.
|
|
35
|
+
*
|
|
36
|
+
* It has no `size`, `color` or `density` of its own — all three belong to the
|
|
37
|
+
* bar, which is the only place they can be set once and hold for every menu on
|
|
38
|
+
* it. The rows inside are the same `PlMenuItem`, `PlMenuSeparator`,
|
|
39
|
+
* `PlMenuGroup` and `PlMenuSubmenu` a `PlMenu` takes, because it *is* the same
|
|
40
|
+
* menu.
|
|
41
|
+
*/
|
|
42
|
+
export declare function PlMenubarMenu({ label, startIcon, disabled, children }: PlMenubarMenuProps): React.ReactElement;
|
|
43
|
+
/**
|
|
44
|
+
* The strip of words at the top of an application — File, Edit, View — each of
|
|
45
|
+
* which opens a menu.
|
|
46
|
+
*
|
|
47
|
+
* What makes it a bar rather than a row of separate menus is what happens once
|
|
48
|
+
* one is open: moving along the strip walks through the others instead of
|
|
49
|
+
* closing the one you left, and the arrow keys move between the menus as well
|
|
50
|
+
* as inside them. Base UI owns all of that, along with the `menubar` role.
|
|
51
|
+
*
|
|
52
|
+
* It draws **no surface of its own**. A menu bar sits *on* something — a
|
|
53
|
+
* `PlToolbar`, a `PlHeader` — and a sheet under a strip that is already on a
|
|
54
|
+
* sheet is two sheets.
|
|
55
|
+
*/
|
|
56
|
+
export declare const PlMenubar: React.ForwardRefExoticComponent<PlMenubarProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{jsxs as e,jsx as t}from"react/jsx-runtime";import*as o from"react";import{Menubar as s}from"@base-ui/react/menubar";import{PlMenu as r}from"../menu/PlMenu.js";import{MenuContext as n}from"../../internal/menu.js";import{controlTextClasses as a,cx as i,gapClasses as l,hasContent as c,iconClasses as p,paddingXClasses as d,radiusClasses as u,transitionClasses as m}from"../../internal/styles.js";const f={xs:"h-4.5",sm:"h-5.5",md:"h-6.5",lg:"h-8",xl:"h-10"},b=/* @__PURE__ */["inline-flex shrink-0 cursor-pointer select-none items-center justify-center","whitespace-nowrap font-medium leading-none","text-(--plass-fg) bg-transparent","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",m,p,"hover:bg-(--p-soft)","data-[popup-open]:bg-(--p-soft-hover) data-[popup-open]:text-(--p-accent)","focus-visible:[outline:2px_solid_var(--p-ring)] focus-visible:[outline-offset:-2px]","disabled:cursor-not-allowed disabled:opacity-50 disabled:saturate-[0.35]","disabled:hover:bg-transparent"].join(" ");export function PlMenubarMenu({label:s,startIcon:p,disabled:m=!1,children:h}){const{size:v,color:x,density:g}=o.useContext(n);return t(r,{size:v,color:x,density:g,disabled:m,openOnHover:!0,sideOffset:4,trigger:e("button",{type:"button",disabled:m,className:i(b,f[v],a[v],l[v],d["default"===g?"compact":g][v],u[v]),children:[c(p)?p:null,s]}),children:h})}export const PlMenubar=/* @__PURE__ */o.forwardRef(function PlMenubar({size:e="md",color:r="primary",density:a="default",orientation:c="horizontal",modal:p=!0,loopFocus:d=!0,disabled:u=!1,className:m,style:f,children:b,...h},v){const x=o.useMemo(()=>({size:e,color:r,density:a}),[e,r,a]);return t(n.Provider,{value:x,children:t(s,{ref:v,orientation:c,modal:p,loopFocus:d,disabled:u,className:i("flex items-center","vertical"===c?"flex-col items-stretch":"flex-row",l[e],m),style:{"--p-soft":`var(--plass-${r}-soft)`,"--p-soft-hover":`var(--plass-${r}-soft-hover)`,"--p-accent":`var(--plass-${r}-accent)`,"--p-ring":`var(--plass-${r}-ring)`,...f},...h,children:b})})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{PlMenubar,PlMenubarMenu}from"./PlMenubar.js";
|