plass-ui 1.1.0 → 1.2.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 (37) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/components/checkbox/PlCheckbox.d.ts +3 -1
  3. package/dist/components/checkbox/PlCheckbox.js +1 -1
  4. package/dist/components/combobox/PlCombobox.d.ts +4 -2
  5. package/dist/components/combobox/PlCombobox.js +1 -1
  6. package/dist/components/command-palette/PlCommandPalette.d.ts +8 -2
  7. package/dist/components/command-palette/PlCommandPalette.js +1 -1
  8. package/dist/components/drawer/PlDrawer.d.ts +4 -2
  9. package/dist/components/drawer/PlDrawer.js +1 -1
  10. package/dist/components/menu/PlMenu.d.ts +4 -2
  11. package/dist/components/menu/PlMenu.js +1 -1
  12. package/dist/components/menubar/PlMenubar.d.ts +5 -1
  13. package/dist/components/menubar/PlMenubar.js +1 -1
  14. package/dist/components/modal/PlModal.d.ts +4 -2
  15. package/dist/components/modal/PlModal.js +1 -1
  16. package/dist/components/navigation-menu/PlNavigationMenu.d.ts +5 -1
  17. package/dist/components/navigation-menu/PlNavigationMenu.js +1 -1
  18. package/dist/components/number-field/PlNumberField.d.ts +4 -2
  19. package/dist/components/number-field/PlNumberField.js +1 -1
  20. package/dist/components/otp-field/PlOtpField.d.ts +3 -1
  21. package/dist/components/otp-field/PlOtpField.js +1 -1
  22. package/dist/components/overlay/PlOverlay.d.ts +4 -2
  23. package/dist/components/overlay/PlOverlay.js +1 -1
  24. package/dist/components/radio-group/PlRadioGroup.d.ts +3 -1
  25. package/dist/components/radio-group/PlRadioGroup.js +1 -1
  26. package/dist/components/select/PlSelect.d.ts +3 -1
  27. package/dist/components/select/PlSelect.js +1 -1
  28. package/dist/components/switch/PlSwitch.d.ts +3 -1
  29. package/dist/components/switch/PlSwitch.js +1 -1
  30. package/dist/components/text-field/PlTextField.d.ts +3 -1
  31. package/dist/components/text-field/PlTextField.js +1 -1
  32. package/dist/components/toast/PlToast.d.ts +10 -0
  33. package/dist/components/toast/PlToast.js +1 -1
  34. package/dist/internal/picker.d.ts +4 -2
  35. package/dist/internal/picker.js +1 -1
  36. package/dist/types.d.ts +72 -0
  37. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  > This package's history. The Flutter package keeps its own at [`packages/flutter/CHANGELOG.md`](https://github.com/jooy2/plass-ui/blob/main/packages/flutter/CHANGELOG.md), because the two version independently.
4
4
 
5
+ ## 1.2.0 (2026-08-30)
6
+
7
+ ### Added
8
+
9
+ - **Every component that draws something now takes a `className` and a `style`.** Six did not, and each for its own reason rather than by decision: `PlCommandPalette`'s prop type is closed because it renders a portalled dialog rather than an element in the caller's tree, `PlMenubarMenu` and `PlNavigationMenuItem` describe a row that their parent draws, `PlMenuGroup` and `PlMenuRadioGroup` had the class and not the style, and a toast has no element to put either on — it is raised from a click handler. The first four take both on the element a reader would point at: the palette's sheet, the word on the bar, the word in the row. A toast takes them in the same `data` its colour and its variant already travel in, so `toast.add({ title, className })` reaches the one message rather than every message the provider will ever show. In all six the class **joins** the component's own rather than replacing them, and the style is applied **over** the custom properties the component wrote, which is the arrangement the rest of the library already had.
10
+
11
+ - **The `--plass-*` tokens are a typed channel.** Every one of them was already settable in an inline `style` — they are ordinary custom properties, and an inline declaration beats every class there is — but a `'--plass-radius-md'` written into a `style` object was a TypeScript error before it was anything else, because React's `CSSProperties` has no index signature. Importing the package now widens it to accept any `--plass-*` key and nothing else, so a typo in some other custom property is still a typo. This is the channel that matters most, and not as a convenience: the library writes its edge, its shadow, its focus ring and its fill as Tailwind _arbitrary properties_, Tailwind sorts those **last** in the generated stylesheet, and an ordinary utility appended after one loses on order whatever it says — while the token underneath it does not. It also cascades, which a `className` cannot: one declaration on a wrapping `<div>` and every Plass component inside it answers. `PlassToken` names all 108 of them and `PlassTokens` is the stricter form for a set of overrides written once, where a name that is not a token fails to compile. A new package test reads `styles.css` and the type as text and fails if either grows a token the other does not have.
12
+
13
+ - **A field's four parts are reachable.** Twelve labelled controls — `PlTextField`, `PlSelect`, `PlCombobox`, `PlNumberField`, `PlOtpField`, `PlCheckbox`, `PlSwitch`, `PlRadioGroup` and the four pickers — put a `className` on the _stack_: the wrapper holding the label, the control and the two lines of text under it. That is the right element to position and size a field with, and the wrong one for everything else a caller reaches for, which until now had nowhere to go. `classNames` names the four parts inside it: `label`, `control`, `description` and `error`.
14
+
15
+ **`control` is the one that matters.** It is the box a `PlTextField` is typed into, the button a `PlSelect` opens, the tick, the track, the run of radios, the trigger a picker's calendar hangs off — the part a reader acts on, and the part almost every override was aimed at. The other three are named because a field that has a label at all has three pieces of text with three different jobs, and "the red one under the box" is not addressable any other way. A `PlRadio` inside a group is deliberately not in the list: it is a row rather than a field, and its own `className` already lands on it.
16
+
17
+ - **A portalled surface's backdrop is reachable.** `PlModal`, `PlDrawer`, `PlOverlay` and `PlCommandPalette` each draw two elements into the portal, and a `className` could only ever land on one of them — the sheet, the panel, the popup, which is what a reader points at and calls the component. The scrim behind it had nothing at all. `classNames.backdrop` is that second element, and it is a **second prop rather than a second meaning for the first**: a component's own surface keeps one way of being addressed, so there is never a question of which of the two wins. An inline `PlDrawer` draws no scrim and simply has nowhere for the class to go, which is the one case where passing it does nothing.
18
+
19
+ ### Documentation
20
+
21
+ - **The styling contract is written down.** [Prop conventions](https://plass.cdget.com/design/prop-conventions#styling-a-component-from-outside) now has the four channels in the order to reach for them, and — the part that was not documented anywhere — **where a plain `className` loses**. The order of two classes in an attribute means nothing; what decides is their order in the generated stylesheet, and Tailwind sorts by _name_, numeric scales ascending and everything else alphabetically. So `text-lg` loses to a `size="sm"` field's `text-sm`, `bg-red-500` loses to a `ghost` button's `bg-transparent`, `w-auto` loses to `fullWidth`, and nothing at all beats an arbitrary property. The page says so with the measured table rather than with advice, and gives the two ways out: a token, or the `!` modifier, which always works because the library carries no `!important` of its own. Which stylesheet was imported changes the answer too, and that is a table as well.
22
+
23
+ - **`Getting started` overpromised what Tailwind's sort decides.** On the `plass-ui/tailwind.css` path it said that a `className` passed to a component "sorts correctly against the component's own classes", which reads as _the caller's class wins_ — and it does not. Tailwind sorts utilities by name, so a `text-lg` is emitted **before** a `size="sm"` field's `text-sm` and loses to it on order. The line now says what the sort actually settles, and points at the table that spells out the rest.
24
+
5
25
  ## 1.1.0 (2026-08-30)
6
26
 
7
27
  ### Added
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { Checkbox as BaseUICheckbox } from '@base-ui/react/checkbox';
3
- import type { PlassColor, PlassSize } from '../../types.js';
3
+ import type { PlassColor, PlassFieldClassNames, PlassSize } from '../../types.js';
4
4
  /**
5
5
  * Base UI's own props, minus the ones this component owns: `className` and
6
6
  * `style` land on the field wrapper rather than on the tick, and `render` would
@@ -8,6 +8,8 @@ import type { PlassColor, PlassSize } from '../../types.js';
8
8
  */
9
9
  type BaseCheckboxProps = Omit<React.ComponentPropsWithoutRef<typeof BaseUICheckbox.Root>, 'className' | 'style' | 'render' | 'children'>;
10
10
  export interface PlCheckboxProps extends BaseCheckboxProps {
11
+ /** Classes on the parts a `className` does not reach. */
12
+ classNames?: PlassFieldClassNames;
11
13
  /** @default 'md' */
12
14
  size?: PlassSize;
13
15
  /** @default 'primary' */
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as r from"react";import{Checkbox as t}from"@base-ui/react/checkbox";import{Field as o}from"@base-ui/react/field";import{controlSlots as s,focusRingClasses as l,glassClasses as i,hasContent as n,metaTextClasses as c,tickRadiusClasses as d,tickRowTextClasses as p,tickSizeClasses as h,transitionClasses as m}from"../../internal/styles.js";const u=/* @__PURE__ */["relative inline-flex shrink-0 items-center justify-center border","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",m,l].join(" "),f=/* @__PURE__ */[i,"cursor-pointer bg-(--plass-glass) [border-color:var(--plass-border)]","hover:bg-(--plass-glass-hover) hover:[border-color:var(--p-line)]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent] data-[checked]:hover:brightness-105","data-[indeterminate]:[background-image:var(--p-fill)] data-[indeterminate]:text-(--p-on-solid)","data-[indeterminate]:[border-color:transparent]"].join(" "),k=/* @__PURE__ */[i,"cursor-default bg-(--plass-glass) [border-color:var(--plass-border)]","saturate-[0.55]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent]"].join(" "),b=/* @__PURE__ */[i,"cursor-not-allowed bg-(--plass-glass) [border-color:var(--plass-border)]","opacity-50 saturate-[0.35]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent]","data-[indeterminate]:[background-image:var(--p-fill)] data-[indeterminate]:text-(--p-on-solid)"].join(" ");function CheckMark(){return e("svg",{viewBox:"0 0 12 12",fill:"none","aria-hidden":"true",className:"size-full",children:e("path",{d:"M2 6.2 4.6 8.8 10 3.4",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function DashMark(){return e("svg",{viewBox:"0 0 12 12",fill:"none","aria-hidden":"true",className:"size-full",children:e("path",{d:"M2.5 6h7",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})})}export const PlCheckbox=/* @__PURE__ */r.forwardRef(function PlCheckbox({size:r="md",color:l="primary",label:i,description:m,error:g,invalid:x,disabled:v=!1,readOnly:j=!1,className:N,style:y,...C},w){const M=n(g),z=x??M,L=z?"danger":l,$=[u,h[r],d[r],v?b:j?k:f].join(" ");return a(o.Root,{disabled:v,invalid:z,className:["inline-flex flex-col gap-1 align-top",N??""].filter(Boolean).join(" "),style:{...s(L,0,"solid"),...y},children:[a("div",{className:`flex items-start gap-2 ${p[r]}`,children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(t.Root,{ref:w,className:$,disabled:v,readOnly:j,...C,children:e(t.Indicator,{className:"flex size-[70%] items-center justify-center",children:C.indeterminate?e(DashMark,{}):e(CheckMark,{})})})}),i||m?a("span",{className:"flex min-w-0 flex-col gap-0.5",children:[i?e(o.Label,{className:v?"text-(--plass-muted-fg)":"cursor-pointer text-(--plass-fg)",children:i}):null,m?e(o.Description,{className:`${c[r]} text-(--plass-muted-fg)`,children:m}):null]}):null]}),e(o.Error,M?{match:!0,className:`${c[r]} text-(--p-accent)`,children:g}:{className:`${c[r]} text-(--p-accent)`})]})});
1
+ "use client";import{jsx as e,jsxs as r}from"react/jsx-runtime";import*as a from"react";import{Checkbox as t}from"@base-ui/react/checkbox";import{Field as o}from"@base-ui/react/field";import{controlSlots as s,cx as l,focusRingClasses as i,glassClasses as n,hasContent as c,metaTextClasses as d,tickRadiusClasses as p,tickRowTextClasses as h,tickSizeClasses as m,transitionClasses as u}from"../../internal/styles.js";const f=/* @__PURE__ */["relative inline-flex shrink-0 items-center justify-center border","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",u,i].join(" "),b=/* @__PURE__ */[n,"cursor-pointer bg-(--plass-glass) [border-color:var(--plass-border)]","hover:bg-(--plass-glass-hover) hover:[border-color:var(--p-line)]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent] data-[checked]:hover:brightness-105","data-[indeterminate]:[background-image:var(--p-fill)] data-[indeterminate]:text-(--p-on-solid)","data-[indeterminate]:[border-color:transparent]"].join(" "),k=/* @__PURE__ */[n,"cursor-default bg-(--plass-glass) [border-color:var(--plass-border)]","saturate-[0.55]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent]"].join(" "),g=/* @__PURE__ */[n,"cursor-not-allowed bg-(--plass-glass) [border-color:var(--plass-border)]","opacity-50 saturate-[0.35]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent]","data-[indeterminate]:[background-image:var(--p-fill)] data-[indeterminate]:text-(--p-on-solid)"].join(" ");function CheckMark(){return e("svg",{viewBox:"0 0 12 12",fill:"none","aria-hidden":"true",className:"size-full",children:e("path",{d:"M2 6.2 4.6 8.8 10 3.4",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function DashMark(){return e("svg",{viewBox:"0 0 12 12",fill:"none","aria-hidden":"true",className:"size-full",children:e("path",{d:"M2.5 6h7",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})})}export const PlCheckbox=/* @__PURE__ */a.forwardRef(function PlCheckbox({size:a="md",color:i="primary",label:n,description:u,error:x,invalid:v,disabled:N=!1,readOnly:j=!1,className:y,classNames:C,style:w,...M},z){const L=c(x),B=v??L,D=B?"danger":i,R=l(f,m[a],p[a],N?g:j?k:b,C?.control);return r(o.Root,{disabled:N,invalid:B,className:["inline-flex flex-col gap-1 align-top",y??""].filter(Boolean).join(" "),style:{...s(D,0,"solid"),...w},children:[r("div",{className:`flex items-start gap-2 ${h[a]}`,children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(t.Root,{ref:z,className:R,disabled:N,readOnly:j,...M,children:e(t.Indicator,{className:"flex size-[70%] items-center justify-center",children:M.indeterminate?e(DashMark,{}):e(CheckMark,{})})})}),n||u?r("span",{className:"flex min-w-0 flex-col gap-0.5",children:[n?e(o.Label,{className:l(N?"text-(--plass-muted-fg)":"cursor-pointer text-(--plass-fg)",C?.label),children:n}):null,u?e(o.Description,{className:l(d[a],"text-(--plass-muted-fg)",C?.description),children:u}):null]}):null]}),e(o.Error,L?{match:!0,className:l(d[a],"text-(--p-accent)",C?.error),children:x}:{className:l(d[a],"text-(--p-accent)",C?.error)})]})});
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { PlassElevation, PlassStyleProps } from '../../types.js';
2
+ import type { PlassElevation, PlassFieldClassNames, PlassStyleProps } from '../../types.js';
3
3
  /**
4
4
  * What a combobox's value may be — the same two types a PlSelect submits, and
5
5
  * for the same reason: a form control's value is what a form sends, and every
@@ -25,6 +25,8 @@ export interface PlComboboxOption {
25
25
  /** One value, or an array of them, depending on `multiple`. */
26
26
  type Selection<Multiple extends boolean | undefined> = Multiple extends true ? PlComboboxValue[] : PlComboboxValue | null;
27
27
  export interface PlComboboxProps<Multiple extends boolean | undefined = false> extends PlassStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'children'> {
28
+ /** Classes on the parts a `className` does not reach. */
29
+ classNames?: PlassFieldClassNames;
28
30
  /**
29
31
  * The options, as data — the same shape PlSelect takes, and for the same
30
32
  * reason: what a caller has is almost always an array already.
@@ -136,5 +138,5 @@ export interface PlComboboxProps<Multiple extends boolean | undefined = false> e
136
138
  * navigation across both the list and the chips, and the hidden input that makes
137
139
  * the whole thing submit with a form.
138
140
  */
139
- export declare function PlCombobox<Multiple extends boolean | undefined = false>({ variant, size, color, density, elevation, items, multiple, value, defaultValue, onValueChange, onInputValueChange, allowCustom, customLabel, clearable, emptyMessage, limit, placeholder, label, description, error, invalid, startIcon, fullWidth, disabled, readOnly, required, name, open, defaultOpen, onOpenChange, openLabel, clearLabel, removeLabel, inputRef, id, className, style, ...props }: PlComboboxProps<Multiple>): React.JSX.Element;
141
+ export declare function PlCombobox<Multiple extends boolean | undefined = false>({ variant, size, color, density, elevation, items, multiple, value, defaultValue, onValueChange, onInputValueChange, allowCustom, customLabel, clearable, emptyMessage, limit, placeholder, label, description, error, invalid, startIcon, fullWidth, disabled, readOnly, required, name, open, defaultOpen, onOpenChange, openLabel, clearLabel, removeLabel, inputRef, id, className, classNames, style, ...props }: PlComboboxProps<Multiple>): React.JSX.Element;
140
142
  export {};
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as l from"react";import{Combobox as t}from"@base-ui/react/combobox";import{Field as s}from"@base-ui/react/field";import{PlChip as n}from"../chip/PlChip.js";import{CheckIcon as r,ChevronIcon as i,CloseIcon as o,PlusIcon as c}from"../../internal/icons.js";import{chipRemoveClasses as d,controlHeightClasses as m,controlTextLeadingClasses as p,cx as u,disabledClasses as h,fieldReadOnlyClasses as b,fieldRestClasses as g,focusWithinRingClasses as f,gapClasses as v,glassClasses as x,hasContent as y,iconClasses as N,metaTextClasses as w,paddingXClasses as C,radiusClasses as L,stackGapClasses as j,surfaceSlots as I,transitionClasses as S}from"../../internal/styles.js";const A=/* @__PURE__ */["group relative flex w-full cursor-text items-center","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",S,f,N].join(" "),O={xs:"min-h-6 py-0",sm:"min-h-8 py-0.5",md:"min-h-10 py-1",lg:"min-h-12 py-1.5",xl:"min-h-14 py-2"},V=/* @__PURE__ */[x,"max-h-[min(20rem,var(--available-height))] overflow-y-auto overscroll-contain","w-[var(--anchor-width)] border bg-(--plass-glass-press) p-1","[border-color:var(--plass-glass-line)]","[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]","[outline:none]"].join(" "),z=/* @__PURE__ */["relative flex cursor-pointer items-center gap-2 select-none","rounded-(--plass-radius-xs) py-1.5 pe-2 ps-7",S,"data-[highlighted]:bg-(--p-soft-hover) data-[highlighted]:text-(--p-accent)","data-[selected]:font-semibold data-[selected]:text-(--p-accent)","data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50","[outline:none]"].join(" "),_=/* @__PURE__ */["inline-flex h-[1lh] shrink-0 cursor-pointer items-center justify-center","rounded-(--plass-radius-xs) text-(--plass-muted-fg)","[transition:color_var(--plass-duration)_var(--plass-ease)]","hover:text-(--p-accent)","focus-visible:[outline:2px_solid_var(--p-ring)] focus-visible:[outline-offset:1px]","disabled:cursor-not-allowed disabled:opacity-50"].join(" ");function toArray(e){return null==e?[]:Array.isArray(e)?e.slice():[e]}export function PlCombobox({variant:f="glass",size:x="md",color:N="primary",density:S="default",elevation:M=0,items:P,multiple:R,value:$,defaultValue:k,onValueChange:T,onInputValueChange:q,allowCustom:E=!0,customLabel:F,clearable:D=!1,emptyMessage:G="No matches",limit:H,placeholder:W,label:B,description:J,error:K,invalid:Q,startIcon:U,fullWidth:X=!1,disabled:Y=!1,readOnly:Z=!1,required:ee=!1,name:ae,open:le,defaultOpen:te,onOpenChange:se,openLabel:ne="Open",clearLabel:re="Clear",removeLabel:ie=e=>`Remove ${e}`,inputRef:oe,id:ce,className:de,style:me,...pe}){const ue=y(K),he=Q??ue,be=he?"danger":N,ge=!0===R,fe=l.useMemo(()=>P.map(e=>({value:e.value,label:e.label??String(e.value),disabled:e.disabled})),[P]),[ve,xe]=l.useState(()=>toArray(k)),ye=void 0===$?ve:toArray($),[Ne,we]=l.useState(""),Ce=l.useMemo(()=>new Map(fe.map(e=>[e.value,e])),[fe]),Le=l.useCallback(e=>Ce.get(e)??{value:e,label:String(e),custom:!0},[Ce]),je=Ne.trim(),Ie=je.toLocaleLowerCase(),Se=""===je||fe.some(e=>e.label.toLocaleLowerCase()===Ie||String(e.value).toLocaleLowerCase()===Ie)||ye.some(e=>String(e).toLocaleLowerCase()===Ie),Ae=!E||Z||Y||Se?null:je,Oe=l.useMemo(()=>null===Ae?fe:[...fe,{value:Ae,label:Ae,custom:!0}],[fe,Ae]),Ve=ge?ye.map(Le):ye.length>0?Le(ye[0]):null,ze=u(A,p[x],L[x],v[x],ge?O[x]:m[x],`${C[S][x]} pe-1.5`,Y?h[f]:Z?b[f]:g[f]),_e=/* @__PURE__ */["min-w-0 flex-1 self-stretch bg-transparent [font:inherit] text-inherit","[outline:none]","placeholder:text-(--plass-muted-fg)","caret-(--p-accent) selection:bg-(--p-soft-press)","disabled:cursor-not-allowed"].join(" "),renderInput=a=>e(t.Input,{ref:oe,placeholder:W,className:u(_e,ge&&"min-w-16",ge&&a&&"ms-1.5")});return a(s.Root,{disabled:Y,invalid:he,className:u("flex-col align-top",j[x],X?"flex w-full":"inline-flex",de),style:{...I(be,M),...me},...pe,children:[B?e(s.Label,{className:u(w[x],"font-semibold",Y?"text-(--plass-muted-fg)":"text-(--plass-fg)"),children:B}):null,a(t.Root,{id:ce,name:ae,items:Oe,multiple:ge,value:Ve,onValueChange:e=>{!function commit(e){void 0===$&&xe(e),T?.(ge?e:e[0]??null)}((null===e?[]:Array.isArray(e)?e:[e]).map(e=>e.value))},onInputValueChange:e=>{we(e),q?.(e)},open:le,defaultOpen:te,onOpenChange:e=>se?.(e),autoHighlight:!0,itemToStringLabel:e=>e.label,itemToStringValue:e=>String(e.value),isItemEqualToValue:(e,a)=>e.value===a.value,limit:H,disabled:Y,readOnly:Z,required:ee,children:[a(t.InputGroup,{className:ze,children:[U?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)",children:U}):null,ge?e(t.Chips,{className:"flex min-w-0 flex-1 flex-wrap items-center gap-1",children:e(t.Value,{children:s=>a(l.Fragment,{children:[s.map(a=>e(t.Chip,{render:e(n,{variant:"glass",size:x,color:be,density:"compact",disabled:Y,endIcon:Z||Y?null:e(t.ChipRemove,{"aria-label":ie(a.label),className:d,children:e(o,{})})}),children:a.label},String(a.value))),renderInput(s.length>0)]})})}):renderInput(!1),D&&!Z?e(t.Clear,{"aria-label":re,className:_,children:e(o,{})}):null,e(t.Trigger,{"aria-label":ne,className:_,children:e(t.Icon,{className:u("flex items-center","[transition:rotate_var(--plass-duration)_var(--plass-ease)]","data-[popup-open]:rotate-180"),children:e(i,{})})})]}),e(t.Portal,{children:e(t.Positioner,{className:"plass-portal z-(--plass-z-portal) [outline:none]",sideOffset:6,children:a(t.Popup,{className:u(V,L[x],p[x]),style:I(be,3),children:[e(t.Empty,{className:"px-2 py-1.5 text-(--plass-muted-fg) empty:hidden",children:G}),e(t.List,{children:s=>e(t.Item,{value:s,disabled:s.disabled,className:z,children:s.custom?a(l.Fragment,{children:[e("span",{className:"absolute start-1.5 flex size-4 items-center justify-center text-(--p-accent) [&_svg]:size-4",children:e(c,{})}),e("span",{className:"truncate",children:F?F(s.label):`Add “${s.label}”`})]}):a(l.Fragment,{children:[e(t.ItemIndicator,{className:"absolute start-1.5 flex size-4 items-center justify-center",children:e(r,{})}),e("span",{className:"truncate",children:s.label})]})},`${s.custom?"custom:":""}${String(s.value)}`)})]})})})]}),J?e(s.Description,{className:u(w[x],"text-(--plass-muted-fg)"),children:J}):null,e(s.Error,ue?{match:!0,className:u(w[x],"text-(--p-accent)"),children:K}:{className:u(w[x],"text-(--p-accent)")})]})}
1
+ "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as l from"react";import{Combobox as t}from"@base-ui/react/combobox";import{Field as s}from"@base-ui/react/field";import{PlChip as r}from"../chip/PlChip.js";import{CheckIcon as n,ChevronIcon as i,CloseIcon as o,PlusIcon as c}from"../../internal/icons.js";import{chipRemoveClasses as d,controlHeightClasses as m,controlTextLeadingClasses as p,cx as u,disabledClasses as h,fieldReadOnlyClasses as b,fieldRestClasses as g,focusWithinRingClasses as f,gapClasses as v,glassClasses as x,hasContent as y,iconClasses as N,metaTextClasses as w,paddingXClasses as C,radiusClasses as L,stackGapClasses as j,surfaceSlots as I,transitionClasses as S}from"../../internal/styles.js";const A=/* @__PURE__ */["group relative flex w-full cursor-text items-center","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",S,f,N].join(" "),O={xs:"min-h-6 py-0",sm:"min-h-8 py-0.5",md:"min-h-10 py-1",lg:"min-h-12 py-1.5",xl:"min-h-14 py-2"},V=/* @__PURE__ */[x,"max-h-[min(20rem,var(--available-height))] overflow-y-auto overscroll-contain","w-[var(--anchor-width)] border bg-(--plass-glass-press) p-1","[border-color:var(--plass-glass-line)]","[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]","[outline:none]"].join(" "),z=/* @__PURE__ */["relative flex cursor-pointer items-center gap-2 select-none","rounded-(--plass-radius-xs) py-1.5 pe-2 ps-7",S,"data-[highlighted]:bg-(--p-soft-hover) data-[highlighted]:text-(--p-accent)","data-[selected]:font-semibold data-[selected]:text-(--p-accent)","data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50","[outline:none]"].join(" "),_=/* @__PURE__ */["inline-flex h-[1lh] shrink-0 cursor-pointer items-center justify-center","rounded-(--plass-radius-xs) text-(--plass-muted-fg)","[transition:color_var(--plass-duration)_var(--plass-ease)]","hover:text-(--p-accent)","focus-visible:[outline:2px_solid_var(--p-ring)] focus-visible:[outline-offset:1px]","disabled:cursor-not-allowed disabled:opacity-50"].join(" ");function toArray(e){return null==e?[]:Array.isArray(e)?e.slice():[e]}export function PlCombobox({variant:f="glass",size:x="md",color:N="primary",density:S="default",elevation:M=0,items:P,multiple:R,value:$,defaultValue:k,onValueChange:T,onInputValueChange:q,allowCustom:E=!0,customLabel:F,clearable:D=!1,emptyMessage:G="No matches",limit:H,placeholder:W,label:B,description:J,error:K,invalid:Q,startIcon:U,fullWidth:X=!1,disabled:Y=!1,readOnly:Z=!1,required:ee=!1,name:ae,open:le,defaultOpen:te,onOpenChange:se,openLabel:re="Open",clearLabel:ne="Clear",removeLabel:ie=e=>`Remove ${e}`,inputRef:oe,id:ce,className:de,classNames:me,style:pe,...ue}){const he=y(K),be=Q??he,ge=be?"danger":N,fe=!0===R,ve=l.useMemo(()=>P.map(e=>({value:e.value,label:e.label??String(e.value),disabled:e.disabled})),[P]),[xe,ye]=l.useState(()=>toArray(k)),Ne=void 0===$?xe:toArray($),[we,Ce]=l.useState(""),Le=l.useMemo(()=>new Map(ve.map(e=>[e.value,e])),[ve]),je=l.useCallback(e=>Le.get(e)??{value:e,label:String(e),custom:!0},[Le]),Ie=we.trim(),Se=Ie.toLocaleLowerCase(),Ae=""===Ie||ve.some(e=>e.label.toLocaleLowerCase()===Se||String(e.value).toLocaleLowerCase()===Se)||Ne.some(e=>String(e).toLocaleLowerCase()===Se),Oe=!E||Z||Y||Ae?null:Ie,Ve=l.useMemo(()=>null===Oe?ve:[...ve,{value:Oe,label:Oe,custom:!0}],[ve,Oe]),ze=fe?Ne.map(je):Ne.length>0?je(Ne[0]):null,_e=u(A,p[x],L[x],v[x],fe?O[x]:m[x],`${C[S][x]} pe-1.5`,Y?h[f]:Z?b[f]:g[f]),Me=/* @__PURE__ */["min-w-0 flex-1 self-stretch bg-transparent [font:inherit] text-inherit","[outline:none]","placeholder:text-(--plass-muted-fg)","caret-(--p-accent) selection:bg-(--p-soft-press)","disabled:cursor-not-allowed"].join(" "),renderInput=a=>e(t.Input,{ref:oe,placeholder:W,className:u(Me,fe&&"min-w-16",fe&&a&&"ms-1.5")});return a(s.Root,{disabled:Y,invalid:be,className:u("flex-col align-top",j[x],X?"flex w-full":"inline-flex",de),style:{...I(ge,M),...pe},...ue,children:[B?e(s.Label,{className:u(w[x],"font-semibold",Y?"text-(--plass-muted-fg)":"text-(--plass-fg)",me?.label),children:B}):null,a(t.Root,{id:ce,name:ae,items:Ve,multiple:fe,value:ze,onValueChange:e=>{!function commit(e){void 0===$&&ye(e),T?.(fe?e:e[0]??null)}((null===e?[]:Array.isArray(e)?e:[e]).map(e=>e.value))},onInputValueChange:e=>{Ce(e),q?.(e)},open:le,defaultOpen:te,onOpenChange:e=>se?.(e),autoHighlight:!0,itemToStringLabel:e=>e.label,itemToStringValue:e=>String(e.value),isItemEqualToValue:(e,a)=>e.value===a.value,limit:H,disabled:Y,readOnly:Z,required:ee,children:[a(t.InputGroup,{className:u(_e,me?.control),children:[U?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)",children:U}):null,fe?e(t.Chips,{className:"flex min-w-0 flex-1 flex-wrap items-center gap-1",children:e(t.Value,{children:s=>a(l.Fragment,{children:[s.map(a=>e(t.Chip,{render:e(r,{variant:"glass",size:x,color:ge,density:"compact",disabled:Y,endIcon:Z||Y?null:e(t.ChipRemove,{"aria-label":ie(a.label),className:d,children:e(o,{})})}),children:a.label},String(a.value))),renderInput(s.length>0)]})})}):renderInput(!1),D&&!Z?e(t.Clear,{"aria-label":ne,className:_,children:e(o,{})}):null,e(t.Trigger,{"aria-label":re,className:_,children:e(t.Icon,{className:u("flex items-center","[transition:rotate_var(--plass-duration)_var(--plass-ease)]","data-[popup-open]:rotate-180"),children:e(i,{})})})]}),e(t.Portal,{children:e(t.Positioner,{className:"plass-portal z-(--plass-z-portal) [outline:none]",sideOffset:6,children:a(t.Popup,{className:u(V,L[x],p[x]),style:I(ge,3),children:[e(t.Empty,{className:"px-2 py-1.5 text-(--plass-muted-fg) empty:hidden",children:G}),e(t.List,{children:s=>e(t.Item,{value:s,disabled:s.disabled,className:z,children:s.custom?a(l.Fragment,{children:[e("span",{className:"absolute start-1.5 flex size-4 items-center justify-center text-(--p-accent) [&_svg]:size-4",children:e(c,{})}),e("span",{className:"truncate",children:F?F(s.label):`Add “${s.label}”`})]}):a(l.Fragment,{children:[e(t.ItemIndicator,{className:"absolute start-1.5 flex size-4 items-center justify-center",children:e(n,{})}),e("span",{className:"truncate",children:s.label})]})},`${s.custom?"custom:":""}${String(s.value)}`)})]})})})]}),J?e(s.Description,{className:u(w[x],"text-(--plass-muted-fg)",me?.description),children:J}):null,e(s.Error,he?{match:!0,className:u(w[x],"text-(--p-accent)",me?.error),children:K}:{className:u(w[x],"text-(--p-accent)",me?.error)})]})}
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { PlassStyleProps } from '../../types.js';
2
+ import type { PlassPortalClassNames, PlassStyleProps } from '../../types.js';
3
3
  /** One thing the palette can do. */
4
4
  export interface PlCommandItem {
5
5
  /** What identifies the command. */
@@ -63,6 +63,12 @@ export interface PlCommandPaletteProps extends Pick<PlassStyleProps, 'size' | 'c
63
63
  emptyMessage?: React.ReactNode;
64
64
  /** The accessible name of the dialog, which has no visible title. @default 'Command palette' */
65
65
  label?: string;
66
+ /** Classes on the sheet, alongside the component's own. */
67
+ className?: string;
68
+ /** Inline styles on the sheet, applied over the tokens it sets. */
69
+ style?: React.CSSProperties;
70
+ /** Classes on the parts a `className` does not reach. */
71
+ classNames?: PlassPortalClassNames;
66
72
  }
67
73
  /**
68
74
  * Everything an application can do, behind one field.
@@ -80,4 +86,4 @@ export interface PlCommandPaletteProps extends Pick<PlassStyleProps, 'size' | 'c
80
86
  * its Dialog owns the sheet, the scrim, the focus trap and returning the focus
81
87
  * to wherever the reader was.
82
88
  */
83
- export declare function PlCommandPalette({ items, open, defaultOpen, onOpenChange, onSelect, shortcut, width, maxHeight, placeholder, emptyMessage, label, size, color, density }: PlCommandPaletteProps): React.ReactElement;
89
+ export declare function PlCommandPalette({ items, open, defaultOpen, onOpenChange, onSelect, shortcut, width, maxHeight, placeholder, emptyMessage, label, size, color, density, className, classNames, style }: PlCommandPaletteProps): React.ReactElement;
@@ -1 +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})]})})})]})})}
1
+ "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as s from"react";import{Autocomplete as t}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",className:H,classNames:V,style:D}){const[F,I]=s.useState(N),[R,A]=s.useState(""),B=p??F,T=s.useCallback(e=>{void 0===p&&I(e),j?.(e)},[p,j]);s.useEffect(()=>{if(!1===K)return;const onKeyDown=e=>{(function pressed(e,a){const s=a.toLowerCase().split("+"),t=s[s.length-1],l=new Set(s.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()!==t)})(e,K)&&(e.preventDefault(),T(!0))};return window.addEventListener("keydown",onKeyDown),()=>window.removeEventListener("keydown",onKeyDown)},[K,T]);const W=s.useMemo(()=>r.map(haystackOf),[r]),q=s.useMemo(()=>{const e=n(R);return""===e?r:r.filter((a,s)=>W[s].includes(e))},[r,W,R]),G=f(z),J=f(S);return e(l.Root,{open:B,onOpenChange:e=>{e||A(""),T(e)},children:a(l.Portal,{children:[e(l.Backdrop,{className:c("plass-portal",x,V?.backdrop)}),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===G?y[P]:"","self-start",H),style:{...h(E,3),...void 0===G?null:{maxWidth:G},...D},children:a(t.Root,{open:!0,mode:"list",items:q,filter:null,value:R,onValueChange:e=>A(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(t.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(t.List,{className:"min-h-0 flex-1 overflow-y-auto overscroll-contain p-1",style:{maxHeight:J},children:(l,r)=>a(s.Fragment,{children:[l.group&&l.group!==q[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(t.Item,{index:r,value:l,disabled:l.disabled,onClick:()=>(e=>{e.disabled||(e.onSelect?.(),C?.(e),T(!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(t.Empty,{className:c(w[P],"py-6 text-center text-(--plass-muted-fg)",m[P]),children:L})]})})})]})})}
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { Dialog as BaseUIDialog } from '@base-ui/react/dialog';
3
- import type { PlassSide, PlassStyleProps } from '../../types.js';
3
+ import type { PlassPortalClassNames, PlassSide, PlassStyleProps } from '../../types.js';
4
4
  /**
5
5
  * How the panel relates to the page.
6
6
  *
@@ -26,6 +26,8 @@ export type PlDrawerMode = 'overlay' | 'inline';
26
26
  * is a decision worth offering.
27
27
  */
28
28
  export interface PlDrawerProps extends Pick<PlassStyleProps, 'size' | 'color' | 'density'>, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'title' | 'children'> {
29
+ /** Classes on the parts a `className` does not reach. */
30
+ classNames?: PlassPortalClassNames;
29
31
  /**
30
32
  * Which edge the panel is attached to. Physical rather than logical, the way
31
33
  * `PlassSide` is everywhere: a drawer along the top of the window is along the
@@ -141,4 +143,4 @@ export declare const PlDrawerClose: React.ForwardRefExoticComponent<Omit<import(
141
143
  * scroll lock, the `aria-labelledby` / `aria-describedby` wiring, restoring
142
144
  * focus to the trigger, and the inert page behind.
143
145
  */
144
- export declare function PlDrawer({ side, mode, size, color, density, open, defaultOpen, onOpenChange, trigger, title, description, actions, dividers, showClose, closeLabel, extent, rounded, modal, dismissible, className, style, children, ...props }: PlDrawerProps): React.JSX.Element | null;
146
+ export declare function PlDrawer({ side, mode, size, color, density, open, defaultOpen, onOpenChange, trigger, title, description, actions, dividers, showClose, closeLabel, extent, rounded, modal, dismissible, className, classNames, style, children, ...props }: PlDrawerProps): React.JSX.Element | null;
@@ -1 +1 @@
1
- "use client";import{jsx as s,jsxs as l,Fragment as e}from"react/jsx-runtime";import{Dialog as r}from"@base-ui/react/dialog";import{CloseIcon as a}from"../../internal/icons.js";import{cx as o,focusRingClasses as d,glassClasses as i,hasContent as t,metaTextClasses as n,sheetBodyClasses as p,sheetHeaderGapClasses as u,sheetLineClasses as m,sheetPaddingXClasses as c,sheetPaddingYClasses as x,sheetSectionGapClasses as f,sheetTitleClasses as g,surfaceSlots as h}from"../../internal/styles.js";const b={xs:"w-56",sm:"w-64",md:"w-80",lg:"w-96",xl:"w-[28rem]"},v={left:{xs:"rounded-r-(--plass-radius-xs)",sm:"rounded-r-(--plass-radius-sm)",md:"rounded-r-(--plass-radius-md)",lg:"rounded-r-(--plass-radius-lg)",xl:"rounded-r-(--plass-radius-xl)"},right:{xs:"rounded-l-(--plass-radius-xs)",sm:"rounded-l-(--plass-radius-sm)",md:"rounded-l-(--plass-radius-md)",lg:"rounded-l-(--plass-radius-lg)",xl:"rounded-l-(--plass-radius-xl)"},top:{xs:"rounded-b-(--plass-radius-xs)",sm:"rounded-b-(--plass-radius-sm)",md:"rounded-b-(--plass-radius-md)",lg:"rounded-b-(--plass-radius-lg)",xl:"rounded-b-(--plass-radius-xl)"},bottom:{xs:"rounded-t-(--plass-radius-xs)",sm:"rounded-t-(--plass-radius-sm)",md:"rounded-t-(--plass-radius-md)",lg:"rounded-t-(--plass-radius-lg)",xl:"rounded-t-(--plass-radius-xl)"}},y={left:"border-r",right:"border-l",top:"border-b",bottom:"border-t"},w={left:"flex-row justify-start",right:"flex-row justify-end",top:"flex-col justify-start",bottom:"flex-col justify-end"},j=/* @__PURE__ */[i,"relative flex flex-col overflow-hidden","text-(--plass-fg) bg-(--plass-glass-press)","[border-color:var(--plass-glass-line)]","[outline:none]"].join(" "),N=/* @__PURE__ */["[transition:opacity_var(--plass-duration)_var(--plass-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" "),k=/* @__PURE__ */["fixed inset-0 z-(--plass-z-portal) bg-(--plass-scrim)","[backdrop-filter:blur(2px)] [-webkit-backdrop-filter:blur(2px)]",N].join(" "),C=/* @__PURE__ */["flex size-[1.6em] shrink-0 cursor-pointer items-center justify-center","rounded-full text-(--plass-muted-fg)","[&_svg]:size-[1.1em] [&_svg]:shrink-0","[transition:background-color_var(--plass-duration)_var(--plass-ease),color_var(--plass-duration)_var(--plass-ease)]","hover:bg-(--p-soft) hover:text-(--plass-fg)",d].join(" ");export const PlDrawerClose=r.Close;export function PlDrawer({side:d="left",mode:i="overlay",size:_="md",color:z="primary",density:$="default",open:D,defaultOpen:P,onOpenChange:O,trigger:T,title:B,description:F,actions:L,dividers:R=!1,showClose:V,closeLabel:q="Close",extent:A,rounded:E=!0,modal:G=!0,dismissible:H=!0,className:I,style:J,children:K,...M}){const Q="overlay"===i,S="left"===d||"right"===d,U=V??Q,W=c[$][_],X=x[$][_],Y=R?`${W} ${X}`:W,Z=t(B)||t(F),ss=t(L),ls=void 0===A?null:{[S?"width":"height"]:"number"==typeof A?`${A}px`:A},es=o(j,p[_],y[d],E?v[d][_]:"",Q?"[box-shadow:var(--plass-shadow-4),var(--plass-gloss-glass)]":"[box-shadow:var(--plass-gloss-glass)]",Q?N:"",S?`h-full max-w-full ${void 0===A?b[_]:""}`:"w-full "+(void 0===A?"max-h-[85%]":""),R?"":`${X} ${f[_]}`,I),rs=Q?r.Title:"h2",as=Q?r.Description:"p",os=l(e,{children:[Z||U?l("div",{className:o("flex shrink-0 items-start gap-3",Y),children:[l("div",{className:o("flex min-w-0 flex-1 flex-col",u[_]),children:[t(B)?s(rs,{className:o("m-0 font-semibold",g[_]),children:B}):null,t(F)?s(as,{className:o("m-0 text-(--plass-muted-fg)",n[_]),children:F}):null]}),U?Q?s(r.Close,{"aria-label":q,className:C,children:s(a,{})}):s("button",{type:"button","aria-label":q,className:C,onClick:()=>O?.(!1),children:s(a,{})}):null]}):null,t(K)?s("div",{className:o("min-h-0 flex-1 overflow-y-auto overscroll-contain",Y,R&&(Z||U)?m:"",R?"":"-my-1 py-1"),children:K}):null,ss?s("div",{className:o("flex shrink-0 flex-wrap items-center justify-end gap-2",Y,R?m:""),children:L}):null]});return Q?l(r.Root,{open:D,defaultOpen:P,modal:G,disablePointerDismissal:!H,onOpenChange:(s,l)=>{H||s||"escape-key"!==l.reason?O?.(s):l.cancel()},children:[T?s(r.Trigger,{render:T}):null,l(r.Portal,{children:[s(r.Backdrop,{className:`plass-portal ${k}`}),s(r.Viewport,{className:o("plass-portal fixed inset-0 z-(--plass-z-portal) flex",w[d]),children:s(r.Popup,{className:es,style:{...h(z,3),...ls,...J},...M,children:os})})]})]}):D??P??!0?s("div",{className:es,style:{...h(z,0),...ls,...J},...M,children:os}):null}
1
+ "use client";import{jsx as s,jsxs as l,Fragment as e}from"react/jsx-runtime";import{Dialog as a}from"@base-ui/react/dialog";import{CloseIcon as r}from"../../internal/icons.js";import{cx as o,focusRingClasses as d,glassClasses as i,hasContent as t,metaTextClasses as n,sheetBodyClasses as p,sheetHeaderGapClasses as u,sheetLineClasses as m,sheetPaddingXClasses as c,sheetPaddingYClasses as x,sheetSectionGapClasses as f,sheetTitleClasses as g,surfaceSlots as h}from"../../internal/styles.js";const b={xs:"w-56",sm:"w-64",md:"w-80",lg:"w-96",xl:"w-[28rem]"},v={left:{xs:"rounded-r-(--plass-radius-xs)",sm:"rounded-r-(--plass-radius-sm)",md:"rounded-r-(--plass-radius-md)",lg:"rounded-r-(--plass-radius-lg)",xl:"rounded-r-(--plass-radius-xl)"},right:{xs:"rounded-l-(--plass-radius-xs)",sm:"rounded-l-(--plass-radius-sm)",md:"rounded-l-(--plass-radius-md)",lg:"rounded-l-(--plass-radius-lg)",xl:"rounded-l-(--plass-radius-xl)"},top:{xs:"rounded-b-(--plass-radius-xs)",sm:"rounded-b-(--plass-radius-sm)",md:"rounded-b-(--plass-radius-md)",lg:"rounded-b-(--plass-radius-lg)",xl:"rounded-b-(--plass-radius-xl)"},bottom:{xs:"rounded-t-(--plass-radius-xs)",sm:"rounded-t-(--plass-radius-sm)",md:"rounded-t-(--plass-radius-md)",lg:"rounded-t-(--plass-radius-lg)",xl:"rounded-t-(--plass-radius-xl)"}},y={left:"border-r",right:"border-l",top:"border-b",bottom:"border-t"},w={left:"flex-row justify-start",right:"flex-row justify-end",top:"flex-col justify-start",bottom:"flex-col justify-end"},j=/* @__PURE__ */[i,"relative flex flex-col overflow-hidden","text-(--plass-fg) bg-(--plass-glass-press)","[border-color:var(--plass-glass-line)]","[outline:none]"].join(" "),N=/* @__PURE__ */["[transition:opacity_var(--plass-duration)_var(--plass-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" "),k=/* @__PURE__ */["fixed inset-0 z-(--plass-z-portal) bg-(--plass-scrim)","[backdrop-filter:blur(2px)] [-webkit-backdrop-filter:blur(2px)]",N].join(" "),C=/* @__PURE__ */["flex size-[1.6em] shrink-0 cursor-pointer items-center justify-center","rounded-full text-(--plass-muted-fg)","[&_svg]:size-[1.1em] [&_svg]:shrink-0","[transition:background-color_var(--plass-duration)_var(--plass-ease),color_var(--plass-duration)_var(--plass-ease)]","hover:bg-(--p-soft) hover:text-(--plass-fg)",d].join(" ");export const PlDrawerClose=a.Close;export function PlDrawer({side:d="left",mode:i="overlay",size:_="md",color:z="primary",density:$="default",open:D,defaultOpen:P,onOpenChange:O,trigger:T,title:B,description:F,actions:L,dividers:R=!1,showClose:V,closeLabel:q="Close",extent:A,rounded:E=!0,modal:G=!0,dismissible:H=!0,className:I,classNames:J,style:K,children:M,...Q}){const S="overlay"===i,U="left"===d||"right"===d,W=V??S,X=c[$][_],Y=x[$][_],Z=R?`${X} ${Y}`:X,ss=t(B)||t(F),ls=t(L),es=void 0===A?null:{[U?"width":"height"]:"number"==typeof A?`${A}px`:A},as=o(j,p[_],y[d],E?v[d][_]:"",S?"[box-shadow:var(--plass-shadow-4),var(--plass-gloss-glass)]":"[box-shadow:var(--plass-gloss-glass)]",S?N:"",U?`h-full max-w-full ${void 0===A?b[_]:""}`:"w-full "+(void 0===A?"max-h-[85%]":""),R?"":`${Y} ${f[_]}`,I),rs=S?a.Title:"h2",os=S?a.Description:"p",ds=l(e,{children:[ss||W?l("div",{className:o("flex shrink-0 items-start gap-3",Z),children:[l("div",{className:o("flex min-w-0 flex-1 flex-col",u[_]),children:[t(B)?s(rs,{className:o("m-0 font-semibold",g[_]),children:B}):null,t(F)?s(os,{className:o("m-0 text-(--plass-muted-fg)",n[_]),children:F}):null]}),W?S?s(a.Close,{"aria-label":q,className:C,children:s(r,{})}):s("button",{type:"button","aria-label":q,className:C,onClick:()=>O?.(!1),children:s(r,{})}):null]}):null,t(M)?s("div",{className:o("min-h-0 flex-1 overflow-y-auto overscroll-contain",Z,R&&(ss||W)?m:"",R?"":"-my-1 py-1"),children:M}):null,ls?s("div",{className:o("flex shrink-0 flex-wrap items-center justify-end gap-2",Z,R?m:""),children:L}):null]});return S?l(a.Root,{open:D,defaultOpen:P,modal:G,disablePointerDismissal:!H,onOpenChange:(s,l)=>{H||s||"escape-key"!==l.reason?O?.(s):l.cancel()},children:[T?s(a.Trigger,{render:T}):null,l(a.Portal,{children:[s(a.Backdrop,{className:o("plass-portal",k,J?.backdrop)}),s(a.Viewport,{className:o("plass-portal fixed inset-0 z-(--plass-z-portal) flex",w[d]),children:s(a.Popup,{className:as,style:{...h(z,3),...es,...K},...Q,children:ds})})]})]}):D??P??!0?s("div",{className:as,style:{...h(z,0),...es,...K},...Q,children:ds}):null}
@@ -113,6 +113,7 @@ export interface PlMenuGroupProps {
113
113
  label?: React.ReactNode;
114
114
  children?: React.ReactNode;
115
115
  className?: string;
116
+ style?: React.CSSProperties;
116
117
  }
117
118
  export interface PlMenuCheckboxItemProps extends Omit<PlMenuItemProps, 'href' | 'target' | 'startIcon' | 'onClick'> {
118
119
  checked?: boolean;
@@ -133,6 +134,7 @@ export interface PlMenuRadioGroupProps {
133
134
  disabled?: boolean;
134
135
  children?: React.ReactNode;
135
136
  className?: string;
137
+ style?: React.CSSProperties;
136
138
  }
137
139
  export interface PlMenuRadioItemProps extends Omit<PlMenuItemProps, 'href' | 'target' | 'startIcon' | 'onClick'> {
138
140
  /** What this row sets the group to. */
@@ -153,7 +155,7 @@ export declare function PlMenuItem({ onClick, href, target, startIcon, endIcon,
153
155
  /** A row that ticks. The tick lands in the same slot a `startIcon` would. */
154
156
  export declare function PlMenuCheckboxItem({ checked, defaultChecked, onCheckedChange, endIcon, shortcut, description, color, closeOnClick, disabled, label, children, className, style }: PlMenuCheckboxItemProps): React.JSX.Element;
155
157
  /** One choice out of a set. Wraps the rows that make up the set. */
156
- export declare function PlMenuRadioGroup({ value, defaultValue, onValueChange, disabled, children, className }: PlMenuRadioGroupProps): React.JSX.Element;
158
+ export declare function PlMenuRadioGroup({ value, defaultValue, onValueChange, disabled, children, className, style }: PlMenuRadioGroupProps): React.JSX.Element;
157
159
  /**
158
160
  * A row inside a `PlMenuRadioGroup`.
159
161
  *
@@ -163,7 +165,7 @@ export declare function PlMenuRadioGroup({ value, defaultValue, onValueChange, d
163
165
  */
164
166
  export declare function PlMenuRadioItem({ value, endIcon, shortcut, description, color, closeOnClick, disabled, label, children, className, style }: PlMenuRadioItemProps): React.JSX.Element;
165
167
  /** A named run of rows. The label is a heading, not a row — it cannot be picked. */
166
- export declare function PlMenuGroup({ label, children, className }: PlMenuGroupProps): React.JSX.Element;
168
+ export declare function PlMenuGroup({ label, children, className, style }: PlMenuGroupProps): React.JSX.Element;
167
169
  /** The hairline between two runs of rows. */
168
170
  export declare function PlMenuSeparator({ className, ...props }: PlMenuSeparatorProps): React.JSX.Element;
169
171
  /**
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as s,Fragment as l}from"react/jsx-runtime";import*as a from"react";import{Menu as n}from"@base-ui/react/menu";import{ContextMenu as t}from"@base-ui/react/context-menu";import{MenuContext as o}from"../../internal/menu.js";import{CheckIcon as r,ChevronIcon as i,DotIcon as c}from"../../internal/icons.js";import{controlTextLeadingClasses as d,cx as p,gapClasses as u,glassClasses as m,hasContent as h,iconClasses as x,metaTextClasses as f,radiusClasses as g,surfaceSlots as y,transitionClasses as b}from"../../internal/styles.js";const C=/* @__PURE__ */[m,"max-h-[min(24rem,var(--available-height))] min-w-40 overflow-y-auto overscroll-contain","border bg-(--plass-glass-press) p-1","[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(" "),N={default:{xs:"px-1.5 py-0.5",sm:"px-2 py-1",md:"px-2.5 py-1.5",lg:"px-3 py-2",xl:"px-3.5 py-2.5"},compact:{xs:"px-1 py-0.5",sm:"px-1.5 py-0.5",md:"px-2 py-1",lg:"px-2.5 py-1",xl:"px-3 py-1.5"}},v={xs:g.xs,sm:g.xs,md:g.sm,lg:g.sm,xl:g.md};function rowClasses(e,s,l,a){return p("relative flex w-full cursor-pointer items-center select-none",l?"text-(--p-accent)":"text-(--plass-fg)",N[s][e],v[e],u[e],d[e],b,x,"data-[highlighted]:bg-(--p-soft-hover)","data-[popup-open]:bg-(--p-soft)","data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50","[outline:none]",a)}const k="flex h-[1lh] w-[1.2em] shrink-0 items-center justify-center";function shortcutClasses(e){return p("ms-2 shrink-0 text-(--plass-muted-fg) tabular-nums",f[e])}function RowBody({children:l,description:a,size:n}){return h(a)?s("span",{className:"flex min-w-0 flex-1 flex-col text-start",children:[e("span",{className:"truncate",children:l}),e("span",{className:p("truncate text-(--plass-muted-fg)",f[n]),children:a})]}):e("span",{className:"min-w-0 flex-1 truncate text-start",children:l})}export function PlMenuItem({onClick:t,href:r,target:i,startIcon:c,endIcon:d,shortcut:u,description:m,color:x,closeOnClick:f=!0,disabled:g=!1,label:b,children:C,className:N,style:v}){const{size:w,density:O}=a.useContext(o),P=s(l,{children:[h(c)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:c}):null,e(RowBody,{description:m,size:w,children:C}),h(d)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:d}):null,h(u)?e("span",{className:shortcutClasses(w),children:u}):null]}),z=x?y(x,0):void 0,I=z||v?{...z,...v}:void 0;return void 0!==r?e(n.LinkItem,{href:r,target:i,label:b,closeOnClick:f,onClick:t,className:rowClasses(w,O,Boolean(x),N),style:I,children:P}):e(n.Item,{disabled:g,label:b,closeOnClick:f,onClick:t,className:rowClasses(w,O,Boolean(x),N),style:I,children:P})}export function PlMenuCheckboxItem({checked:l,defaultChecked:t,onCheckedChange:i,endIcon:c,shortcut:d,description:u,color:m,closeOnClick:x=!1,disabled:f=!1,label:g,children:b,className:C,style:N}){const{size:v,density:w}=a.useContext(o),O=m?y(m,0):void 0;return s(n.CheckboxItem,{checked:l,defaultChecked:t,onCheckedChange:e=>i?.(e),disabled:f,label:g,closeOnClick:x,className:rowClasses(v,w,Boolean(m),C),style:O||N?{...O,...N}:void 0,children:[e("span",{className:p(k,"text-(--p-accent)"),children:e(n.CheckboxItemIndicator,{className:"flex items-center justify-center",children:e(r,{})})}),e(RowBody,{description:u,size:v,children:b}),h(c)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:c}):null,h(d)?e("span",{className:shortcutClasses(v),children:d}):null]})}export function PlMenuRadioGroup({value:s,defaultValue:l,onValueChange:a,disabled:t=!1,children:o,className:r}){return e(n.RadioGroup,{value:s,defaultValue:l,onValueChange:e=>a?.(e),disabled:t,className:r,children:o})}export function PlMenuRadioItem({value:l,endIcon:t,shortcut:r,description:i,color:d,closeOnClick:u=!1,disabled:m=!1,label:x,children:f,className:g,style:b}){const{size:C,density:N}=a.useContext(o),v=d?y(d,0):void 0;return s(n.RadioItem,{value:l,disabled:m,label:x,closeOnClick:u,className:rowClasses(C,N,Boolean(d),g),style:v||b?{...v,...b}:void 0,children:[e("span",{className:p(k,"text-(--p-accent)"),children:e(n.RadioItemIndicator,{className:"flex items-center justify-center",children:e(c,{})})}),e(RowBody,{description:i,size:C,children:f}),h(t)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:t}):null,h(r)?e("span",{className:shortcutClasses(C),children:r}):null]})}export function PlMenuGroup({label:l,children:t,className:r}){const{size:i,density:c}=a.useContext(o);return s(n.Group,{className:r,children:[h(l)?e(n.GroupLabel,{className:p(N[c][i],f[i],"font-semibold tracking-wide text-(--plass-muted-fg) uppercase"),children:l}):null,t]})}export function PlMenuSeparator({className:s,...l}){return e(n.Separator,{className:p("-mx-1 my-1 h-px bg-(--plass-divider)",s),...l})}export function PlMenuSubmenu({label:l,startIcon:t,disabled:r=!1,side:c="right",sideOffset:u=4,children:m,className:x,style:f}){const{size:b,density:N,color:v}=a.useContext(o);return s(n.SubmenuRoot,{children:[s(n.SubmenuTrigger,{disabled:r,className:rowClasses(b,N,!1),children:[h(t)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:t}):null,e("span",{className:"min-w-0 flex-1 truncate text-start",children:l}),e("span",{className:p(k,"text-(--plass-muted-fg) -rotate-90"),children:e(i,{})})]}),e(n.Portal,{children:e(n.Positioner,{className:"plass-portal z-(--plass-z-portal) [outline:none]",side:c,sideOffset:u,align:"start",children:e(n.Popup,{className:p(C,g[b],d[b],x),style:{...y(v,3),...f},children:m})})})]})}export function PlMenu({size:l="md",color:t="primary",density:r="default",trigger:i,open:c,defaultOpen:u,onOpenChange:m,side:h="bottom",align:x="start",sideOffset:f=6,modal:b=!0,openOnHover:N=!1,loopFocus:v=!0,disabled:k=!1,className:w,style:O,children:P}){const z=a.useMemo(()=>({size:l,color:t,density:r}),[l,t,r]);return e(o.Provider,{value:z,children:s(n.Root,{open:c,defaultOpen:u,onOpenChange:e=>m?.(e),modal:b,loopFocus:v,disabled:k,children:[i?e(n.Trigger,{render:i,openOnHover:N,disabled:k}):null,e(n.Portal,{children:e(n.Positioner,{className:"plass-portal z-(--plass-z-portal) [outline:none]",side:h,align:x,sideOffset:f,children:e(n.Popup,{className:p(C,g[l],d[l],w),style:{...y(t,3),...O},children:P})})})]})})}export function PlContextMenu({size:l="md",color:n="primary",density:r="default",content:i,children:c,open:u,defaultOpen:m,onOpenChange:h,loopFocus:x=!0,disabled:f=!1,className:b,style:N}){const v=a.useMemo(()=>({size:l,color:n,density:r}),[l,n,r]);return e(o.Provider,{value:v,children:s(t.Root,{open:u,defaultOpen:m,onOpenChange:e=>h?.(e),loopFocus:x,disabled:f,children:[e(t.Trigger,{children:c}),e(t.Portal,{children:e(t.Positioner,{className:"plass-portal z-(--plass-z-portal) [outline:none]",children:e(t.Popup,{className:p(C,g[l],d[l],b),style:{...y(n,3),...N},children:i})})})]})})}
1
+ "use client";import{jsx as e,jsxs as s,Fragment as l}from"react/jsx-runtime";import*as a from"react";import{Menu as n}from"@base-ui/react/menu";import{ContextMenu as t}from"@base-ui/react/context-menu";import{MenuContext as o}from"../../internal/menu.js";import{CheckIcon as r,ChevronIcon as i,DotIcon as c}from"../../internal/icons.js";import{controlTextLeadingClasses as d,cx as p,gapClasses as u,glassClasses as m,hasContent as h,iconClasses as x,metaTextClasses as f,radiusClasses as y,surfaceSlots as g,transitionClasses as b}from"../../internal/styles.js";const C=/* @__PURE__ */[m,"max-h-[min(24rem,var(--available-height))] min-w-40 overflow-y-auto overscroll-contain","border bg-(--plass-glass-press) p-1","[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(" "),N={default:{xs:"px-1.5 py-0.5",sm:"px-2 py-1",md:"px-2.5 py-1.5",lg:"px-3 py-2",xl:"px-3.5 py-2.5"},compact:{xs:"px-1 py-0.5",sm:"px-1.5 py-0.5",md:"px-2 py-1",lg:"px-2.5 py-1",xl:"px-3 py-1.5"}},v={xs:y.xs,sm:y.xs,md:y.sm,lg:y.sm,xl:y.md};function rowClasses(e,s,l,a){return p("relative flex w-full cursor-pointer items-center select-none",l?"text-(--p-accent)":"text-(--plass-fg)",N[s][e],v[e],u[e],d[e],b,x,"data-[highlighted]:bg-(--p-soft-hover)","data-[popup-open]:bg-(--p-soft)","data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50","[outline:none]",a)}const k="flex h-[1lh] w-[1.2em] shrink-0 items-center justify-center";function shortcutClasses(e){return p("ms-2 shrink-0 text-(--plass-muted-fg) tabular-nums",f[e])}function RowBody({children:l,description:a,size:n}){return h(a)?s("span",{className:"flex min-w-0 flex-1 flex-col text-start",children:[e("span",{className:"truncate",children:l}),e("span",{className:p("truncate text-(--plass-muted-fg)",f[n]),children:a})]}):e("span",{className:"min-w-0 flex-1 truncate text-start",children:l})}export function PlMenuItem({onClick:t,href:r,target:i,startIcon:c,endIcon:d,shortcut:u,description:m,color:x,closeOnClick:f=!0,disabled:y=!1,label:b,children:C,className:N,style:v}){const{size:w,density:O}=a.useContext(o),P=s(l,{children:[h(c)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:c}):null,e(RowBody,{description:m,size:w,children:C}),h(d)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:d}):null,h(u)?e("span",{className:shortcutClasses(w),children:u}):null]}),z=x?g(x,0):void 0,I=z||v?{...z,...v}:void 0;return void 0!==r?e(n.LinkItem,{href:r,target:i,label:b,closeOnClick:f,onClick:t,className:rowClasses(w,O,Boolean(x),N),style:I,children:P}):e(n.Item,{disabled:y,label:b,closeOnClick:f,onClick:t,className:rowClasses(w,O,Boolean(x),N),style:I,children:P})}export function PlMenuCheckboxItem({checked:l,defaultChecked:t,onCheckedChange:i,endIcon:c,shortcut:d,description:u,color:m,closeOnClick:x=!1,disabled:f=!1,label:y,children:b,className:C,style:N}){const{size:v,density:w}=a.useContext(o),O=m?g(m,0):void 0;return s(n.CheckboxItem,{checked:l,defaultChecked:t,onCheckedChange:e=>i?.(e),disabled:f,label:y,closeOnClick:x,className:rowClasses(v,w,Boolean(m),C),style:O||N?{...O,...N}:void 0,children:[e("span",{className:p(k,"text-(--p-accent)"),children:e(n.CheckboxItemIndicator,{className:"flex items-center justify-center",children:e(r,{})})}),e(RowBody,{description:u,size:v,children:b}),h(c)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:c}):null,h(d)?e("span",{className:shortcutClasses(v),children:d}):null]})}export function PlMenuRadioGroup({value:s,defaultValue:l,onValueChange:a,disabled:t=!1,children:o,className:r,style:i}){return e(n.RadioGroup,{value:s,defaultValue:l,onValueChange:e=>a?.(e),disabled:t,className:r,style:i,children:o})}export function PlMenuRadioItem({value:l,endIcon:t,shortcut:r,description:i,color:d,closeOnClick:u=!1,disabled:m=!1,label:x,children:f,className:y,style:b}){const{size:C,density:N}=a.useContext(o),v=d?g(d,0):void 0;return s(n.RadioItem,{value:l,disabled:m,label:x,closeOnClick:u,className:rowClasses(C,N,Boolean(d),y),style:v||b?{...v,...b}:void 0,children:[e("span",{className:p(k,"text-(--p-accent)"),children:e(n.RadioItemIndicator,{className:"flex items-center justify-center",children:e(c,{})})}),e(RowBody,{description:i,size:C,children:f}),h(t)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:t}):null,h(r)?e("span",{className:shortcutClasses(C),children:r}):null]})}export function PlMenuGroup({label:l,children:t,className:r,style:i}){const{size:c,density:d}=a.useContext(o);return s(n.Group,{className:r,style:i,children:[h(l)?e(n.GroupLabel,{className:p(N[d][c],f[c],"font-semibold tracking-wide text-(--plass-muted-fg) uppercase"),children:l}):null,t]})}export function PlMenuSeparator({className:s,...l}){return e(n.Separator,{className:p("-mx-1 my-1 h-px bg-(--plass-divider)",s),...l})}export function PlMenuSubmenu({label:l,startIcon:t,disabled:r=!1,side:c="right",sideOffset:u=4,children:m,className:x,style:f}){const{size:b,density:N,color:v}=a.useContext(o);return s(n.SubmenuRoot,{children:[s(n.SubmenuTrigger,{disabled:r,className:rowClasses(b,N,!1),children:[h(t)?e("span",{className:p(k,"text-(--plass-muted-fg)"),children:t}):null,e("span",{className:"min-w-0 flex-1 truncate text-start",children:l}),e("span",{className:p(k,"text-(--plass-muted-fg) -rotate-90"),children:e(i,{})})]}),e(n.Portal,{children:e(n.Positioner,{className:"plass-portal z-(--plass-z-portal) [outline:none]",side:c,sideOffset:u,align:"start",children:e(n.Popup,{className:p(C,y[b],d[b],x),style:{...g(v,3),...f},children:m})})})]})}export function PlMenu({size:l="md",color:t="primary",density:r="default",trigger:i,open:c,defaultOpen:u,onOpenChange:m,side:h="bottom",align:x="start",sideOffset:f=6,modal:b=!0,openOnHover:N=!1,loopFocus:v=!0,disabled:k=!1,className:w,style:O,children:P}){const z=a.useMemo(()=>({size:l,color:t,density:r}),[l,t,r]);return e(o.Provider,{value:z,children:s(n.Root,{open:c,defaultOpen:u,onOpenChange:e=>m?.(e),modal:b,loopFocus:v,disabled:k,children:[i?e(n.Trigger,{render:i,openOnHover:N,disabled:k}):null,e(n.Portal,{children:e(n.Positioner,{className:"plass-portal z-(--plass-z-portal) [outline:none]",side:h,align:x,sideOffset:f,children:e(n.Popup,{className:p(C,y[l],d[l],w),style:{...g(t,3),...O},children:P})})})]})})}export function PlContextMenu({size:l="md",color:n="primary",density:r="default",content:i,children:c,open:u,defaultOpen:m,onOpenChange:h,loopFocus:x=!0,disabled:f=!1,className:b,style:N}){const v=a.useMemo(()=>({size:l,color:n,density:r}),[l,n,r]);return e(o.Provider,{value:v,children:s(t.Root,{open:u,defaultOpen:m,onOpenChange:e=>h?.(e),loopFocus:x,disabled:f,children:[e(t.Trigger,{children:c}),e(t.Portal,{children:e(t.Positioner,{className:"plass-portal z-(--plass-z-portal) [outline:none]",children:e(t.Popup,{className:p(C,y[l],d[l],b),style:{...g(n,3),...N},children:i})})})]})})}
@@ -29,6 +29,10 @@ export interface PlMenubarMenuProps {
29
29
  disabled?: boolean;
30
30
  /** The rows, written exactly as they are inside a `PlMenu`. */
31
31
  children?: React.ReactNode;
32
+ /** Classes on the word this menu is opened by, alongside the bar's own. */
33
+ className?: string;
34
+ /** Inline styles on that word. */
35
+ style?: React.CSSProperties;
32
36
  }
33
37
  /**
34
38
  * One menu on the bar: the word, and the rows behind it.
@@ -39,7 +43,7 @@ export interface PlMenubarMenuProps {
39
43
  * `PlMenuGroup` and `PlMenuSubmenu` a `PlMenu` takes, because it *is* the same
40
44
  * menu.
41
45
  */
42
- export declare function PlMenubarMenu({ label, startIcon, disabled, children }: PlMenubarMenuProps): React.ReactElement;
46
+ export declare function PlMenubarMenu({ label, startIcon, disabled, children, className, style }: PlMenubarMenuProps): React.ReactElement;
43
47
  /**
44
48
  * The strip of words at the top of an application — File, Edit, View — each of
45
49
  * which opens a menu.
@@ -1 +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})})});
1
+ "use client";import{jsxs as e,jsx as t}from"react/jsx-runtime";import*as s from"react";import{Menubar as o}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:o,startIcon:p,disabled:m=!1,children:h,className:v,style:x}){const{size:g,color:y,density:j}=s.useContext(n);return t(r,{size:g,color:y,density:j,disabled:m,openOnHover:!0,sideOffset:4,trigger:e("button",{type:"button",disabled:m,className:i(b,f[g],a[g],l[g],d["default"===j?"compact":j][g],u[g],v),style:x,children:[c(p)?p:null,o]}),children:h})}export const PlMenubar=/* @__PURE__ */s.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=s.useMemo(()=>({size:e,color:r,density:a}),[e,r,a]);return t(n.Provider,{value:x,children:t(o,{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})})});
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { Dialog as BaseUIDialog } from '@base-ui/react/dialog';
3
- import type { PlassStyleProps } from '../../types.js';
3
+ import type { PlassPortalClassNames, PlassStyleProps } from '../../types.js';
4
4
  /**
5
5
  * A modal takes `size`, `color` and `density` and stops there.
6
6
  *
@@ -9,6 +9,8 @@ import type { PlassStyleProps } from '../../types.js';
9
9
  * page. There is no `elevation` either — see `popupClasses`.
10
10
  */
11
11
  export interface PlModalProps extends Pick<PlassStyleProps, 'size' | 'color' | 'density'>, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'title' | 'children'> {
12
+ /** Classes on the parts a `className` does not reach. */
13
+ classNames?: PlassPortalClassNames;
12
14
  /** The modal is shown. Use with `onOpenChange` for a controlled modal. */
13
15
  open?: boolean;
14
16
  /** Whether it starts open, for an uncontrolled one. */
@@ -109,4 +111,4 @@ export declare const PlModalClose: React.ForwardRefExoticComponent<Omit<import("
109
111
  * the header and the actions stay put while only the body scrolls, which is why
110
112
  * `dividers` matters more here than on a PlCard.
111
113
  */
112
- export declare function PlModal({ size, color, density, open, defaultOpen, onOpenChange, trigger, title, description, actions, dividers, showClose, closeLabel, width, fullWidth, fullScreen, modal, dismissible, className, style, children, ...props }: PlModalProps): React.JSX.Element;
114
+ export declare function PlModal({ size, color, density, open, defaultOpen, onOpenChange, trigger, title, description, actions, dividers, showClose, closeLabel, width, fullWidth, fullScreen, modal, dismissible, className, classNames, style, children, ...props }: PlModalProps): React.JSX.Element;
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as l}from"react/jsx-runtime";import{Dialog as s}from"@base-ui/react/dialog";import{CloseIcon as a}from"../../internal/icons.js";import{focusRingClasses as i,glassClasses as o,hasContent as r,metaTextClasses as t,radiusClasses as n,sheetBodyClasses as d,sheetHeaderGapClasses as c,sheetLineClasses as p,sheetPaddingXClasses as m,sheetPaddingYClasses as f,sheetSectionGapClasses as u,sheetTitleClasses as x,surfaceSlots as h}from"../../internal/styles.js";const g={xs:"max-w-80",sm:"max-w-96",md:"max-w-lg",lg:"max-w-2xl",xl:"max-w-4xl"},v=/* @__PURE__ */[o,"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-4),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=/* @__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(" ");export const PlModalClose=s.Close;export function PlModal({size:o="md",color:b="primary",density:w="default",open:j,defaultOpen:$,onOpenChange:N,trigger:k,title:_,description:z,actions:C,dividers:P=!1,showClose:B=!0,closeLabel:O="Close",width:D,fullWidth:M=!0,fullScreen:T=!1,modal:W=!0,dismissible:L=!0,className:R,style:S,children:V,...q}){const A=m[w][o],E=f[w][o],F=P?`${A} ${E}`:A,G=r(_)||r(z),H=r(C);return l(s.Root,{open:j,defaultOpen:$,modal:W,disablePointerDismissal:!L,onOpenChange:(e,l)=>{L||e||"escape-key"!==l.reason?N?.(e):l.cancel()},children:[k?e(s.Trigger,{render:k}):null,l(s.Portal,{children:[e(s.Backdrop,{className:`plass-portal ${y}`}),e(s.Viewport,{className:["plass-portal fixed inset-0 z-(--plass-z-portal) flex justify-center",T?"items-stretch":"items-center p-4"].join(" "),children:l(s.Popup,{className:[v,d[o],T?"h-full max-w-none rounded-none":`max-h-full ${n[o]} ${void 0===D?g[o]:""}`,T||M?"":"w-auto",P?"":`${E} ${u[o]}`,R??""].filter(Boolean).join(" "),style:{...h(b,3),...void 0===D?null:{maxWidth:"number"==typeof D?`${D}px`:D},...S},...q,children:[G||B?l("div",{className:`flex shrink-0 items-start gap-3 ${F}`,children:[l("div",{className:`flex min-w-0 flex-1 flex-col ${c[o]}`,children:[r(_)?e(s.Title,{className:`m-0 font-semibold ${x[o]}`,children:_}):null,r(z)?e(s.Description,{className:`m-0 text-(--plass-muted-fg) ${t[o]}`,children:z}):null]}),B?e(s.Close,{"aria-label":O,className:["flex size-[1.6em] shrink-0 cursor-pointer items-center justify-center","rounded-full text-(--plass-muted-fg)","[&_svg]:size-[1.1em] [&_svg]:shrink-0","[transition:background-color_var(--plass-duration)_var(--plass-ease),color_var(--plass-duration)_var(--plass-ease)]","hover:bg-(--p-soft) hover:text-(--plass-fg)",i].join(" "),children:e(a,{})}):null]}):null,r(V)?e("div",{className:["min-h-0 flex-1 overflow-y-auto overscroll-contain",F,P&&(G||B)?p:"",P?"":"-my-1 py-1"].filter(Boolean).join(" "),children:V}):null,H?e("div",{className:["flex shrink-0 flex-wrap items-center justify-end gap-2",F,P?p:""].filter(Boolean).join(" "),children:C}):null]})})]})]})}
1
+ "use client";import{jsx as e,jsxs as s}from"react/jsx-runtime";import{Dialog as l}from"@base-ui/react/dialog";import{CloseIcon as a}from"../../internal/icons.js";import{cx as i,focusRingClasses as o,glassClasses as r,hasContent as t,metaTextClasses as n,radiusClasses as d,sheetBodyClasses as c,sheetHeaderGapClasses as p,sheetLineClasses as m,sheetPaddingXClasses as f,sheetPaddingYClasses as u,sheetSectionGapClasses as x,sheetTitleClasses as h,surfaceSlots as g}from"../../internal/styles.js";const v={xs:"max-w-80",sm:"max-w-96",md:"max-w-lg",lg:"max-w-2xl",xl:"max-w-4xl"},y=/* @__PURE__ */[r,"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-4),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(" "),b=/* @__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(" ");export const PlModalClose=l.Close;export function PlModal({size:r="md",color:w="primary",density:j="default",open:N,defaultOpen:k,onOpenChange:$,trigger:_,title:z,description:C,actions:P,dividers:B=!1,showClose:O=!0,closeLabel:D="Close",width:M,fullWidth:T=!0,fullScreen:W=!1,modal:L=!0,dismissible:R=!0,className:S,classNames:V,style:q,children:A,...E}){const F=f[j][r],G=u[j][r],H=B?`${F} ${G}`:F,I=t(z)||t(C),J=t(P);return s(l.Root,{open:N,defaultOpen:k,modal:L,disablePointerDismissal:!R,onOpenChange:(e,s)=>{R||e||"escape-key"!==s.reason?$?.(e):s.cancel()},children:[_?e(l.Trigger,{render:_}):null,s(l.Portal,{children:[e(l.Backdrop,{className:i("plass-portal",b,V?.backdrop)}),e(l.Viewport,{className:["plass-portal fixed inset-0 z-(--plass-z-portal) flex justify-center",W?"items-stretch":"items-center p-4"].join(" "),children:s(l.Popup,{className:[y,c[r],W?"h-full max-w-none rounded-none":`max-h-full ${d[r]} ${void 0===M?v[r]:""}`,W||T?"":"w-auto",B?"":`${G} ${x[r]}`,S??""].filter(Boolean).join(" "),style:{...g(w,3),...void 0===M?null:{maxWidth:"number"==typeof M?`${M}px`:M},...q},...E,children:[I||O?s("div",{className:`flex shrink-0 items-start gap-3 ${H}`,children:[s("div",{className:`flex min-w-0 flex-1 flex-col ${p[r]}`,children:[t(z)?e(l.Title,{className:`m-0 font-semibold ${h[r]}`,children:z}):null,t(C)?e(l.Description,{className:`m-0 text-(--plass-muted-fg) ${n[r]}`,children:C}):null]}),O?e(l.Close,{"aria-label":D,className:["flex size-[1.6em] shrink-0 cursor-pointer items-center justify-center","rounded-full text-(--plass-muted-fg)","[&_svg]:size-[1.1em] [&_svg]:shrink-0","[transition:background-color_var(--plass-duration)_var(--plass-ease),color_var(--plass-duration)_var(--plass-ease)]","hover:bg-(--p-soft) hover:text-(--plass-fg)",o].join(" "),children:e(a,{})}):null]}):null,t(A)?e("div",{className:["min-h-0 flex-1 overflow-y-auto overscroll-contain",H,B&&(I||O)?m:"",B?"":"-my-1 py-1"].filter(Boolean).join(" "),children:A}):null,J?e("div",{className:["flex shrink-0 flex-wrap items-center justify-end gap-2",H,B?m:""].filter(Boolean).join(" "),children:P}):null]})})]})]})}
@@ -52,6 +52,10 @@ export interface PlNavigationMenuItemProps {
52
52
  columns?: number;
53
53
  /** The panel's contents — usually `PlNavigationMenuLink`s. */
54
54
  children?: React.ReactNode;
55
+ /** Classes on the word in the row, alongside the component's own. */
56
+ className?: string;
57
+ /** Inline styles on that word. */
58
+ style?: React.CSSProperties;
55
59
  }
56
60
  export interface PlNavigationMenuLinkProps extends Omit<React.ComponentPropsWithoutRef<'a'>, 'color' | 'title'> {
57
61
  /** Where it goes. */
@@ -80,7 +84,7 @@ export declare const PlNavigationMenuLink: React.ForwardRefExoticComponent<PlNav
80
84
  * is a link, and the difference is not cosmetic — the second is announced as a
81
85
  * destination and the first as something that expands.
82
86
  */
83
- export declare function PlNavigationMenuItem({ label, href, target, rel, startIcon, value, disabled, columns, children }: PlNavigationMenuItemProps): React.ReactElement;
87
+ export declare function PlNavigationMenuItem({ label, href, target, rel, startIcon, value, disabled, columns, children, className, style }: PlNavigationMenuItemProps): React.ReactElement;
84
88
  /**
85
89
  * A site's navigation: a row of destinations, some of which open a panel of
86
90
  * more of them.
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as a,Fragment as t}from"react/jsx-runtime";import*as s from"react";import{NavigationMenu as n}from"@base-ui/react/navigation-menu";import{ChevronIcon as l}from"../../internal/icons.js";import{safeRel as r}from"../../internal/link.js";import{controlHeightClasses as i,controlTextClasses as o,controlTextLeadingClasses as d,cx as c,focusRingClasses as p,focusRingInsetClasses as u,gapClasses as m,glassClasses as f,hasContent as h,iconClasses as g,metaTextClasses as v,paddingXClasses as x,radiusClasses as y,surfaceSlots as N,transitionClasses as b}from"../../internal/styles.js";const w=/* @__PURE__ */s.createContext({size:"md",density:"default"}),j=/* @__PURE__ */["inline-flex shrink-0 cursor-pointer select-none items-center justify-center","whitespace-nowrap font-medium leading-none no-underline","text-(--plass-fg) bg-transparent","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",b,g,p,"hover:bg-(--p-soft)","data-[popup-open]:bg-(--p-soft-hover) data-[popup-open]:text-(--p-accent)","data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50","data-[disabled]:saturate-[0.35] data-[disabled]:hover:bg-transparent"].join(" "),P=/* @__PURE__ */[f,"relative 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] overflow-hidden","[transition:opacity_var(--plass-duration)_var(--plass-ease),width_var(--plass-duration)_var(--plass-ease),height_var(--plass-duration)_var(--plass-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" "),k=/* @__PURE__ */["flex min-w-0 cursor-pointer items-start no-underline","text-(--plass-fg) bg-transparent",b,g,"hover:bg-(--p-soft)",u].join(" "),z={xs:"p-1",sm:"p-1.5",md:"p-2",lg:"p-2.5",xl:"p-3"};export const PlNavigationMenuLink=/* @__PURE__ */s.forwardRef(function PlNavigationMenuLink({href:t,title:l,description:r,startIcon:i,className:o,children:p,...u},f){const{size:g,density:N}=s.useContext(w);return a(n.Link,{ref:f,href:t,className:c(k,y[g],m[g],x[N][g],"py-2",o),...u,children:[h(i)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:i}):null,a("span",{className:"flex min-w-0 flex-col gap-0.5",children:[e("span",{className:c("font-medium",d[g]),children:l}),h(r)?e("span",{className:c("text-(--plass-muted-fg)",v[g]),children:r}):null,p]})]})});export function PlNavigationMenuItem({label:d,href:p,target:u,rel:f,startIcon:g,value:v,disabled:N=!1,columns:b=1,children:P}){const{size:k,density:_}=s.useContext(w),C=void 0!==p&&!h(P),M=c(j,i[k],o[k],m[k],x[_][k],y[k]);return e(n.Item,{value:v,children:C?a(n.Link,{href:p,target:u,rel:r(u,f),className:M,children:[h(g)?g:null,d]}):a(t,{children:[a(n.Trigger,{disabled:N,className:M,children:[h(g)?g:null,d,e(n.Icon,{className:"flex items-center [transition:rotate_var(--plass-duration)_var(--plass-ease)] data-[popup-open]:rotate-180",children:e(l,{})})]}),e(n.Content,{className:c("grid gap-1",z[k]),style:b>1?{gridTemplateColumns:`repeat(${b}, minmax(0, 1fr))`}:void 0,children:P})]})})}export const PlNavigationMenu=/* @__PURE__ */s.forwardRef(function PlNavigationMenu({size:t="md",color:l="primary",density:r="default",orientation:i="horizontal",value:o,defaultValue:d,onValueChange:p,delay:u,closeDelay:f,sideOffset:h=8,className:g,style:v,children:x,...b},j){const k=s.useMemo(()=>({size:t,density:r}),[t,r]);return e(w.Provider,{value:k,children:a(n.Root,{ref:j,orientation:i,value:o,defaultValue:d,onValueChange:e=>p?.(e),delay:u,closeDelay:f,className:g,style:{...N(l,3),...v},...b,children:[e(n.List,{className:c("flex items-center","vertical"===i?"flex-col items-stretch":"flex-row",m[t]),children:x}),e(n.Portal,{children:e(n.Positioner,{className:"plass-portal z-(--plass-z-portal) [outline:none]",sideOffset:h,collisionPadding:12,children:e(n.Popup,{className:c(P,y[t]),children:e(n.Viewport,{})})})})]})})});
1
+ "use client";import{jsx as e,jsxs as a,Fragment as s}from"react/jsx-runtime";import*as t from"react";import{NavigationMenu as n}from"@base-ui/react/navigation-menu";import{ChevronIcon as l}from"../../internal/icons.js";import{safeRel as r}from"../../internal/link.js";import{controlHeightClasses as i,controlTextClasses as o,controlTextLeadingClasses as d,cx as c,focusRingClasses as p,focusRingInsetClasses as u,gapClasses as m,glassClasses as f,hasContent as h,iconClasses as g,metaTextClasses as v,paddingXClasses as x,radiusClasses as y,surfaceSlots as N,transitionClasses as b}from"../../internal/styles.js";const w=/* @__PURE__ */t.createContext({size:"md",density:"default"}),j=/* @__PURE__ */["inline-flex shrink-0 cursor-pointer select-none items-center justify-center","whitespace-nowrap font-medium leading-none no-underline","text-(--plass-fg) bg-transparent","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",b,g,p,"hover:bg-(--p-soft)","data-[popup-open]:bg-(--p-soft-hover) data-[popup-open]:text-(--p-accent)","data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50","data-[disabled]:saturate-[0.35] data-[disabled]:hover:bg-transparent"].join(" "),P=/* @__PURE__ */[f,"relative 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] overflow-hidden","[transition:opacity_var(--plass-duration)_var(--plass-ease),width_var(--plass-duration)_var(--plass-ease),height_var(--plass-duration)_var(--plass-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" "),k=/* @__PURE__ */["flex min-w-0 cursor-pointer items-start no-underline","text-(--plass-fg) bg-transparent",b,g,"hover:bg-(--p-soft)",u].join(" "),z={xs:"p-1",sm:"p-1.5",md:"p-2",lg:"p-2.5",xl:"p-3"};export const PlNavigationMenuLink=/* @__PURE__ */t.forwardRef(function PlNavigationMenuLink({href:s,title:l,description:r,startIcon:i,className:o,children:p,...u},f){const{size:g,density:N}=t.useContext(w);return a(n.Link,{ref:f,href:s,className:c(k,y[g],m[g],x[N][g],"py-2",o),...u,children:[h(i)?e("span",{className:"flex h-[1lh] shrink-0 items-center",children:i}):null,a("span",{className:"flex min-w-0 flex-col gap-0.5",children:[e("span",{className:c("font-medium",d[g]),children:l}),h(r)?e("span",{className:c("text-(--plass-muted-fg)",v[g]),children:r}):null,p]})]})});export function PlNavigationMenuItem({label:d,href:p,target:u,rel:f,startIcon:g,value:v,disabled:N=!1,columns:b=1,children:P,className:k,style:_}){const{size:C,density:M}=t.useContext(w),I=void 0!==p&&!h(P),L=c(j,i[C],o[C],m[C],x[M][C],y[C],k);return e(n.Item,{value:v,children:I?a(n.Link,{href:p,target:u,rel:r(u,f),className:L,style:_,children:[h(g)?g:null,d]}):a(s,{children:[a(n.Trigger,{disabled:N,className:L,style:_,children:[h(g)?g:null,d,e(n.Icon,{className:"flex items-center [transition:rotate_var(--plass-duration)_var(--plass-ease)] data-[popup-open]:rotate-180",children:e(l,{})})]}),e(n.Content,{className:c("grid gap-1",z[C]),style:b>1?{gridTemplateColumns:`repeat(${b}, minmax(0, 1fr))`}:void 0,children:P})]})})}export const PlNavigationMenu=/* @__PURE__ */t.forwardRef(function PlNavigationMenu({size:s="md",color:l="primary",density:r="default",orientation:i="horizontal",value:o,defaultValue:d,onValueChange:p,delay:u,closeDelay:f,sideOffset:h=8,className:g,style:v,children:x,...b},j){const k=t.useMemo(()=>({size:s,density:r}),[s,r]);return e(w.Provider,{value:k,children:a(n.Root,{ref:j,orientation:i,value:o,defaultValue:d,onValueChange:e=>p?.(e),delay:u,closeDelay:f,className:g,style:{...N(l,3),...v},...b,children:[e(n.List,{className:c("flex items-center","vertical"===i?"flex-col items-stretch":"flex-row",m[s]),children:x}),e(n.Portal,{children:e(n.Positioner,{className:"plass-portal z-(--plass-z-portal) [outline:none]",sideOffset:h,collisionPadding:12,children:e(n.Popup,{className:c(P,y[s]),children:e(n.Viewport,{})})})})]})})});
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { PlassElevation, PlassStyleProps } from '../../types.js';
2
+ import type { PlassElevation, PlassFieldClassNames, PlassStyleProps } from '../../types.js';
3
3
  /**
4
4
  * Where the two steppers sit.
5
5
  *
@@ -15,6 +15,8 @@ import type { PlassElevation, PlassStyleProps } from '../../types.js';
15
15
  */
16
16
  export type PlNumberFieldSteppers = 'end' | 'split' | 'none';
17
17
  export interface PlNumberFieldProps extends PlassStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'children'> {
18
+ /** Classes on the parts a `className` does not reach. */
19
+ classNames?: PlassFieldClassNames;
18
20
  /**
19
21
  * Drop shadow depth. `0` is the default — a field is a well cut into the
20
22
  * sheet, not a key resting on it.
@@ -130,4 +132,4 @@ export interface PlNumberFieldProps extends PlassStyleProps, Omit<React.Componen
130
132
  * clamping, the press-and-hold repeat on the steppers, and the hidden input that
131
133
  * submits with a form.
132
134
  */
133
- export declare function PlNumberField({ variant, size, color, density, elevation, value, defaultValue, onValueChange, onValueCommitted, min, max, step, largeStep, smallStep, snapOnStep, allowWheelScrub, format, locale, steppers, incrementLabel, decrementLabel, label, description, error, invalid, startIcon, endIcon, fullWidth, disabled, readOnly, required, name, placeholder, id, className, style, ...props }: PlNumberFieldProps): React.JSX.Element;
135
+ export declare function PlNumberField({ variant, size, color, density, elevation, value, defaultValue, onValueChange, onValueCommitted, min, max, step, largeStep, smallStep, snapOnStep, allowWheelScrub, format, locale, steppers, incrementLabel, decrementLabel, label, description, error, invalid, startIcon, endIcon, fullWidth, disabled, readOnly, required, name, placeholder, id, className, classNames, style, ...props }: PlNumberFieldProps): React.JSX.Element;
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import{NumberField as l}from"@base-ui/react/number-field";import{Field as t}from"@base-ui/react/field";import{MinusIcon as s,PlusIcon as n}from"../../internal/icons.js";import{controlHeightClasses as r,controlTextLeadingClasses as i,disabledClasses as o,fieldReadOnlyClasses as c,fieldRestClasses as d,focusRingClasses as p,focusWithinRingClasses as m,gapClasses as u,hasContent as f,iconClasses as h,metaTextClasses as b,paddingXClasses as x,radiusClasses as g,stackGapClasses as v,surfaceSlots as N,transitionClasses as j}from"../../internal/styles.js";const y=/* @__PURE__ */["group relative flex w-full cursor-text items-center","[-webkit-tap-highlight-color:transparent]",j,"focus-within:[transition-duration:0ms]",m,h].join(" "),w=/* @__PURE__ */["inline-flex size-[1.7em] shrink-0 cursor-pointer items-center justify-center","rounded-(--plass-radius-xs) text-(--plass-muted-fg) select-none","[&_svg]:size-[0.9em] [&_svg]:shrink-0","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]","[transition:background-color_var(--plass-duration)_var(--plass-ease),color_var(--plass-duration)_var(--plass-ease),opacity_var(--plass-duration)_var(--plass-ease)]","active:[transition-duration:0ms]","hover:bg-(--p-soft) hover:text-(--p-accent)","active:bg-(--p-soft-press)",p,"disabled:cursor-not-allowed disabled:bg-transparent disabled:opacity-40"].join(" ");export function PlNumberField({variant:p="glass",size:m="md",color:h="primary",density:j="default",elevation:k=0,value:S,defaultValue:_,onValueChange:V,onValueCommitted:I,min:C,max:O,step:$,largeStep:z,smallStep:B,snapOnStep:D,allowWheelScrub:L=!1,format:W,locale:q,steppers:F="end",incrementLabel:R="Increase",decrementLabel:E="Decrease",label:G,description:P,error:A,invalid:H,startIcon:J,endIcon:K,fullWidth:M=!1,disabled:Q=!1,readOnly:T=!1,required:U=!1,name:X,placeholder:Y,id:Z,className:ee,style:ae,...le}){const te=f(A),se=H??te,ne=se?"danger":h,re=x[j][m],ie={end:`${re} pe-1`,split:"px-1",none:re},oe=e(l.Decrement,{"aria-label":E,className:w,children:e(s,{})}),ce=e(l.Increment,{"aria-label":R,className:w,children:e(n,{})}),de="none"!==F&&!T;return a(t.Root,{disabled:Q,invalid:se,className:["flex-col align-top",v[m],M?"flex w-full":"inline-flex",ee??""].filter(Boolean).join(" "),style:{...N(ne,k),...ae},...le,children:[G?e(t.Label,{className:[b[m],"font-medium text-(--plass-fg)",Q?"opacity-50":""].filter(Boolean).join(" "),children:G}):null,e(l.Root,{id:Z,name:X,className:"contents",value:S,defaultValue:_,onValueChange:e=>V?.(e),onValueCommitted:e=>I?.(e),min:C,max:O,step:$,largeStep:z,smallStep:B,snapOnStep:D,allowWheelScrub:L,format:W,locale:q,disabled:Q,readOnly:T,required:U,children:a(l.Group,{className:[y,r[m],i[m],g[m],u[m],de?ie[F]:re,Q?o[p]:T?c[p]:d[p]].join(" "),children:[de&&"split"===F?oe:null,J?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)",children:J}):null,e(l.Input,{placeholder:Y,className:["min-w-0 flex-1 self-stretch bg-transparent [font:inherit] text-inherit","[outline:none]","tabular-nums","split"===F&&de?"text-center":"","placeholder:text-(--plass-muted-fg)","caret-(--p-accent) selection:bg-(--p-soft-press)","disabled:cursor-not-allowed"].filter(Boolean).join(" ")}),K?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)",children:K}):null,de&&"end"===F?a("span",{className:"flex shrink-0 items-center gap-0.5",children:[oe,ce]}):null,de&&"split"===F?ce:null]})}),P?e(t.Description,{className:`${b[m]} text-(--plass-muted-fg)`,children:P}):null,e(t.Error,te?{match:!0,className:`${b[m]} text-(--p-accent)`,children:A}:{className:`${b[m]} text-(--p-accent)`})]})}
1
+ "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import{NumberField as l}from"@base-ui/react/number-field";import{Field as t}from"@base-ui/react/field";import{MinusIcon as s,PlusIcon as n}from"../../internal/icons.js";import{controlHeightClasses as r,controlTextLeadingClasses as i,cx as o,disabledClasses as c,fieldReadOnlyClasses as d,fieldRestClasses as p,focusRingClasses as m,focusWithinRingClasses as u,gapClasses as f,hasContent as h,iconClasses as b,metaTextClasses as x,paddingXClasses as g,radiusClasses as v,stackGapClasses as N,surfaceSlots as j,transitionClasses as y}from"../../internal/styles.js";const w=/* @__PURE__ */["group relative flex w-full cursor-text items-center","[-webkit-tap-highlight-color:transparent]",y,"focus-within:[transition-duration:0ms]",u,b].join(" "),k=/* @__PURE__ */["inline-flex size-[1.7em] shrink-0 cursor-pointer items-center justify-center","rounded-(--plass-radius-xs) text-(--plass-muted-fg) select-none","[&_svg]:size-[0.9em] [&_svg]:shrink-0","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]","[transition:background-color_var(--plass-duration)_var(--plass-ease),color_var(--plass-duration)_var(--plass-ease),opacity_var(--plass-duration)_var(--plass-ease)]","active:[transition-duration:0ms]","hover:bg-(--p-soft) hover:text-(--p-accent)","active:bg-(--p-soft-press)",m,"disabled:cursor-not-allowed disabled:bg-transparent disabled:opacity-40"].join(" ");export function PlNumberField({variant:m="glass",size:u="md",color:b="primary",density:y="default",elevation:S=0,value:_,defaultValue:V,onValueChange:I,onValueCommitted:C,min:O,max:z,step:B,largeStep:D,smallStep:L,snapOnStep:W,allowWheelScrub:q=!1,format:F,locale:R,steppers:E="end",incrementLabel:G="Increase",decrementLabel:P="Decrease",label:$,description:A,error:H,invalid:J,startIcon:K,endIcon:M,fullWidth:Q=!1,disabled:T=!1,readOnly:U=!1,required:X=!1,name:Y,placeholder:Z,id:ee,className:ae,classNames:le,style:te,...se}){const ne=h(H),re=J??ne,ie=re?"danger":b,oe=g[y][u],ce={end:`${oe} pe-1`,split:"px-1",none:oe},de=e(l.Decrement,{"aria-label":P,className:k,children:e(s,{})}),pe=e(l.Increment,{"aria-label":G,className:k,children:e(n,{})}),me="none"!==E&&!U;return a(t.Root,{disabled:T,invalid:re,className:["flex-col align-top",N[u],Q?"flex w-full":"inline-flex",ae??""].filter(Boolean).join(" "),style:{...j(ie,S),...te},...se,children:[$?e(t.Label,{className:o(x[u],"font-medium text-(--plass-fg)",T?"opacity-50":"",le?.label),children:$}):null,e(l.Root,{id:ee,name:Y,className:"contents",value:_,defaultValue:V,onValueChange:e=>I?.(e),onValueCommitted:e=>C?.(e),min:O,max:z,step:B,largeStep:D,smallStep:L,snapOnStep:W,allowWheelScrub:q,format:F,locale:R,disabled:T,readOnly:U,required:X,children:a(l.Group,{className:[w,r[u],i[u],v[u],f[u],me?ce[E]:oe,T?c[m]:U?d[m]:p[m],le?.control].filter(Boolean).join(" "),children:[me&&"split"===E?de:null,K?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)",children:K}):null,e(l.Input,{placeholder:Z,className:["min-w-0 flex-1 self-stretch bg-transparent [font:inherit] text-inherit","[outline:none]","tabular-nums","split"===E&&me?"text-center":"","placeholder:text-(--plass-muted-fg)","caret-(--p-accent) selection:bg-(--p-soft-press)","disabled:cursor-not-allowed"].filter(Boolean).join(" ")}),M?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)",children:M}):null,me&&"end"===E?a("span",{className:"flex shrink-0 items-center gap-0.5",children:[de,pe]}):null,me&&"split"===E?pe:null]})}),A?e(t.Description,{className:o(x[u],"text-(--plass-muted-fg)",le?.description),children:A}):null,e(t.Error,ne?{match:!0,className:o(x[u],"text-(--p-accent)",le?.error),children:H}:{className:o(x[u],"text-(--p-accent)",le?.error)})]})}
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { PlassElevation, PlassStyleProps } from '../../types.js';
2
+ import type { PlassElevation, PlassFieldClassNames, PlassStyleProps } from '../../types.js';
3
3
  /**
4
4
  * What may be typed into a slot.
5
5
  *
@@ -9,6 +9,8 @@ import type { PlassElevation, PlassStyleProps } from '../../types.js';
9
9
  */
10
10
  export type PlOtpCharset = 'numeric' | 'alpha' | 'alphanumeric' | 'any';
11
11
  export interface PlOtpFieldProps extends PlassStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'onChange' | 'children'> {
12
+ /** Classes on the parts a `className` does not reach. */
13
+ classNames?: PlassFieldClassNames;
12
14
  /** Drop shadow depth. `0` is the default — a field is cut into the sheet. */
13
15
  elevation?: PlassElevation;
14
16
  /**
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{Field as l}from"@base-ui/react/field";import{OTPField as r}from"@base-ui/react/otp-field";import{cx as n,disabledClasses as s,fieldReadOnlyClasses as i,fieldRestClasses as o,hasContent as m,metaTextClasses as d,stackGapClasses as u,surfaceSlots as c,transitionClasses as p}from"../../internal/styles.js";const f={xs:"h-7 w-6",sm:"h-8 w-7",md:"h-10 w-8",lg:"h-12 w-10",xl:"h-14 w-12"},x={xs:"rounded-[0.3125rem]",sm:"rounded-[0.375rem]",md:"rounded-[0.4375rem]",lg:"rounded-[0.5625rem]",xl:"rounded-[0.6875rem]"},g={xs:"text-[0.8125rem]",sm:"text-[0.9375rem]",md:"text-[1.0625rem]",lg:"text-[1.25rem]",xl:"text-[1.5rem]"},h={default:{xs:"gap-1",sm:"gap-1",md:"gap-1.5",lg:"gap-2",xl:"gap-2.5"},compact:{xs:"gap-0.5",sm:"gap-0.5",md:"gap-1",lg:"gap-1",xl:"gap-1.5"}},y={numeric:"numeric",alpha:"alpha",alphanumeric:"alphanumeric",any:"none"};export const PlOtpField=/* @__PURE__ */t.forwardRef(function PlOtpField({variant:b="glass",size:v="md",color:N="primary",density:V="default",elevation:w=0,length:F=6,charset:j="numeric",mask:C=!1,groupSize:M,separator:O="–",value:I,defaultValue:R,onValueChange:S,onComplete:k,onValueInvalid:q,autoSubmit:z=!1,label:P,description:_,error:A,invalid:D,name:E,required:L=!1,disabled:T=!1,readOnly:B=!1,autoFocus:G=!1,className:H,style:J,...K},Q){const U=Math.min(12,Math.max(2,Math.round(F))),W=m(A),X=D??W,Y=X?"danger":N,Z=n("text-center font-medium [font-family:inherit]",f[v],g[v],x[v],p,"caret-(--p-accent) selection:bg-(--p-soft-press)","focus:[outline:2px_solid_var(--p-ring)] focus:[outline-offset:0px]","focus:[transition-duration:0ms]",T?s[b]:B?i[b]:o[b]),$=M&&M>0?Math.round(M):0;return a(l.Root,{disabled:T,invalid:X,className:n("inline-flex flex-col align-top",u[v],H),style:{...c(Y,w),...J},children:[m(P)?e(l.Label,{className:n(d[v],"font-medium",T?"text-(--plass-muted-fg)":"text-(--plass-fg)"),children:P}):null,e(r.Root,{ref:Q,length:U,validationType:y[j],mask:C,name:E,required:L,disabled:T,readOnly:B,autoSubmit:z,value:I,defaultValue:R,onValueChange:e=>S?.(e),onValueComplete:e=>k?.(e),onValueInvalid:e=>q?.(e),className:n("flex items-center",h[V][v]),...K,children:Array.from({length:U},(l,s)=>a(t.Fragment,{children:[$>0&&s>0&&s%$===0?e("span",{"aria-hidden":"true",className:n("select-none px-0.5 text-(--plass-muted-fg)",g[v]),children:O}):null,e(r.Input,{className:Z,autoFocus:G&&0===s})]},s))}),m(_)?e(l.Description,{className:n(d[v],"text-(--plass-muted-fg)"),children:_}):null,e(l.Error,W?{match:!0,className:n(d[v],"text-(--p-accent)"),children:A}:{className:n(d[v],"text-(--p-accent)")})]})});
1
+ "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as t from"react";import{Field as l}from"@base-ui/react/field";import{OTPField as r}from"@base-ui/react/otp-field";import{cx as n,disabledClasses as s,fieldReadOnlyClasses as o,fieldRestClasses as i,hasContent as m,metaTextClasses as d,stackGapClasses as u,surfaceSlots as c,transitionClasses as p}from"../../internal/styles.js";const f={xs:"h-7 w-6",sm:"h-8 w-7",md:"h-10 w-8",lg:"h-12 w-10",xl:"h-14 w-12"},x={xs:"rounded-[0.3125rem]",sm:"rounded-[0.375rem]",md:"rounded-[0.4375rem]",lg:"rounded-[0.5625rem]",xl:"rounded-[0.6875rem]"},g={xs:"text-[0.8125rem]",sm:"text-[0.9375rem]",md:"text-[1.0625rem]",lg:"text-[1.25rem]",xl:"text-[1.5rem]"},h={default:{xs:"gap-1",sm:"gap-1",md:"gap-1.5",lg:"gap-2",xl:"gap-2.5"},compact:{xs:"gap-0.5",sm:"gap-0.5",md:"gap-1",lg:"gap-1",xl:"gap-1.5"}},b={numeric:"numeric",alpha:"alpha",alphanumeric:"alphanumeric",any:"none"};export const PlOtpField=/* @__PURE__ */t.forwardRef(function PlOtpField({variant:y="glass",size:v="md",color:N="primary",density:V="default",elevation:w=0,length:F=6,charset:j="numeric",mask:C=!1,groupSize:M,separator:O="–",value:I,defaultValue:R,onValueChange:S,onComplete:k,onValueInvalid:q,autoSubmit:z=!1,label:P,description:_,error:A,invalid:D,name:E,required:L=!1,disabled:T=!1,readOnly:B=!1,autoFocus:G=!1,className:H,classNames:J,style:K,...Q},U){const W=Math.min(12,Math.max(2,Math.round(F))),X=m(A),Y=D??X,Z=Y?"danger":N,$=n("text-center font-medium [font-family:inherit]",f[v],g[v],x[v],p,"caret-(--p-accent) selection:bg-(--p-soft-press)","focus:[outline:2px_solid_var(--p-ring)] focus:[outline-offset:0px]","focus:[transition-duration:0ms]",T?s[y]:B?o[y]:i[y]),ee=M&&M>0?Math.round(M):0;return a(l.Root,{disabled:T,invalid:Y,className:n("inline-flex flex-col align-top",u[v],H),style:{...c(Z,w),...K},children:[m(P)?e(l.Label,{className:n(d[v],"font-medium",T?"text-(--plass-muted-fg)":"text-(--plass-fg)",J?.label),children:P}):null,e(r.Root,{ref:U,length:W,validationType:b[j],mask:C,name:E,required:L,disabled:T,readOnly:B,autoSubmit:z,value:I,defaultValue:R,onValueChange:e=>S?.(e),onValueComplete:e=>k?.(e),onValueInvalid:e=>q?.(e),className:n("flex items-center",h[V][v],J?.control),...Q,children:Array.from({length:W},(l,s)=>a(t.Fragment,{children:[ee>0&&s>0&&s%ee===0?e("span",{"aria-hidden":"true",className:n("select-none px-0.5 text-(--plass-muted-fg)",g[v]),children:O}):null,e(r.Input,{className:$,autoFocus:G&&0===s})]},s))}),m(_)?e(l.Description,{className:n(d[v],"text-(--plass-muted-fg)",J?.description),children:_}):null,e(l.Error,X?{match:!0,className:n(d[v],"text-(--p-accent)",J?.error),children:A}:{className:n(d[v],"text-(--p-accent)",J?.error)})]})});
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { PlassAlign, PlassColor, PlassSize } from '../../types.js';
2
+ import type { PlassAlign, PlassColor, PlassPortalClassNames, PlassSize } from '../../types.js';
3
3
  /**
4
4
  * How much of the page the overlay takes away.
5
5
  *
@@ -28,6 +28,8 @@ export type PlOverlayTone = 'scrim' | 'glass' | 'solid' | 'clear';
28
28
  * shadow is a scrim with an edge.
29
29
  */
30
30
  export interface PlOverlayProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'children'> {
31
+ /** Classes on the parts a `className` does not reach. */
32
+ classNames?: PlassPortalClassNames;
31
33
  /** The overlay is shown. Use with `onOpenChange` for a controlled overlay. */
32
34
  open?: boolean;
33
35
  /** Whether the overlay starts shown, for an uncontrolled one. */
@@ -93,4 +95,4 @@ export interface PlOverlayProps extends Omit<React.ComponentPropsWithoutRef<'div
93
95
  * held inside, the page behind going inert, and focus returning to wherever it
94
96
  * came from when the overlay closes.
95
97
  */
96
- export declare function PlOverlay({ open, defaultOpen, onOpenChange, tone, dismissible, modal, align, size, color, label, className, style, children, ...props }: PlOverlayProps): React.JSX.Element;
98
+ export declare function PlOverlay({ open, defaultOpen, onOpenChange, tone, dismissible, modal, align, size, color, label, className, classNames, style, children, ...props }: PlOverlayProps): React.JSX.Element;
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Dialog as s}from"@base-ui/react/dialog";import{surfaceSlots as l}from"../../internal/styles.js";const r={scrim:"bg-(--plass-scrim) [backdrop-filter:blur(2px)] [-webkit-backdrop-filter:blur(2px)]",glass:/* @__PURE__ */["[background-color:color-mix(in_oklab,var(--plass-scrim)_45%,transparent)]","[backdrop-filter:var(--plass-blur)] [-webkit-backdrop-filter:var(--plass-blur)]"].join(" "),solid:"bg-(--plass-surface)",clear:""},t={start:"items-start",center:"items-center",end:"items-end"},i={xs:"p-3",sm:"p-4",md:"p-6",lg:"p-8",xl:"p-10"},o=/* @__PURE__ */["[transition:opacity_var(--plass-duration)_var(--plass-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" ");export function PlOverlay({open:n,defaultOpen:p,onOpenChange:c,tone:m="scrim",dismissible:d=!1,modal:f=!0,align:u="center",size:b="md",color:x="primary",label:y="Overlay",className:g,style:j,children:k,...h}){return e(s.Root,{open:n,defaultOpen:p,modal:f,disablePointerDismissal:!d,onOpenChange:(e,a)=>{d||e||"escape-key"!==a.reason?c?.(e):a.cancel()},children:a(s.Portal,{children:[e(s.Backdrop,{className:`plass-portal fixed inset-0 z-(--plass-z-portal) ${o} ${r[m]}`}),e(s.Viewport,{className:["plass-portal fixed inset-0 z-(--plass-z-portal) flex justify-center",t[u],i[b]].join(" "),children:e(s.Popup,{"aria-label":y,className:["flex max-h-full max-w-full flex-col items-center justify-center","[outline:none]",o,g??""].filter(Boolean).join(" "),style:{...l(x,0),...j},...h,children:k})})]})})}
1
+ "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import{Dialog as s}from"@base-ui/react/dialog";import{cx as l,surfaceSlots as r}from"../../internal/styles.js";const t={scrim:"bg-(--plass-scrim) [backdrop-filter:blur(2px)] [-webkit-backdrop-filter:blur(2px)]",glass:/* @__PURE__ */["[background-color:color-mix(in_oklab,var(--plass-scrim)_45%,transparent)]","[backdrop-filter:var(--plass-blur)] [-webkit-backdrop-filter:var(--plass-blur)]"].join(" "),solid:"bg-(--plass-surface)",clear:""},i={start:"items-start",center:"items-center",end:"items-end"},o={xs:"p-3",sm:"p-4",md:"p-6",lg:"p-8",xl:"p-10"},n=/* @__PURE__ */["[transition:opacity_var(--plass-duration)_var(--plass-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0"].join(" ");export function PlOverlay({open:p,defaultOpen:c,onOpenChange:m,tone:d="scrim",dismissible:f=!1,modal:b=!0,align:u="center",size:x="md",color:y="primary",label:g="Overlay",className:k,classNames:j,style:h,children:v,...O}){return e(s.Root,{open:p,defaultOpen:c,modal:b,disablePointerDismissal:!f,onOpenChange:(e,a)=>{f||e||"escape-key"!==a.reason?m?.(e):a.cancel()},children:a(s.Portal,{children:[e(s.Backdrop,{className:l("plass-portal fixed inset-0 z-(--plass-z-portal)",n,t[d],j?.backdrop)}),e(s.Viewport,{className:["plass-portal fixed inset-0 z-(--plass-z-portal) flex justify-center",i[u],o[x]].join(" "),children:e(s.Popup,{"aria-label":g,className:["flex max-h-full max-w-full flex-col items-center justify-center","[outline:none]",n,k??""].filter(Boolean).join(" "),style:{...r(y,0),...h},...O,children:v})})]})})}
@@ -1,8 +1,10 @@
1
1
  import * as React from 'react';
2
2
  import { Radio as BaseUIRadio } from '@base-ui/react/radio';
3
3
  import { RadioGroup as BaseUIRadioGroup } from '@base-ui/react/radio-group';
4
- import type { PlassColor, PlassOrientation, PlassSize } from '../../types.js';
4
+ import type { PlassColor, PlassFieldClassNames, PlassOrientation, PlassSize } from '../../types.js';
5
5
  export interface PlRadioGroupProps extends Omit<React.ComponentPropsWithoutRef<typeof BaseUIRadioGroup>, 'className' | 'style' | 'render'> {
6
+ /** Classes on the parts a `className` does not reach. */
7
+ classNames?: PlassFieldClassNames;
6
8
  /** @default 'md' */
7
9
  size?: PlassSize;
8
10
  /** @default 'primary' */
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as r from"react";import{Radio as l}from"@base-ui/react/radio";import{RadioGroup as o}from"@base-ui/react/radio-group";import{Field as s}from"@base-ui/react/field";import{controlSlots as t,focusRingClasses as i,glassClasses as c,hasContent as d,metaTextClasses as n,tickDotClasses as p,tickRowTextClasses as m,tickSizeClasses as f,transitionClasses as u}from"../../internal/styles.js";const h=/* @__PURE__ */r.createContext({size:"md",color:"primary",readOnly:!1}),b=/* @__PURE__ */["relative inline-flex shrink-0 items-center justify-center rounded-full border","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",u,i].join(" "),g=/* @__PURE__ */[c,"cursor-pointer bg-(--plass-glass) [border-color:var(--plass-border)]","hover:bg-(--plass-glass-hover) hover:[border-color:var(--p-line)]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent] data-[checked]:hover:brightness-105"].join(" "),x=/* @__PURE__ */[c,"cursor-default bg-(--plass-glass) [border-color:var(--plass-border)]","saturate-[0.55]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent]"].join(" "),v=/* @__PURE__ */[c,"cursor-not-allowed bg-(--plass-glass) [border-color:var(--plass-border)]","opacity-50 saturate-[0.35]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent]"].join(" ");export const PlRadio=/* @__PURE__ */r.forwardRef(function PlRadio({label:o,description:t,disabled:i=!1,className:c,style:d,...u},k){const y=r.useContext(h),N=u.readOnly??y.readOnly;return e(s.Root,{disabled:i,className:["flex flex-col",c??""].filter(Boolean).join(" "),style:d,children:a("div",{className:`flex items-start gap-2 ${m[y.size]}`,children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(l.Root,{ref:k,className:[b,f[y.size],i?v:N?x:g].join(" "),disabled:i,...u,children:e(l.Indicator,{className:`rounded-full bg-current ${p[y.size]}`})})}),o||t?a("span",{className:"flex min-w-0 flex-col gap-0.5",children:[o?e(s.Label,{className:i?"text-(--plass-muted-fg)":"cursor-pointer text-(--plass-fg)",children:o}):null,t?e(s.Description,{className:`${n[y.size]} text-(--plass-muted-fg)`,children:t}):null]}):null]})})});export const PlRadioGroup=/* @__PURE__ */r.forwardRef(function PlRadioGroup({size:l="md",color:i="primary",orientation:c="vertical",label:p,description:m,error:f,invalid:u,disabled:b=!1,readOnly:g=!1,className:x,style:v,children:k,...y},N){const j=d(f),R=u??j,z=R?"danger":i,w=r.useMemo(()=>({size:l,color:z,readOnly:g}),[l,z,g]);return e(h.Provider,{value:w,children:a(s.Root,{disabled:b,invalid:R,className:["flex flex-col gap-1.5",x??""].filter(Boolean).join(" "),style:{...t(z,0,"solid"),...v},children:[p?e(s.Label,{className:[n[l],"font-semibold",b?"text-(--plass-muted-fg)":"text-(--plass-fg)"].join(" "),children:p}):null,m?e(s.Description,{className:`${n[l]} text-(--plass-muted-fg)`,children:m}):null,e(o,{ref:N,disabled:b,readOnly:g,className:["flex","horizontal"===c?"flex-row flex-wrap gap-x-5 gap-y-2":"flex-col gap-2"].join(" "),...y,children:k}),e(s.Error,j?{match:!0,className:`${n[l]} text-(--p-accent)`,children:f}:{className:`${n[l]} text-(--p-accent)`})]})})});
1
+ "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as r from"react";import{Radio as l}from"@base-ui/react/radio";import{RadioGroup as o}from"@base-ui/react/radio-group";import{Field as s}from"@base-ui/react/field";import{controlSlots as t,cx as i,focusRingClasses as c,glassClasses as d,hasContent as n,metaTextClasses as p,tickDotClasses as m,tickRowTextClasses as f,tickSizeClasses as u,transitionClasses as h}from"../../internal/styles.js";const b=/* @__PURE__ */r.createContext({size:"md",color:"primary",readOnly:!1}),g=/* @__PURE__ */["relative inline-flex shrink-0 items-center justify-center rounded-full border","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",h,c].join(" "),x=/* @__PURE__ */[d,"cursor-pointer bg-(--plass-glass) [border-color:var(--plass-border)]","hover:bg-(--plass-glass-hover) hover:[border-color:var(--p-line)]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent] data-[checked]:hover:brightness-105"].join(" "),v=/* @__PURE__ */[d,"cursor-default bg-(--plass-glass) [border-color:var(--plass-border)]","saturate-[0.55]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent]"].join(" "),N=/* @__PURE__ */[d,"cursor-not-allowed bg-(--plass-glass) [border-color:var(--plass-border)]","opacity-50 saturate-[0.35]","data-[checked]:[background-image:var(--p-fill)] data-[checked]:text-(--p-on-solid)","data-[checked]:[border-color:transparent]"].join(" ");export const PlRadio=/* @__PURE__ */r.forwardRef(function PlRadio({label:o,description:t,disabled:i=!1,className:c,style:d,...n},h){const k=r.useContext(b),y=n.readOnly??k.readOnly;return e(s.Root,{disabled:i,className:["flex flex-col",c??""].filter(Boolean).join(" "),style:d,children:a("div",{className:`flex items-start gap-2 ${f[k.size]}`,children:[e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(l.Root,{ref:h,className:[g,u[k.size],i?N:y?v:x].join(" "),disabled:i,...n,children:e(l.Indicator,{className:`rounded-full bg-current ${m[k.size]}`})})}),o||t?a("span",{className:"flex min-w-0 flex-col gap-0.5",children:[o?e(s.Label,{className:i?"text-(--plass-muted-fg)":"cursor-pointer text-(--plass-fg)",children:o}):null,t?e(s.Description,{className:`${p[k.size]} text-(--plass-muted-fg)`,children:t}):null]}):null]})})});export const PlRadioGroup=/* @__PURE__ */r.forwardRef(function PlRadioGroup({size:l="md",color:c="primary",orientation:d="vertical",label:m,description:f,error:u,invalid:h,disabled:g=!1,readOnly:x=!1,className:v,classNames:N,style:k,children:y,...j},R){const z=n(u),w=h??z,O=w?"danger":c,P=r.useMemo(()=>({size:l,color:O,readOnly:x}),[l,O,x]);return e(b.Provider,{value:P,children:a(s.Root,{disabled:g,invalid:w,className:["flex flex-col gap-1.5",v??""].filter(Boolean).join(" "),style:{...t(O,0,"solid"),...k},children:[m?e(s.Label,{className:i(p[l],"font-semibold",g?"text-(--plass-muted-fg)":"text-(--plass-fg)",N?.label),children:m}):null,f?e(s.Description,{className:i(p[l],"text-(--plass-muted-fg)",N?.description),children:f}):null,e(o,{ref:R,disabled:g,readOnly:x,className:i("flex","horizontal"===d?"flex-row flex-wrap gap-x-5 gap-y-2":"flex-col gap-2",N?.control),...j,children:y}),e(s.Error,z?{match:!0,className:i(p[l],"text-(--p-accent)",N?.error),children:u}:{className:i(p[l],"text-(--p-accent)",N?.error)})]})})});
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { PlassElevation, PlassStyleProps } from '../../types.js';
2
+ import type { PlassElevation, PlassFieldClassNames, PlassStyleProps } from '../../types.js';
3
3
  /**
4
4
  * What a select's value may be.
5
5
  *
@@ -19,6 +19,8 @@ export interface PlSelectOption {
19
19
  disabled?: boolean;
20
20
  }
21
21
  export interface PlSelectProps extends PlassStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'children'> {
22
+ /** Classes on the parts a `className` does not reach. */
23
+ classNames?: PlassFieldClassNames;
22
24
  /**
23
25
  * The options, as data. There is no `<PlSelect.Option>` to compose: what a
24
26
  * caller has is almost always an array already, and the list has to be
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as l from"react";import{Select as t}from"@base-ui/react/select";import{Field as s}from"@base-ui/react/field";import{CheckIcon as r,ChevronIcon as i}from"../../internal/icons.js";import{WidthSizer as n}from"../../internal/sizer.js";import{controlHeightClasses as o,controlTextLeadingClasses as c,disabledClasses as d,fieldReadOnlyClasses as m,fieldRestClasses as p,focusWithinRingClasses as u,gapClasses as h,glassClasses as f,hasContent as g,iconClasses as x,metaTextClasses as v,paddingXClasses as b,radiusClasses as N,stackGapClasses as j,surfaceSlots as w,transitionClasses as y}from"../../internal/styles.js";const I=/* @__PURE__ */["group relative flex w-full cursor-pointer items-center select-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",y,u,x].join(" "),S=/* @__PURE__ */[f,"max-h-[min(20rem,var(--available-height))] overflow-y-auto overscroll-contain","min-w-[var(--anchor-width)] border bg-(--plass-glass-press) p-1","[border-color:var(--plass-glass-line)]","[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]","[outline:none]"].join(" "),$=/* @__PURE__ */["relative flex cursor-pointer items-center gap-2 select-none","rounded-(--plass-radius-xs) py-1.5 pe-2 ps-7",y,"data-[highlighted]:bg-(--p-soft-hover) data-[highlighted]:text-(--p-accent)","data-[selected]:font-semibold data-[selected]:text-(--p-accent)","data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50","[outline:none]"].join(" ");export const PlSelect=/* @__PURE__ */l.forwardRef(function PlSelect({variant:u="glass",size:f="md",color:x="primary",density:y="default",elevation:z=0,items:P,value:V,defaultValue:k,onValueChange:O,placeholder:R,label:T,description:q,error:C,invalid:M,startIcon:W,fullWidth:_=!1,disabled:B=!1,readOnly:D=!1,required:E=!1,name:L,id:A,className:F,style:G,...H},J){const K=g(C),Q=M??K,U=Q?"danger":x,X=l.useMemo(()=>P.map(e=>({label:e.label??String(e.value),value:e.value})),[P]),Y=l.useMemo(()=>[...P.map(e=>e.label??String(e.value)),...g(R)?[R]:[]],[P,R]);return a(s.Root,{disabled:B,invalid:Q,className:["flex-col align-top",j[f],_?"flex w-full":"inline-flex",F??""].filter(Boolean).join(" "),style:{...w(U,z),...G},...H,children:[T?e(s.Label,{className:[v[f],"font-semibold",B?"text-(--plass-muted-fg)":"text-(--plass-fg)"].join(" "),children:T}):null,a(t.Root,{id:A,name:L,items:X,value:V,defaultValue:k,onValueChange:e=>O?.(e),disabled:B,readOnly:D,required:E,children:[a(t.Trigger,{ref:J,className:[I,o[f],c[f],N[f],h[f],b[y][f],B?d[u]:D?`${m[u]} cursor-default`:p[u]].join(" "),children:[W?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)",children:W}):null,a("span",{className:"flex min-w-0 flex-1 flex-col",children:[e(t.Value,{className:["w-full truncate text-start","data-[placeholder]:text-(--plass-muted-fg)"].join(" "),placeholder:R}),e(n,{samples:Y})]}),e(t.Icon,{className:["flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)","[transition:rotate_var(--plass-duration)_var(--plass-ease)]","data-[popup-open]:rotate-180"].join(" "),children:e(i,{})})]}),e(t.Portal,{children:e(t.Positioner,{className:"plass-portal z-(--plass-z-portal) [outline:none]",sideOffset:6,alignItemWithTrigger:!1,children:e(t.Popup,{className:`${S} ${N[f]} ${c[f]}`,style:w(U,3),children:P.map(l=>a(t.Item,{value:l.value,disabled:l.disabled,className:$,children:[e(t.ItemIndicator,{className:"absolute start-1.5 flex size-4 items-center justify-center",children:e(r,{})}),e(t.ItemText,{className:"truncate",children:l.label??String(l.value)})]},String(l.value)))})})})]}),q?e(s.Description,{className:`${v[f]} text-(--plass-muted-fg)`,children:q}):null,e(s.Error,K?{match:!0,className:`${v[f]} text-(--p-accent)`,children:C}:{className:`${v[f]} text-(--p-accent)`})]})});
1
+ "use client";import{jsx as e,jsxs as a}from"react/jsx-runtime";import*as l from"react";import{Select as t}from"@base-ui/react/select";import{Field as s}from"@base-ui/react/field";import{CheckIcon as r,ChevronIcon as i}from"../../internal/icons.js";import{WidthSizer as n}from"../../internal/sizer.js";import{controlHeightClasses as o,controlTextLeadingClasses as c,cx as d,disabledClasses as m,fieldReadOnlyClasses as p,fieldRestClasses as u,focusWithinRingClasses as h,gapClasses as f,glassClasses as g,hasContent as x,iconClasses as v,metaTextClasses as b,paddingXClasses as N,radiusClasses as j,stackGapClasses as w,surfaceSlots as y,transitionClasses as I}from"../../internal/styles.js";const S=/* @__PURE__ */["group relative flex w-full cursor-pointer items-center select-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",I,h,v].join(" "),z=/* @__PURE__ */[g,"max-h-[min(20rem,var(--available-height))] overflow-y-auto overscroll-contain","min-w-[var(--anchor-width)] border bg-(--plass-glass-press) p-1","[border-color:var(--plass-glass-line)]","[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]","[outline:none]"].join(" "),P=/* @__PURE__ */["relative flex cursor-pointer items-center gap-2 select-none","rounded-(--plass-radius-xs) py-1.5 pe-2 ps-7",I,"data-[highlighted]:bg-(--p-soft-hover) data-[highlighted]:text-(--p-accent)","data-[selected]:font-semibold data-[selected]:text-(--p-accent)","data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50","[outline:none]"].join(" ");export const PlSelect=/* @__PURE__ */l.forwardRef(function PlSelect({variant:h="glass",size:g="md",color:v="primary",density:I="default",elevation:V=0,items:$,value:k,defaultValue:O,onValueChange:R,placeholder:T,label:q,description:B,error:C,invalid:M,startIcon:W,fullWidth:_=!1,disabled:D=!1,readOnly:E=!1,required:L=!1,name:A,id:F,className:G,classNames:H,style:J,...K},Q){const U=x(C),X=M??U,Y=X?"danger":v,Z=l.useMemo(()=>$.map(e=>({label:e.label??String(e.value),value:e.value})),[$]),ee=l.useMemo(()=>[...$.map(e=>e.label??String(e.value)),...x(T)?[T]:[]],[$,T]);return a(s.Root,{disabled:D,invalid:X,className:["flex-col align-top",w[g],_?"flex w-full":"inline-flex",G??""].filter(Boolean).join(" "),style:{...y(Y,V),...J},...K,children:[q?e(s.Label,{className:d(b[g],"font-semibold",D?"text-(--plass-muted-fg)":"text-(--plass-fg)",H?.label),children:q}):null,a(t.Root,{id:F,name:A,items:Z,value:k,defaultValue:O,onValueChange:e=>R?.(e),disabled:D,readOnly:E,required:L,children:[a(t.Trigger,{ref:Q,className:[S,o[g],c[g],j[g],f[g],N[I][g],D?m[h]:E?`${p[h]} cursor-default`:u[h],H?.control].filter(Boolean).join(" "),children:[W?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)",children:W}):null,a("span",{className:"flex min-w-0 flex-1 flex-col",children:[e(t.Value,{className:["w-full truncate text-start","data-[placeholder]:text-(--plass-muted-fg)"].join(" "),placeholder:T}),e(n,{samples:ee})]}),e(t.Icon,{className:["flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)","[transition:rotate_var(--plass-duration)_var(--plass-ease)]","data-[popup-open]:rotate-180"].join(" "),children:e(i,{})})]}),e(t.Portal,{children:e(t.Positioner,{className:"plass-portal z-(--plass-z-portal) [outline:none]",sideOffset:6,alignItemWithTrigger:!1,children:e(t.Popup,{className:`${z} ${j[g]} ${c[g]}`,style:y(Y,3),children:$.map(l=>a(t.Item,{value:l.value,disabled:l.disabled,className:P,children:[e(t.ItemIndicator,{className:"absolute start-1.5 flex size-4 items-center justify-center",children:e(r,{})}),e(t.ItemText,{className:"truncate",children:l.label??String(l.value)})]},String(l.value)))})})})]}),B?e(s.Description,{className:d(b[g],"text-(--plass-muted-fg)",H?.description),children:B}):null,e(s.Error,U?{match:!0,className:d(b[g],"text-(--p-accent)",H?.error),children:C}:{className:d(b[g],"text-(--p-accent)",H?.error)})]})});
@@ -1,10 +1,12 @@
1
1
  import * as React from 'react';
2
2
  import { Switch as BaseUISwitch } from '@base-ui/react/switch';
3
- import type { PlassAlign, PlassColor, PlassSize } from '../../types.js';
3
+ import type { PlassAlign, PlassColor, PlassFieldClassNames, PlassSize } from '../../types.js';
4
4
  /** Which side of the track the label sits on. */
5
5
  export type PlSwitchLabelPlacement = Extract<PlassAlign, 'start' | 'end'>;
6
6
  type BaseSwitchProps = Omit<React.ComponentPropsWithoutRef<typeof BaseUISwitch.Root>, 'className' | 'style' | 'render' | 'children'>;
7
7
  export interface PlSwitchProps extends BaseSwitchProps {
8
+ /** Classes on the parts a `className` does not reach. */
9
+ classNames?: PlassFieldClassNames;
8
10
  /** @default 'md' */
9
11
  size?: PlassSize;
10
12
  /** @default 'primary' */
@@ -1 +1 @@
1
- "use client";import{jsx as a,jsxs as e,Fragment as t}from"react/jsx-runtime";import*as l from"react";import{Switch as r}from"@base-ui/react/switch";import{Field as s}from"@base-ui/react/field";import{controlSlots as i,focusRingClasses as c,hasContent as n,metaTextClasses as o,tickRowTextClasses as d}from"../../internal/styles.js";const h={xs:"h-3.5 w-6",sm:"h-4 w-7",md:"h-5 w-9",lg:"h-6 w-11",xl:"h-7 w-13"},m={xs:"data-[checked]:left-[calc(100%-0.75rem)]",sm:"data-[checked]:left-[calc(100%-0.875rem)]",md:"data-[checked]:left-[calc(100%-1.125rem)]",lg:"data-[checked]:left-[calc(100%-1.375rem)]",xl:"data-[checked]:left-[calc(100%-1.625rem)]"},p=/* @__PURE__ */["relative inline-flex shrink-0 rounded-full","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]","[transition-property:background-color,background-image,box-shadow,filter]","[transition-duration:var(--plass-duration)]","[transition-timing-function:var(--plass-ease)]",c].join(" "),f=/* @__PURE__ */["cursor-pointer bg-(--plass-track)","hover:brightness-[0.97] dark:hover:brightness-110","data-[checked]:[background-image:var(--p-fill)]","data-[checked]:[box-shadow:var(--p-lift)] data-[checked]:hover:brightness-105"].join(" "),u=/* @__PURE__ */["cursor-default bg-(--plass-track) saturate-[0.55]","data-[checked]:[background-image:var(--p-fill)]","data-[checked]:shadow-none"].join(" "),g=/* @__PURE__ */["cursor-not-allowed bg-(--plass-track)","opacity-50 saturate-[0.35] shadow-none","data-[checked]:[background-image:var(--p-fill)]"].join(" "),b=/* @__PURE__ */["absolute inset-y-0.5 left-0.5 aspect-square rounded-full bg-white","[box-shadow:0_1px_2px_rgb(20_40_90/0.25)]","[transition:left_var(--plass-duration)_var(--plass-ease)]"].join(" ");export const PlSwitch=/* @__PURE__ */l.forwardRef(function PlSwitch({size:l="md",color:c="primary",label:x,description:k,error:w,invalid:v,labelPlacement:j="end",disabled:N=!1,readOnly:y=!1,className:_,style:$,...P},R){const S=n(w),B=v??S,O=B?"danger":c,q=a("span",{className:"flex h-[1lh] shrink-0 items-center",children:a(r.Root,{ref:R,className:[p,h[l],N?g:y?u:f].join(" "),disabled:N,readOnly:y,...P,children:a(r.Thumb,{className:`${b} ${m[l]}`})})}),z=x||k?e("span",{className:["flex min-w-0 flex-col gap-0.5","start"===j?"flex-1":""].filter(Boolean).join(" "),children:[x?a(s.Label,{className:N?"text-(--plass-muted-fg)":"cursor-pointer text-(--plass-fg)",children:x}):null,k?a(s.Description,{className:`${o[l]} text-(--plass-muted-fg)`,children:k}):null]}):null;return e(s.Root,{disabled:N,invalid:B,className:["inline-flex flex-col gap-1 align-top",_??""].filter(Boolean).join(" "),style:{...i(O,0,"solid"),...$},children:[a("div",{className:`flex items-start gap-2.5 ${d[l]}`,children:e(t,"start"===j?{children:[z,q]}:{children:[q,z]})}),a(s.Error,S?{match:!0,className:`${o[l]} text-(--p-accent)`,children:w}:{className:`${o[l]} text-(--p-accent)`})]})});
1
+ "use client";import{jsx as e,jsxs as a,Fragment as r}from"react/jsx-runtime";import*as t from"react";import{Switch as l}from"@base-ui/react/switch";import{Field as s}from"@base-ui/react/field";import{controlSlots as c,cx as i,focusRingClasses as n,hasContent as o,metaTextClasses as d,tickRowTextClasses as h}from"../../internal/styles.js";const m={xs:"h-3.5 w-6",sm:"h-4 w-7",md:"h-5 w-9",lg:"h-6 w-11",xl:"h-7 w-13"},p={xs:"data-[checked]:left-[calc(100%-0.75rem)]",sm:"data-[checked]:left-[calc(100%-0.875rem)]",md:"data-[checked]:left-[calc(100%-1.125rem)]",lg:"data-[checked]:left-[calc(100%-1.375rem)]",xl:"data-[checked]:left-[calc(100%-1.625rem)]"},f=/* @__PURE__ */["relative inline-flex shrink-0 rounded-full","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]","[transition-property:background-color,background-image,box-shadow,filter]","[transition-duration:var(--plass-duration)]","[transition-timing-function:var(--plass-ease)]",n].join(" "),u=/* @__PURE__ */["cursor-pointer bg-(--plass-track)","hover:brightness-[0.97] dark:hover:brightness-110","data-[checked]:[background-image:var(--p-fill)]","data-[checked]:[box-shadow:var(--p-lift)] data-[checked]:hover:brightness-105"].join(" "),g=/* @__PURE__ */["cursor-default bg-(--plass-track) saturate-[0.55]","data-[checked]:[background-image:var(--p-fill)]","data-[checked]:shadow-none"].join(" "),b=/* @__PURE__ */["cursor-not-allowed bg-(--plass-track)","opacity-50 saturate-[0.35] shadow-none","data-[checked]:[background-image:var(--p-fill)]"].join(" "),x=/* @__PURE__ */["absolute inset-y-0.5 left-0.5 aspect-square rounded-full bg-white","[box-shadow:0_1px_2px_rgb(20_40_90/0.25)]","[transition:left_var(--plass-duration)_var(--plass-ease)]"].join(" ");export const PlSwitch=/* @__PURE__ */t.forwardRef(function PlSwitch({size:t="md",color:n="primary",label:k,description:w,error:v,invalid:N,labelPlacement:j="end",disabled:y=!1,readOnly:_=!1,className:P,classNames:R,style:S,...$},B){const O=o(v),q=N??O,z=q?"danger":n,D=e("span",{className:"flex h-[1lh] shrink-0 items-center",children:e(l.Root,{ref:B,className:i(f,m[t],y?b:_?g:u,R?.control),disabled:y,readOnly:_,...$,children:e(l.Thumb,{className:`${x} ${p[t]}`})})}),E=k||w?a("span",{className:["flex min-w-0 flex-col gap-0.5","start"===j?"flex-1":""].filter(Boolean).join(" "),children:[k?e(s.Label,{className:i(y?"text-(--plass-muted-fg)":"cursor-pointer text-(--plass-fg)",R?.label),children:k}):null,w?e(s.Description,{className:i(d[t],"text-(--plass-muted-fg)",R?.description),children:w}):null]}):null;return a(s.Root,{disabled:y,invalid:q,className:["inline-flex flex-col gap-1 align-top",P??""].filter(Boolean).join(" "),style:{...c(z,0,"solid"),...S},children:[e("div",{className:`flex items-start gap-2.5 ${h[t]}`,children:a(r,"start"===j?{children:[E,D]}:{children:[D,E]})}),e(s.Error,O?{match:!0,className:i(d[t],"text-(--p-accent)",R?.error),children:v}:{className:i(d[t],"text-(--p-accent)",R?.error)})]})});
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { PlassElevation, PlassStyleProps } from '../../types.js';
2
+ import type { PlassElevation, PlassFieldClassNames, PlassStyleProps } from '../../types.js';
3
3
  /** How the multiline control may be resized by the user. Ignored when single line. */
4
4
  export type PlTextFieldResize = 'none' | 'vertical' | 'horizontal' | 'both';
5
5
  /**
@@ -9,6 +9,8 @@ export type PlTextFieldResize = 'none' | 'vertical' | 'horizontal' | 'both';
9
9
  */
10
10
  type NativeControlProps = Omit<React.ComponentPropsWithoutRef<'input'>, 'color' | 'size' | 'onChange' | 'children'>;
11
11
  export interface PlTextFieldProps extends PlassStyleProps, NativeControlProps {
12
+ /** Classes on the parts a `className` does not reach. */
13
+ classNames?: PlassFieldClassNames;
12
14
  /**
13
15
  * Drop shadow depth. `0` is the default — a field is a well cut into the
14
16
  * sheet, not a key resting on it, and the one place in the library where a
@@ -1 +1 @@
1
- "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as l from"react";import{Field as n}from"@base-ui/react/field";import{Input as s}from"@base-ui/react/input";import{Spinner as i}from"../../internal/icons.js";import{controlHeightClasses as r,controlTextLeadingClasses as a,disabledClasses as o,fieldReadOnlyClasses as c,fieldRestClasses as m,focusWithinRingClasses as d,gapClasses as p,hasContent as x,iconClasses as u,metaTextClasses as f,paddingXClasses as h,radiusClasses as g,stackGapClasses as $,surfaceSlots as y,transitionClasses as b}from"../../internal/styles.js";const j={xs:`${p.xs} ${g.xs} ${a.xs}`,sm:`${p.sm} ${g.sm} ${a.sm}`,md:`${p.md} ${g.md} ${a.md}`,lg:`${p.lg} ${g.lg} ${a.lg}`,xl:`${p.xl} ${g.xl} ${a.xl}`},N={xs:"min-h-6 py-[3px]",sm:"min-h-8 py-[6px]",md:"min-h-10 py-[9px]",lg:"min-h-12 py-[11px]",xl:"min-h-14 py-[13px]"},v={none:"resize-none",vertical:"resize-y",horizontal:"resize-x",both:"resize"},w=/* @__PURE__ */["group relative flex w-full cursor-text","[-webkit-tap-highlight-color:transparent]",b,d,u].join(" "),z=m,k=c;export const PlTextField=/* @__PURE__ */l.forwardRef(function PlTextField({variant:a="glass",size:c="md",color:m="primary",density:d="default",elevation:p=0,multiline:u=!1,rows:g=3,resize:b="vertical",label:D,description:P,error:R,invalid:T,startIcon:B,endIcon:F,loading:I=!1,fullWidth:O=!1,readOnly:C=!1,disabled:E=!1,type:L="text",className:W,style:q,...A},G){const H=x(R),J=T??H,K=J?"danger":m,M=l.useRef(null),Q=l.useCallback(e=>{M.current=e,"function"==typeof G?G(e):G&&(G.current=e)},[G]),S=[w,j[c],u?`${N[c]} items-start`:`${r[c]} items-center`,h[d][c],E?o[a]:C?k[a]:z[a]].filter(Boolean).join(" "),U=["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)","disabled:cursor-not-allowed",u?`block ${v[b]}`:"self-stretch"].join(" "),V="inline-flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg) transition-[color] duration-(--plass-duration) group-focus-within:text-(--p-accent)";return t(n.Root,{disabled:E,invalid:J,className:["flex-col align-top",$[c],O?"flex w-full":"inline-flex",W??""].filter(Boolean).join(" "),style:{...y(K,p),...q},children:[D?e(n.Label,{className:[f[c],"font-semibold",E?"text-(--plass-muted-fg)":"text-(--plass-fg)"].join(" "),children:D}):null,t("span",{className:S,onPointerDown:e=>{e.target!==e.currentTarget||E||(e.preventDefault(),M.current?.focus())},children:[B?e("span",{className:V,children:B}):null,e(s,{ref:Q,className:U,disabled:E,readOnly:C,"aria-busy":I||void 0,"data-loading":I||void 0,...u?{render:e("textarea",{rows:g})}:{type:L},...A}),I?e("span",{className:V,children:e(i,{})}):F?e("span",{className:V,children:F}):null]}),P?e(n.Description,{className:[f[c],"text-(--plass-muted-fg)"].join(" "),children:P}):null,e(n.Error,H?{match:!0,className:[f[c],"text-(--p-accent)"].join(" "),children:R}:{className:[f[c],"text-(--p-accent)"].join(" ")})]})});
1
+ "use client";import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as l from"react";import{Field as s}from"@base-ui/react/field";import{Input as r}from"@base-ui/react/input";import{Spinner as n}from"../../internal/icons.js";import{controlHeightClasses as a,controlTextLeadingClasses as i,cx as o,disabledClasses as c,fieldReadOnlyClasses as m,fieldRestClasses as d,focusWithinRingClasses as p,gapClasses as x,hasContent as u,iconClasses as f,metaTextClasses as h,paddingXClasses as g,radiusClasses as $,stackGapClasses as b,surfaceSlots as y,transitionClasses as N}from"../../internal/styles.js";const v={xs:`${x.xs} ${$.xs} ${i.xs}`,sm:`${x.sm} ${$.sm} ${i.sm}`,md:`${x.md} ${$.md} ${i.md}`,lg:`${x.lg} ${$.lg} ${i.lg}`,xl:`${x.xl} ${$.xl} ${i.xl}`},w={xs:"min-h-6 py-[3px]",sm:"min-h-8 py-[6px]",md:"min-h-10 py-[9px]",lg:"min-h-12 py-[11px]",xl:"min-h-14 py-[13px]"},j={none:"resize-none",vertical:"resize-y",horizontal:"resize-x",both:"resize"},z=/* @__PURE__ */["group relative flex w-full cursor-text","[-webkit-tap-highlight-color:transparent]",N,p,f].join(" "),k=d,D=m;export const PlTextField=/* @__PURE__ */l.forwardRef(function PlTextField({variant:i="glass",size:m="md",color:d="primary",density:p="default",elevation:x=0,multiline:f=!1,rows:$=3,resize:N="vertical",label:P,description:R,error:T,invalid:B,startIcon:F,endIcon:I,loading:O=!1,fullWidth:C=!1,readOnly:E=!1,disabled:L=!1,type:W="text",className:q,classNames:A,style:G,...H},J){const K=u(T),M=B??K,Q=M?"danger":d,S=l.useRef(null),U=l.useCallback(e=>{S.current=e,"function"==typeof J?J(e):J&&(J.current=e)},[J]),V=[z,v[m],f?`${w[m]} items-start`:`${a[m]} items-center`,g[p][m],L?c[i]:E?D[i]:k[i]].filter(Boolean).join(" "),X=["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)","disabled:cursor-not-allowed",f?`block ${j[N]}`:"self-stretch"].join(" "),Y="inline-flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg) transition-[color] duration-(--plass-duration) group-focus-within:text-(--p-accent)";return t(s.Root,{disabled:L,invalid:M,className:["flex-col align-top",b[m],C?"flex w-full":"inline-flex",q??""].filter(Boolean).join(" "),style:{...y(Q,x),...G},children:[P?e(s.Label,{className:o(h[m],"font-semibold",L?"text-(--plass-muted-fg)":"text-(--plass-fg)",A?.label),children:P}):null,t("span",{className:o(V,A?.control),onPointerDown:e=>{e.target!==e.currentTarget||L||(e.preventDefault(),S.current?.focus())},children:[F?e("span",{className:Y,children:F}):null,e(r,{ref:U,className:X,disabled:L,readOnly:E,"aria-busy":O||void 0,"data-loading":O||void 0,...f?{render:e("textarea",{rows:$})}:{type:W},...H}),O?e("span",{className:Y,children:e(n,{})}):I?e("span",{className:Y,children:I}):null]}),R?e(s.Description,{className:o(h[m],"text-(--plass-muted-fg)",A?.description),children:R}):null,e(s.Error,K?{match:!0,className:o(h[m],"text-(--p-accent)",A?.error),children:T}:{className:o(h[m],"text-(--p-accent)",A?.error)})]})});
@@ -18,6 +18,16 @@ export interface PlToastData {
18
18
  color?: PlassColor;
19
19
  variant?: PlassVariant;
20
20
  icon?: React.ReactNode | false;
21
+ /**
22
+ * Classes on this toast, alongside the ones the provider gives every toast.
23
+ *
24
+ * A toast has no element a caller can put a `className` on — it is raised
25
+ * from a click handler rather than written into a tree — so the class travels
26
+ * with the message, in the same `data` the colour and the variant do.
27
+ */
28
+ className?: string;
29
+ /** Inline styles on this toast, applied over the tokens it sets. */
30
+ style?: React.CSSProperties;
21
31
  }
22
32
  export interface PlToastOptions extends PlToastData {
23
33
  /**
@@ -1 +1 @@
1
- "use client";import{jsx as t,jsxs as e}from"react/jsx-runtime";import*as s from"react";import{Toast as o}from"@base-ui/react/toast";import{CloseIcon as a,severityIcon as i}from"../../internal/icons.js";import{controlSlots as r,focusRingClasses as n,glassClasses as l,hasContent as c,iconClasses as p,metaTextClasses as d,radiusClasses as m,sheetBodyClasses as u,sheetHeaderGapClasses as f,sheetPaddingXClasses as h,sheetPaddingYClasses as g,sheetSectionGapClasses as v,sheetTitleClasses as x}from"../../internal/styles.js";const b={"top-start":"top-0 items-start","top-center":"top-0 items-center","top-end":"top-0 items-end","bottom-start":"bottom-0 flex-col-reverse items-start","bottom-center":"bottom-0 flex-col-reverse items-center","bottom-end":"bottom-0 flex-col-reverse items-end"},y={solid:/* @__PURE__ */["text-(--p-on-solid) [background-image:var(--p-fill)]","[box-shadow:var(--plass-shadow-3),var(--p-lift)]"].join(" "),glass:/* @__PURE__ */[l,"border text-(--plass-fg) bg-(--plass-glass-press)","[border-color:var(--p-line)]","[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]"].join(" "),ghost:/* @__PURE__ */[l,"text-(--plass-fg) bg-(--plass-glass-press)","[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]"].join(" ")},w={solid:"",glass:"text-(--p-accent)",ghost:"text-(--p-accent)"};function toManagerOptions(t){const{color:e,variant:s,icon:o,actionLabel:a,onAction:i,...r}=t;return{...r,data:{color:e,variant:s,icon:o},actionProps:void 0===a?void 0:{children:a,onClick:i}}}export function usePlToast(){const t=o.useToastManager();return s.useMemo(()=>({add:e=>t.add(toManagerOptions(e)),close:e=>t.close(e),update:(e,s)=>t.update(e,toManagerOptions(s)),promise:(e,s)=>t.promise(e,{loading:toManagerOptions(s.loading),success:t=>toManagerOptions("function"==typeof s.success?s.success(t):s.success),error:t=>toManagerOptions("function"==typeof s.error?s.error(t):s.error)}),toasts:t.toasts}),[t])}function ToastItem({toast:s,variant:l,color:b,size:j,density:N,closeLabel:T,swipeDirection:M}){const z=s.data?.variant??l??"glass",O=s.data?.color??b,P=void 0===s.data?.icon?i(O):s.data.icon,k=w[z],$=c(s.title);return e(o.Root,{toast:s,swipeDirection:M,className:["pointer-events-auto flex w-full items-start",h[N??"default"][j],g[N??"default"][j],m[j],v[j],u[j],y[z],p,"[transition:opacity_var(--plass-duration)_var(--plass-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0","data-[limited]:hidden",n,"[outline:none]"].filter(Boolean).join(" "),style:r(O,3,z),children:[c(P)?t("span",{className:`flex h-[1lh] shrink-0 items-center ${k}`,children:P}):null,e("div",{className:`flex min-w-0 flex-1 flex-col ${f[j]}`,children:[t(o.Title,{className:`plass-title font-semibold ${x[j]} ${k}`}),t(o.Description,{className:$&&"solid"!==z?"text-(--plass-muted-fg)":""})]}),t(o.Action,{className:["flex h-[1lh] shrink-0 cursor-pointer items-center rounded-full px-2","font-medium underline-offset-2",k||"text-(--p-on-solid)","hover:underline",n,d[j]].join(" ")}),t("span",{className:"flex h-[1lh] shrink-0 items-center",children:t(o.Close,{"aria-label":T,className:["inline-flex size-[1.15em] cursor-pointer items-center justify-center rounded-full","opacity-70 [transition:opacity_var(--plass-duration)_var(--plass-ease)]","hover:opacity-100 focus-visible:opacity-100",n].join(" "),children:t(a,{})})})]})}function ToastViewport(e){const{toasts:s}=o.useToastManager(),{position:a,width:i,...r}=e,n=[a.startsWith("top")?"up":"down","left","right"];return t(o.Portal,{children:t(o.Viewport,{className:["plass-portal pointer-events-none fixed inset-x-0 z-(--plass-z-portal) flex flex-col gap-2 p-4",b[a]].join(" "),children:s.map(e=>t("div",{className:"w-full",style:{maxWidth:"number"==typeof i?`${i}px`:i},children:t(ToastItem,{toast:e,swipeDirection:n,...r})},e.id))})})}export function PlToastProvider({variant:s="glass",size:a="md",color:i="primary",density:r="default",position:n="bottom-end",timeout:l=5e3,limit:c=3,width:p=380,closeLabel:d="Close",children:m}){return e(o.Provider,{timeout:l,limit:c,children:[m,t(ToastViewport,{position:n,variant:s,size:a,color:i,density:r,width:p,closeLabel:d})]})}
1
+ "use client";import{jsx as t,jsxs as s}from"react/jsx-runtime";import*as e from"react";import{Toast as o}from"@base-ui/react/toast";import{CloseIcon as a,severityIcon as i}from"../../internal/icons.js";import{controlSlots as r,focusRingClasses as n,glassClasses as l,hasContent as c,iconClasses as p,metaTextClasses as d,radiusClasses as m,sheetBodyClasses as u,sheetHeaderGapClasses as f,sheetPaddingXClasses as h,sheetPaddingYClasses as g,sheetSectionGapClasses as v,sheetTitleClasses as x}from"../../internal/styles.js";const b={"top-start":"top-0 items-start","top-center":"top-0 items-center","top-end":"top-0 items-end","bottom-start":"bottom-0 flex-col-reverse items-start","bottom-center":"bottom-0 flex-col-reverse items-center","bottom-end":"bottom-0 flex-col-reverse items-end"},y={solid:/* @__PURE__ */["text-(--p-on-solid) [background-image:var(--p-fill)]","[box-shadow:var(--plass-shadow-3),var(--p-lift)]"].join(" "),glass:/* @__PURE__ */[l,"border text-(--plass-fg) bg-(--plass-glass-press)","[border-color:var(--p-line)]","[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]"].join(" "),ghost:/* @__PURE__ */[l,"text-(--plass-fg) bg-(--plass-glass-press)","[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]"].join(" ")},w={solid:"",glass:"text-(--p-accent)",ghost:"text-(--p-accent)"};function toManagerOptions(t){const{color:s,variant:e,icon:o,className:a,style:i,actionLabel:r,onAction:n,...l}=t;return{...l,data:{color:s,variant:e,icon:o,className:a,style:i},actionProps:void 0===r?void 0:{children:r,onClick:n}}}export function usePlToast(){const t=o.useToastManager();return e.useMemo(()=>({add:s=>t.add(toManagerOptions(s)),close:s=>t.close(s),update:(s,e)=>t.update(s,toManagerOptions(e)),promise:(s,e)=>t.promise(s,{loading:toManagerOptions(e.loading),success:t=>toManagerOptions("function"==typeof e.success?e.success(t):e.success),error:t=>toManagerOptions("function"==typeof e.error?e.error(t):e.error)}),toasts:t.toasts}),[t])}function ToastItem({toast:e,variant:l,color:b,size:j,density:N,closeLabel:T,swipeDirection:M}){const z=e.data?.variant??l??"glass",O=e.data?.color??b,P=void 0===e.data?.icon?i(O):e.data.icon,k=w[z],$=c(e.title);return s(o.Root,{toast:e,swipeDirection:M,className:["pointer-events-auto flex w-full items-start",h[N??"default"][j],g[N??"default"][j],m[j],v[j],u[j],y[z],p,"[transition:opacity_var(--plass-duration)_var(--plass-ease)]","data-[starting-style]:opacity-0 data-[ending-style]:opacity-0","data-[limited]:hidden",n,"[outline:none]",e.data?.className??""].filter(Boolean).join(" "),style:{...r(O,3,z),...e.data?.style},children:[c(P)?t("span",{className:`flex h-[1lh] shrink-0 items-center ${k}`,children:P}):null,s("div",{className:`flex min-w-0 flex-1 flex-col ${f[j]}`,children:[t(o.Title,{className:`plass-title font-semibold ${x[j]} ${k}`}),t(o.Description,{className:$&&"solid"!==z?"text-(--plass-muted-fg)":""})]}),t(o.Action,{className:["flex h-[1lh] shrink-0 cursor-pointer items-center rounded-full px-2","font-medium underline-offset-2",k||"text-(--p-on-solid)","hover:underline",n,d[j]].join(" ")}),t("span",{className:"flex h-[1lh] shrink-0 items-center",children:t(o.Close,{"aria-label":T,className:["inline-flex size-[1.15em] cursor-pointer items-center justify-center rounded-full","opacity-70 [transition:opacity_var(--plass-duration)_var(--plass-ease)]","hover:opacity-100 focus-visible:opacity-100",n].join(" "),children:t(a,{})})})]})}function ToastViewport(s){const{toasts:e}=o.useToastManager(),{position:a,width:i,...r}=s,n=[a.startsWith("top")?"up":"down","left","right"];return t(o.Portal,{children:t(o.Viewport,{className:["plass-portal pointer-events-none fixed inset-x-0 z-(--plass-z-portal) flex flex-col gap-2 p-4",b[a]].join(" "),children:e.map(s=>t("div",{className:"w-full",style:{maxWidth:"number"==typeof i?`${i}px`:i},children:t(ToastItem,{toast:s,swipeDirection:n,...r})},s.id))})})}export function PlToastProvider({variant:e="glass",size:a="md",color:i="primary",density:r="default",position:n="bottom-end",timeout:l=5e3,limit:c=3,width:p=380,closeLabel:d="Close",children:m}){return s(o.Provider,{timeout:l,limit:c,children:[m,t(ToastViewport,{position:n,variant:e,size:a,color:i,density:r,width:p,closeLabel:d})]})}
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import type { PlassPickerLabels } from './calendar.js';
3
- import type { PlassColor, PlassElevation, PlassSize, PlassStyleProps } from '../types.js';
3
+ import type { PlassColor, PlassElevation, PlassFieldClassNames, PlassSize, PlassStyleProps } from '../types.js';
4
4
  /**
5
5
  * The shell all four pickers wear: a field-shaped trigger with a popup hanging
6
6
  * off it.
@@ -59,6 +59,8 @@ export interface PlassPickerShellProps extends PlassStyleProps, Omit<React.Compo
59
59
  invalid?: boolean;
60
60
  /** The glyph before the value — a calendar or a clock. */
61
61
  startIcon?: React.ReactNode;
62
+ /** Classes on the parts a `className` does not reach. */
63
+ classNames?: PlassFieldClassNames;
62
64
  /** Stretches to the width of the container. */
63
65
  fullWidth?: boolean;
64
66
  /** Unavailable. */
@@ -102,7 +104,7 @@ interface InternalShellProps extends PlassPickerShellProps {
102
104
  * and the way `invalid` re-points the whole colour family at `danger` so the
103
105
  * edge, the ring and the message turn over together.
104
106
  */
105
- export declare function PickerShell({ variant, size, color, density, elevation, label, description, error, invalid, startIcon, fullWidth, disabled, readOnly, required, id, className, style, display, samples, empty, clearable, onClear, open, onOpenChange, labels, hiddenValues, children, triggerRef, ...props }: InternalShellProps): React.JSX.Element;
107
+ export declare function PickerShell({ variant, size, color, density, elevation, label, description, error, invalid, startIcon, fullWidth, disabled, readOnly, required, id, className, classNames, style, display, samples, empty, clearable, onClear, open, onOpenChange, labels, hiddenValues, children, triggerRef, ...props }: InternalShellProps): React.JSX.Element;
106
108
  /**
107
109
  * The row of shortcuts under a picker's panel.
108
110
  *
@@ -1 +1 @@
1
- import{jsx as e,jsxs as l}from"react/jsx-runtime";import*as s from"react";import{Field as a}from"@base-ui/react/field";import{Popover as r}from"@base-ui/react/popover";import{CloseIcon as t}from"./icons.js";import{WidthSizer as i}from"./sizer.js";import{chipRemoveClasses as n,controlHeightClasses as o,controlTextLeadingClasses as p,cx as d,disabledClasses as c,fieldReadOnlyClasses as u,fieldRestClasses as m,focusWithinRingClasses as f,gapClasses as h,glassClasses as g,iconClasses as x,metaTextClasses as b,paddingXClasses as v,radiusClasses as y,stackGapClasses as N,surfaceSlots as P,transitionClasses as j}from"./styles.js";export function popupSlots(e,l){return{...P(e,l),"--p-fill":`var(--plass-${e}-fill)`,"--p-on-solid":`var(--plass-${e}-on-solid)`}}const w=/* @__PURE__ */["group relative flex w-full items-center select-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",j,f,x].join(" ");export const pickerPopupClasses=/* @__PURE__ */[g,"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(" ");export const popupPaddingClasses={xs:"p-1.5",sm:"p-2",md:"p-2.5",lg:"p-3",xl:"p-3.5"};export function PickerShell({variant:f="glass",size:g="md",color:x="primary",density:j="default",elevation:k=0,label:C,description:$,error:z,invalid:O,startIcon:F,fullWidth:R=!1,disabled:S=!1,readOnly:q=!1,required:D=!1,id:I,className:_,style:B,display:E,samples:L,empty:T,clearable:V=!1,onClear:W,open:A,onOpenChange:G,labels:H,hiddenValues:J,children:K,triggerRef:M,...Q}){const U=s.useId(),X=I??`${U}-trigger`,Y=`${U}-label`,Z=`${U}-description`,ee=`${U}-error`,le=null!=z&&!1!==z&&""!==z,se=O??le,ae=se?"danger":x,re=S||q,te=[$?Z:null,le?ee:null].filter(Boolean).join(" ")||void 0;return l(a.Root,{disabled:S,invalid:se,className:d("flex-col align-top",N[g],R?"flex w-full":"inline-flex",_),style:{...P(ae,k),...B},...Q,children:[C?e(a.Label,{id:Y,htmlFor:X,className:d(b[g],"font-semibold",S?"text-(--plass-muted-fg)":"text-(--plass-fg)"),children:C}):null,l(r.Root,{open:A,onOpenChange:e=>G(e),children:[l("span",{className:d(w,o[g],p[g],y[g],h[g],v[j][g],S?c[f]:q?u[f]:m[f]),children:[l(r.Trigger,{id:X,ref:M,disabled:S,"aria-labelledby":C?Y:void 0,"aria-describedby":te,"aria-required":D||void 0,"aria-invalid":se||void 0,className:d("flex min-w-0 flex-1 items-center bg-transparent text-start [font:inherit] text-inherit",h[g],"[outline:none]",re?"cursor-default":"cursor-pointer"),children:[F?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)",children:F}):null,l("span",{className:"flex min-w-0 flex-1 flex-col",children:[e("span",{className:d("w-full truncate",T?"text-(--plass-muted-fg)":"text-(--plass-fg)"),children:E}),e(i,{samples:L??[]})]})]}),!V||T||re?null:e("button",{type:"button","aria-label":H.clear,className:d(n,"text-(--plass-muted-fg)"),onClick:e=>{e.stopPropagation(),W()},children:e(t,{})})]}),e(r.Portal,{children:e(r.Positioner,{className:"plass-portal z-(--plass-z-portal) [outline:none]",sideOffset:6,align:"start",children:e(r.Popup,{initialFocus:!1,className:d(pickerPopupClasses,y[g],popupPaddingClasses[g],p[g]),style:popupSlots(ae,3),children:K})})})]}),$?e(a.Description,{id:Z,className:d(b[g],"text-(--plass-muted-fg)"),children:$}):null,le?e(a.Error,{id:ee,match:!0,className:d(b[g],"text-(--p-accent)"),children:z}):null,J?.map((l,s)=>e("input",{type:"hidden",name:l.name,value:l.value},s))]})}export function PickerFooter({size:l,children:s}){return e("div",{className:d("flex items-center justify-end border-t pt-1.5","[border-color:var(--plass-divider)]",h[l]),children:s})}export function PickerDivider(){return e("div",{"aria-hidden":"true",className:"w-px self-stretch bg-(--plass-divider)"})}
1
+ import{jsx as e,jsxs as l}from"react/jsx-runtime";import*as s from"react";import{Field as a}from"@base-ui/react/field";import{Popover as r}from"@base-ui/react/popover";import{CloseIcon as t}from"./icons.js";import{WidthSizer as i}from"./sizer.js";import{chipRemoveClasses as n,controlHeightClasses as o,controlTextLeadingClasses as p,cx as d,disabledClasses as c,fieldReadOnlyClasses as u,fieldRestClasses as m,focusWithinRingClasses as f,gapClasses as h,glassClasses as g,iconClasses as x,metaTextClasses as b,paddingXClasses as v,radiusClasses as y,stackGapClasses as N,surfaceSlots as P,transitionClasses as j}from"./styles.js";export function popupSlots(e,l){return{...P(e,l),"--p-fill":`var(--plass-${e}-fill)`,"--p-on-solid":`var(--plass-${e}-on-solid)`}}const w=/* @__PURE__ */["group relative flex w-full items-center select-none","[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]",j,f,x].join(" ");export const pickerPopupClasses=/* @__PURE__ */[g,"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(" ");export const popupPaddingClasses={xs:"p-1.5",sm:"p-2",md:"p-2.5",lg:"p-3",xl:"p-3.5"};export function PickerShell({variant:f="glass",size:g="md",color:x="primary",density:j="default",elevation:k=0,label:C,description:$,error:z,invalid:O,startIcon:F,fullWidth:R=!1,disabled:S=!1,readOnly:q=!1,required:D=!1,id:I,className:_,classNames:B,style:E,display:L,samples:T,empty:V,clearable:W=!1,onClear:A,open:G,onOpenChange:H,labels:J,hiddenValues:K,children:M,triggerRef:Q,...U}){const X=s.useId(),Y=I??`${X}-trigger`,Z=`${X}-label`,ee=`${X}-description`,le=`${X}-error`,se=null!=z&&!1!==z&&""!==z,ae=O??se,re=ae?"danger":x,te=S||q,ie=[$?ee:null,se?le:null].filter(Boolean).join(" ")||void 0;return l(a.Root,{disabled:S,invalid:ae,className:d("flex-col align-top",N[g],R?"flex w-full":"inline-flex",_),style:{...P(re,k),...E},...U,children:[C?e(a.Label,{id:Z,htmlFor:Y,className:d(b[g],"font-semibold",S?"text-(--plass-muted-fg)":"text-(--plass-fg)",B?.label),children:C}):null,l(r.Root,{open:G,onOpenChange:e=>H(e),children:[l("span",{className:d(w,o[g],p[g],y[g],h[g],v[j][g],S?c[f]:q?u[f]:m[f],B?.control),children:[l(r.Trigger,{id:Y,ref:Q,disabled:S,"aria-labelledby":C?Z:void 0,"aria-describedby":ie,"aria-required":D||void 0,"aria-invalid":ae||void 0,className:d("flex min-w-0 flex-1 items-center bg-transparent text-start [font:inherit] text-inherit",h[g],"[outline:none]",te?"cursor-default":"cursor-pointer"),children:[F?e("span",{className:"flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)",children:F}):null,l("span",{className:"flex min-w-0 flex-1 flex-col",children:[e("span",{className:d("w-full truncate",V?"text-(--plass-muted-fg)":"text-(--plass-fg)"),children:L}),e(i,{samples:T??[]})]})]}),!W||V||te?null:e("button",{type:"button","aria-label":J.clear,className:d(n,"text-(--plass-muted-fg)"),onClick:e=>{e.stopPropagation(),A()},children:e(t,{})})]}),e(r.Portal,{children:e(r.Positioner,{className:"plass-portal z-(--plass-z-portal) [outline:none]",sideOffset:6,align:"start",children:e(r.Popup,{initialFocus:!1,className:d(pickerPopupClasses,y[g],popupPaddingClasses[g],p[g]),style:popupSlots(re,3),children:M})})})]}),$?e(a.Description,{id:ee,className:d(b[g],"text-(--plass-muted-fg)",B?.description),children:$}):null,se?e(a.Error,{id:le,match:!0,className:d(b[g],"text-(--p-accent)",B?.error),children:z}):null,K?.map((l,s)=>e("input",{type:"hidden",name:l.name,value:l.value},s))]})}export function PickerFooter({size:l,children:s}){return e("div",{className:d("flex items-center justify-end border-t pt-1.5","[border-color:var(--plass-divider)]",h[l]),children:s})}export function PickerDivider(){return e("div",{"aria-hidden":"true",className:"w-px self-stretch bg-(--plass-divider)"})}
package/dist/types.d.ts CHANGED
@@ -145,6 +145,78 @@ export interface PlassStyleProps {
145
145
  /** @default 'default' */
146
146
  density?: PlassDensity;
147
147
  }
148
+ /**
149
+ * The parts of a labelled control a `className` does not reach.
150
+ *
151
+ * A field is four things stacked, and only the stack itself is addressable
152
+ * otherwise: `className` lands on the wrapper that holds the label, the control
153
+ * and the two lines of text under it. That is right for the layout — a
154
+ * `w-full`, a margin, a grid position — and it is the wrong element for every
155
+ * other override a caller reaches for.
156
+ *
157
+ * `control` is the part a reader acts on: the box a `PlTextField` is typed
158
+ * into, the button a `PlSelect` opens, the tick, the track, the row of radios.
159
+ * It is the one of the four that is worth naming even when the other three are
160
+ * not there.
161
+ */
162
+ export interface PlassFieldClassNames {
163
+ /** The text above the control. */
164
+ label?: string;
165
+ /** The part a reader acts on. */
166
+ control?: string;
167
+ /** The helper text below it. */
168
+ description?: string;
169
+ /** The message below it, shown when the field is invalid. */
170
+ error?: string;
171
+ }
172
+ /** The parts of a portalled surface a `className` does not reach. */
173
+ export interface PlassPortalClassNames {
174
+ /**
175
+ * The sheet drawn over the page behind the surface — the scrim, the blur, and
176
+ * the thing a click outside the surface lands on.
177
+ */
178
+ backdrop?: string;
179
+ }
180
+ /**
181
+ * The twelve slots a colour family is cut into.
182
+ *
183
+ * Not a vocabulary a caller invents in: these are the names `styles.css`
184
+ * declares six times over, once per family, and a component reads them through
185
+ * its `--p-*` locals rather than by name. They are spelled out here so that
186
+ * `PlassToken` can be a real union rather than a string.
187
+ */
188
+ export type PlassColorSlot = 'accent' | 'fill' | 'line' | 'line-hover' | 'on-solid' | 'ring' | 'soft' | 'soft-hover' | 'soft-press' | 'solid' | 'solid-to' | 'tint';
189
+ /**
190
+ * Every design token a caller may set, by name.
191
+ *
192
+ * The `--p-*` locals a component writes onto itself are **not** here on
193
+ * purpose. Those are the library talking to itself — which family this control
194
+ * resolved to, what its shadow costs at this `elevation` — and a caller who
195
+ * sets one is setting the answer rather than the question. `color`, `variant`
196
+ * and `elevation` are the props that decide them.
197
+ */
198
+ export type PlassToken = `--plass-${PlassColor}-${PlassColorSlot}` | `--plass-radius-${PlassSize}` | `--plass-shadow-${0 | 1 | 2 | 3 | 4}` | '--plass-shadow-ambient' | '--plass-bg-from' | '--plass-bg-to' | '--plass-blur' | '--plass-border' | '--plass-divider' | '--plass-duration' | '--plass-duration-slow' | '--plass-ease' | '--plass-fg' | '--plass-flash-on-fill' | '--plass-glass' | '--plass-glass-hover' | '--plass-glass-line' | '--plass-glass-press' | '--plass-gloss-glass' | '--plass-glow-angle' | '--plass-glow-on-fill' | '--plass-muted-fg' | '--plass-scrim' | '--plass-stripe' | '--plass-surface' | '--plass-tint-strength' | '--plass-track' | '--plass-well' | '--plass-z-portal';
199
+ /**
200
+ * A set of token overrides, on its own.
201
+ *
202
+ * Not a `style` object — deliberately. The augmentation below widens
203
+ * `CSSProperties` to accept any `--plass-*` key, which is what makes the
204
+ * channel usable at all but also means a typo inside a `style` is a
205
+ * declaration nobody reads rather than an error. This type is not widened, so
206
+ * a name that is not a token fails to compile: write the theme here, once, and
207
+ * spread it into as many `style` props as it applies to.
208
+ */
209
+ export type PlassTokens = Partial<Record<PlassToken, string | number>>;
210
+ declare module 'react' {
211
+ interface CSSProperties {
212
+ /**
213
+ * A Plass design token. See `PlassToken` for the names, and
214
+ * [the token reference](https://plass.cdget.com/design/color) for what each
215
+ * one paints.
216
+ */
217
+ [token: `--plass-${string}`]: string | number | undefined;
218
+ }
219
+ }
148
220
  /**
149
221
  * The six effects the `PlAnimate*` components are built out of.
150
222
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plass-ui",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "A React UI component library made of glass and gradients — smooth tinted surfaces, shadows in their own colour, and light that follows the pointer. Accessible and themeable, ESM only, types included, dark mode built in.",
5
5
  "type": "module",
6
6
  "types": "dist/index.d.ts",