@burtson-labs/ui 0.12.2 → 0.12.4

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.
@@ -2,7 +2,21 @@ import { cn } from "../lib/utils.js";
2
2
  import * as React from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  //#region src/components/input.tsx
5
- var fieldClasses = "w-full min-w-0 rounded-md border border-input bg-surface px-3 text-base sm:text-sm text-foreground shadow-xs outline-none transition-[border-color,box-shadow,background-color] placeholder:text-muted-foreground/80 hover:border-border-strong focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:border-brand focus-visible:ring-[3px] focus-visible:ring-ring/15 disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-60 aria-invalid:border-destructive aria-invalid:ring-destructive/15 dark:bg-surface-raised";
5
+ /**
6
+ * Keyboard focus for anything that is a text field, or a box that contains
7
+ * one (Composer, a bordered Command): the border turns the ring colour and a
8
+ * 1px inset ring doubles it to 2px. It sits inside the border box, so it
9
+ * follows the radius exactly and no overflow can clip it. The outline is
10
+ * suppressed with !important: an app's unlayered `:focus-visible { outline }`
11
+ * would otherwise beat the utilities layer and draw a second, offset box.
12
+ * outline-hidden keeps a transparent outline, which forced-colors mode shows.
13
+ */
14
+ var fieldFocusClasses = "outline-hidden! focus-visible:border-ring focus-visible:inset-ring-1 focus-visible:inset-ring-ring aria-invalid:focus-visible:inset-ring-destructive";
15
+ /**
16
+ * Fields and field-like triggers: 10px radius (radius-md). Popovers are 12px
17
+ * (radius-lg) and their rows 8px (radius-sm: 12px less the 4px inset).
18
+ */
19
+ var fieldClasses = `w-full min-w-0 rounded-md border border-input bg-surface px-3 text-base sm:text-sm text-foreground shadow-xs transition-[border-color,box-shadow,background-color] placeholder:text-muted-foreground/80 hover:border-border-strong ${fieldFocusClasses} disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-60 aria-invalid:border-destructive dark:bg-surface-raised`;
6
20
  var Input = React.forwardRef(function Input({ className, type, ...props }, ref) {
7
21
  return /* @__PURE__ */ jsx("input", {
8
22
  ref,
@@ -13,6 +27,6 @@ var Input = React.forwardRef(function Input({ className, type, ...props }, ref)
13
27
  });
14
28
  });
15
29
  //#endregion
16
- export { Input, fieldClasses };
30
+ export { Input, fieldClasses, fieldFocusClasses };
17
31
 
18
32
  //# sourceMappingURL=input.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"input.js","names":[],"sources":["../../src/components/input.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nexport const fieldClasses =\n 'w-full min-w-0 rounded-md border border-input bg-surface px-3 text-base sm:text-sm text-foreground shadow-xs outline-none transition-[border-color,box-shadow,background-color] placeholder:text-muted-foreground/80 hover:border-border-strong focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:border-brand focus-visible:ring-[3px] focus-visible:ring-ring/15 disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-60 aria-invalid:border-destructive aria-invalid:ring-destructive/15 dark:bg-surface-raised';\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(function Input(\n { className, type, ...props }: React.ComponentProps<'input'>,\n ref,\n) {\n return (\n <input\n ref={ref}\n type={type}\n data-slot=\"input\"\n className={cn(\n fieldClasses,\n 'h-9 py-1.5 file:mr-3 file:border-0 file:bg-transparent file:text-sm file:font-semibold file:text-foreground',\n className,\n )}\n {...props}\n />\n );\n});\n\nexport { Input };\n"],"mappings":";;;;AAIA,IAAa,eACX;AAEF,IAAM,QAAQ,MAAM,WAA4D,SAAS,MACvF,EAAE,WAAW,MAAM,GAAG,SACtB,KACA;CACA,OACE,oBAAC,SAAD;EACO;EACC;EACN,aAAU;EACV,WAAW,GACT,cACA,+GACA,SACF;EACA,GAAI;CACL,CAAA;AAEL,CAAC"}
1
+ {"version":3,"file":"input.js","names":[],"sources":["../../src/components/input.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\n/**\n * Keyboard focus for anything that is a text field, or a box that contains\n * one (Composer, a bordered Command): the border turns the ring colour and a\n * 1px inset ring doubles it to 2px. It sits inside the border box, so it\n * follows the radius exactly and no overflow can clip it. The outline is\n * suppressed with !important: an app's unlayered `:focus-visible { outline }`\n * would otherwise beat the utilities layer and draw a second, offset box.\n * outline-hidden keeps a transparent outline, which forced-colors mode shows.\n */\nexport const fieldFocusClasses =\n 'outline-hidden! focus-visible:border-ring focus-visible:inset-ring-1 focus-visible:inset-ring-ring aria-invalid:focus-visible:inset-ring-destructive';\n\n/**\n * Fields and field-like triggers: 10px radius (radius-md). Popovers are 12px\n * (radius-lg) and their rows 8px (radius-sm: 12px less the 4px inset).\n */\nexport const fieldClasses = `w-full min-w-0 rounded-md border border-input bg-surface px-3 text-base sm:text-sm text-foreground shadow-xs transition-[border-color,box-shadow,background-color] placeholder:text-muted-foreground/80 hover:border-border-strong ${fieldFocusClasses} disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-60 aria-invalid:border-destructive dark:bg-surface-raised`;\n\nconst Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(function Input(\n { className, type, ...props }: React.ComponentProps<'input'>,\n ref,\n) {\n return (\n <input\n ref={ref}\n type={type}\n data-slot=\"input\"\n className={cn(\n fieldClasses,\n 'h-9 py-1.5 file:mr-3 file:border-0 file:bg-transparent file:text-sm file:font-semibold file:text-foreground',\n className,\n )}\n {...props}\n />\n );\n});\n\nexport { Input };\n"],"mappings":";;;;;;;;;;;;;AAaA,IAAa,oBACX;;;;;AAMF,IAAa,eAAe,sOAAsO,kBAAkB;AAEpR,IAAM,QAAQ,MAAM,WAA4D,SAAS,MACvF,EAAE,WAAW,MAAM,GAAG,SACtB,KACA;CACA,OACE,oBAAC,SAAD;EACO;EACC;EACN,aAAU;EACV,WAAW,GACT,cACA,+GACA,SACF;EACA,GAAI;CACL,CAAA;AAEL,CAAC"}
@@ -119,7 +119,7 @@ function MenubarSubTrigger({ className, inset, children, ...props }) {
119
119
  return /* @__PURE__ */ jsxs(Menubar.SubTrigger, {
120
120
  "data-slot": "menubar-sub-trigger",
121
121
  "data-inset": inset || void 0,
122
- className: cn(menuItemClasses, "data-[state=open]:bg-muted", className),
122
+ className: cn(menuItemClasses, "data-[state=open]:bg-secondary", className),
123
123
  ...props,
124
124
  children: [children, /* @__PURE__ */ jsx(ChevronRight, {
125
125
  className: "ml-auto size-4",
@@ -1 +1 @@
1
- {"version":3,"file":"menubar.js","names":["Menubar","MenubarPrimitive","itemClasses"],"sources":["../../src/components/menubar.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport { Menubar as MenubarPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { menuItemClasses as itemClasses, surfaceClasses } from './popover';\n\n/**\n * An application menu bar (File, Edit, View). Left/Right move between menus,\n * Down opens one, and an open menu follows the pointer across triggers. Rows\n * match DropdownMenu and ContextMenu.\n */\nfunction Menubar({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Root>) {\n return (\n <MenubarPrimitive.Root\n data-slot=\"menubar\"\n className={cn('flex h-8 items-center gap-0.5 rounded-md border bg-surface p-0.5', className)}\n {...props}\n />\n );\n}\n\nfunction MenubarMenu(props: React.ComponentProps<typeof MenubarPrimitive.Menu>) {\n return <MenubarPrimitive.Menu data-slot=\"menubar-menu\" {...props} />;\n}\n\nfunction MenubarTrigger({\n className,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Trigger>) {\n return (\n <MenubarPrimitive.Trigger\n data-slot=\"menubar-trigger\"\n className={cn(\n 'flex h-7 items-center rounded-sm px-2.5 text-[13px] font-medium outline-none select-none hover:bg-muted focus-visible:shadow-[inset_0_0_0_1px_var(--ring)] data-[state=open]:bg-muted',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MenubarGroup(props: React.ComponentProps<typeof MenubarPrimitive.Group>) {\n return <MenubarPrimitive.Group data-slot=\"menubar-group\" {...props} />;\n}\n\nfunction MenubarContent({\n className,\n align = 'start',\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Content>) {\n return (\n <MenubarPrimitive.Portal>\n <MenubarPrimitive.Content\n data-slot=\"menubar-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n surfaceClasses,\n 'max-h-(--radix-menubar-content-available-height) min-w-[8rem] origin-(--radix-menubar-content-transform-origin) overflow-x-hidden overflow-y-auto p-1',\n className,\n )}\n {...props}\n />\n </MenubarPrimitive.Portal>\n );\n}\n\nfunction MenubarItem({\n className,\n inset,\n variant = 'default',\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Item> & {\n inset?: boolean;\n variant?: 'default' | 'destructive';\n}) {\n return (\n <MenubarPrimitive.Item\n data-slot=\"menubar-item\"\n data-inset={inset || undefined}\n data-variant={variant}\n className={cn(\n itemClasses,\n 'data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MenubarCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>) {\n return (\n <MenubarPrimitive.CheckboxItem\n data-slot=\"menubar-checkbox-item\"\n className={cn(itemClasses, 'pl-8', className)}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <Check className=\"size-4 text-foreground\" aria-hidden />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.CheckboxItem>\n );\n}\n\nfunction MenubarRadioGroup(props: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {\n return <MenubarPrimitive.RadioGroup data-slot=\"menubar-radio-group\" {...props} />;\n}\n\nfunction MenubarRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.RadioItem>) {\n return (\n <MenubarPrimitive.RadioItem\n data-slot=\"menubar-radio-item\"\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <span className=\"block size-2 rounded-full bg-foreground\" />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.RadioItem>\n );\n}\n\nfunction MenubarLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Label> & { inset?: boolean }) {\n return (\n <MenubarPrimitive.Label\n data-slot=\"menubar-label\"\n data-inset={inset || undefined}\n className={cn(\n 'px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase data-[inset]:pl-8',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MenubarSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Separator>) {\n return (\n <MenubarPrimitive.Separator\n data-slot=\"menubar-separator\"\n className={cn('-mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction MenubarShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"menubar-shortcut\"\n className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nfunction MenubarSub(props: React.ComponentProps<typeof MenubarPrimitive.Sub>) {\n return <MenubarPrimitive.Sub data-slot=\"menubar-sub\" {...props} />;\n}\n\nfunction MenubarSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & { inset?: boolean }) {\n return (\n <MenubarPrimitive.SubTrigger\n data-slot=\"menubar-sub-trigger\"\n data-inset={inset || undefined}\n className={cn(itemClasses, 'data-[state=open]:bg-muted', className)}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto size-4\" aria-hidden />\n </MenubarPrimitive.SubTrigger>\n );\n}\n\nfunction MenubarSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.SubContent>) {\n return (\n <MenubarPrimitive.Portal>\n <MenubarPrimitive.SubContent\n data-slot=\"menubar-sub-content\"\n className={cn(\n surfaceClasses,\n 'min-w-[8rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden p-1',\n className,\n )}\n {...props}\n />\n </MenubarPrimitive.Portal>\n );\n}\n\nexport {\n Menubar,\n MenubarMenu,\n MenubarCheckboxItem,\n MenubarContent,\n MenubarGroup,\n MenubarItem,\n MenubarLabel,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarSeparator,\n MenubarShortcut,\n MenubarSub,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarTrigger,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"menubar.js","names":["Menubar","MenubarPrimitive","itemClasses"],"sources":["../../src/components/menubar.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronRight from '@burtson-labs/icons/react/chevron-right';\nimport { Menubar as MenubarPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { menuItemClasses as itemClasses, surfaceClasses } from './popover';\n\n/**\n * An application menu bar (File, Edit, View). Left/Right move between menus,\n * Down opens one, and an open menu follows the pointer across triggers. Rows\n * match DropdownMenu and ContextMenu.\n */\nfunction Menubar({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Root>) {\n return (\n <MenubarPrimitive.Root\n data-slot=\"menubar\"\n className={cn('flex h-8 items-center gap-0.5 rounded-md border bg-surface p-0.5', className)}\n {...props}\n />\n );\n}\n\nfunction MenubarMenu(props: React.ComponentProps<typeof MenubarPrimitive.Menu>) {\n return <MenubarPrimitive.Menu data-slot=\"menubar-menu\" {...props} />;\n}\n\nfunction MenubarTrigger({\n className,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Trigger>) {\n return (\n <MenubarPrimitive.Trigger\n data-slot=\"menubar-trigger\"\n className={cn(\n 'flex h-7 items-center rounded-sm px-2.5 text-[13px] font-medium outline-none select-none hover:bg-muted focus-visible:shadow-[inset_0_0_0_1px_var(--ring)] data-[state=open]:bg-muted',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MenubarGroup(props: React.ComponentProps<typeof MenubarPrimitive.Group>) {\n return <MenubarPrimitive.Group data-slot=\"menubar-group\" {...props} />;\n}\n\nfunction MenubarContent({\n className,\n align = 'start',\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Content>) {\n return (\n <MenubarPrimitive.Portal>\n <MenubarPrimitive.Content\n data-slot=\"menubar-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n surfaceClasses,\n 'max-h-(--radix-menubar-content-available-height) min-w-[8rem] origin-(--radix-menubar-content-transform-origin) overflow-x-hidden overflow-y-auto p-1',\n className,\n )}\n {...props}\n />\n </MenubarPrimitive.Portal>\n );\n}\n\nfunction MenubarItem({\n className,\n inset,\n variant = 'default',\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Item> & {\n inset?: boolean;\n variant?: 'default' | 'destructive';\n}) {\n return (\n <MenubarPrimitive.Item\n data-slot=\"menubar-item\"\n data-inset={inset || undefined}\n data-variant={variant}\n className={cn(\n itemClasses,\n 'data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:*:[svg]:!text-destructive',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MenubarCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>) {\n return (\n <MenubarPrimitive.CheckboxItem\n data-slot=\"menubar-checkbox-item\"\n className={cn(itemClasses, 'pl-8', className)}\n checked={checked}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <Check className=\"size-4 text-foreground\" aria-hidden />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.CheckboxItem>\n );\n}\n\nfunction MenubarRadioGroup(props: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {\n return <MenubarPrimitive.RadioGroup data-slot=\"menubar-radio-group\" {...props} />;\n}\n\nfunction MenubarRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.RadioItem>) {\n return (\n <MenubarPrimitive.RadioItem\n data-slot=\"menubar-radio-item\"\n className={cn(itemClasses, 'pl-8', className)}\n {...props}\n >\n <span className=\"pointer-events-none absolute left-2 flex size-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <span className=\"block size-2 rounded-full bg-foreground\" />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.RadioItem>\n );\n}\n\nfunction MenubarLabel({\n className,\n inset,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Label> & { inset?: boolean }) {\n return (\n <MenubarPrimitive.Label\n data-slot=\"menubar-label\"\n data-inset={inset || undefined}\n className={cn(\n 'px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase data-[inset]:pl-8',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction MenubarSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.Separator>) {\n return (\n <MenubarPrimitive.Separator\n data-slot=\"menubar-separator\"\n className={cn('-mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nfunction MenubarShortcut({ className, ...props }: React.ComponentProps<'span'>) {\n return (\n <span\n data-slot=\"menubar-shortcut\"\n className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nfunction MenubarSub(props: React.ComponentProps<typeof MenubarPrimitive.Sub>) {\n return <MenubarPrimitive.Sub data-slot=\"menubar-sub\" {...props} />;\n}\n\nfunction MenubarSubTrigger({\n className,\n inset,\n children,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & { inset?: boolean }) {\n return (\n <MenubarPrimitive.SubTrigger\n data-slot=\"menubar-sub-trigger\"\n data-inset={inset || undefined}\n className={cn(itemClasses, 'data-[state=open]:bg-secondary', className)}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto size-4\" aria-hidden />\n </MenubarPrimitive.SubTrigger>\n );\n}\n\nfunction MenubarSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof MenubarPrimitive.SubContent>) {\n return (\n <MenubarPrimitive.Portal>\n <MenubarPrimitive.SubContent\n data-slot=\"menubar-sub-content\"\n className={cn(\n surfaceClasses,\n 'min-w-[8rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden p-1',\n className,\n )}\n {...props}\n />\n </MenubarPrimitive.Portal>\n );\n}\n\nexport {\n Menubar,\n MenubarMenu,\n MenubarCheckboxItem,\n MenubarContent,\n MenubarGroup,\n MenubarItem,\n MenubarLabel,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarSeparator,\n MenubarShortcut,\n MenubarSub,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarTrigger,\n};\n"],"mappings":"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"}
@@ -99,7 +99,7 @@ function MessageEditor({ defaultValue, onSubmit, onCancel, submitLabel = "Send",
99
99
  send();
100
100
  }
101
101
  },
102
- className: "field-sizing-content max-h-60 min-h-16 w-full resize-none rounded-lg border border-brand bg-surface px-3 py-2 text-base leading-6 ring-[3px] ring-ring/15 outline-none sm:text-sm"
102
+ className: "field-sizing-content max-h-60 min-h-16 w-full resize-none rounded-lg border border-ring bg-surface px-3 py-2 text-base leading-6 inset-ring-1 inset-ring-ring outline-hidden! sm:text-sm"
103
103
  }), /* @__PURE__ */ jsxs("div", {
104
104
  className: "flex justify-end gap-2",
105
105
  children: [/* @__PURE__ */ jsx(Button, {
@@ -1 +1 @@
1
- {"version":3,"file":"message-actions.js","names":["_Fragment"],"sources":["../../src/components/message-actions.tsx"],"sourcesContent":["import Edit from '@burtson-labs/icons/react/edit';\nimport FileText from '@burtson-labs/icons/react/file-text';\nimport RotateCcw from '@burtson-labs/icons/react/rotate-ccw';\nimport ThumbsDown from '@burtson-labs/icons/react/thumbs-down';\nimport ThumbsUp from '@burtson-labs/icons/react/thumbs-up';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { formatBytes } from './attachment';\nimport { VoiceMessage } from './audio-player';\nimport { Button } from './button';\nimport { CopyButton } from './copy-button';\nimport { IconButton } from './icon-button';\n\nexport type MessageFeedback = 'up' | 'down' | null;\n\nexport interface MessageActionsProps extends React.ComponentProps<'div'> {\n /** Text for the copy button; leave out to hide it. */\n copyText?: string;\n onRegenerate?: () => void;\n /** Edit a sent message (user turns). Pair with MessageEditor. */\n onEdit?: () => void;\n /** The current rating; controlled. */\n feedback?: MessageFeedback;\n /** Adds thumbs up and down. Clicking the chosen one again clears it (null). */\n onFeedback?: (value: MessageFeedback) => void;\n}\n\n/**\n * The row under a message: copy, regenerate, edit and a thumbs rating, as\n * small icon buttons. Pass it to Message's `actions`, which shows it on\n * hover and focus (always on touch screens).\n */\nfunction MessageActions({\n copyText,\n onRegenerate,\n onEdit,\n feedback = null,\n onFeedback,\n className,\n ...props\n}: MessageActionsProps) {\n const small = 'size-7 text-muted-foreground hover:text-foreground pointer-coarse:size-10';\n return (\n <div\n data-slot=\"message-actions\"\n role=\"toolbar\"\n aria-label=\"Message actions\"\n className={cn('flex items-center gap-0.5', className)}\n {...props}\n >\n {copyText !== undefined && (\n <CopyButton value={copyText} label=\"Copy message\" className={small} />\n )}\n {onEdit && (\n <IconButton\n variant=\"ghost\"\n size=\"icon-sm\"\n label=\"Edit message\"\n onClick={onEdit}\n className={small}\n >\n <Edit />\n </IconButton>\n )}\n {onRegenerate && (\n <IconButton\n variant=\"ghost\"\n size=\"icon-sm\"\n label=\"Regenerate response\"\n onClick={onRegenerate}\n className={small}\n >\n <RotateCcw />\n </IconButton>\n )}\n {onFeedback && (\n <>\n <IconButton\n variant=\"ghost\"\n size=\"icon-sm\"\n label=\"Good response\"\n aria-pressed={feedback === 'up'}\n onClick={() => onFeedback(feedback === 'up' ? null : 'up')}\n className={cn(small, feedback === 'up' && 'text-brand hover:text-brand')}\n >\n <ThumbsUp className={cn(feedback === 'up' && 'fill-current')} />\n </IconButton>\n <IconButton\n variant=\"ghost\"\n size=\"icon-sm\"\n label=\"Bad response\"\n aria-pressed={feedback === 'down'}\n onClick={() => onFeedback(feedback === 'down' ? null : 'down')}\n className={cn(small, feedback === 'down' && 'text-foreground')}\n >\n <ThumbsDown className={cn(feedback === 'down' && 'fill-current')} />\n </IconButton>\n </>\n )}\n </div>\n );\n}\n\nexport interface MessageEditorProps extends Omit<React.ComponentProps<'form'>, 'onSubmit'> {\n /** The text being edited. */\n defaultValue: string;\n /** Save and send the edited message again. */\n onSubmit: (text: string) => void;\n onCancel: () => void;\n submitLabel?: string;\n}\n\n/**\n * Edit-and-resend in place of a sent message. Enter sends (never mid-IME\n * composition), Shift+Enter adds a line, Escape cancels.\n */\nfunction MessageEditor({\n defaultValue,\n onSubmit,\n onCancel,\n submitLabel = 'Send',\n className,\n ...props\n}: MessageEditorProps) {\n const [value, setValue] = React.useState(defaultValue);\n const send = () => {\n if (value.trim()) onSubmit(value.trim());\n };\n return (\n <form\n data-slot=\"message-editor\"\n onSubmit={(e) => {\n e.preventDefault();\n send();\n }}\n className={cn('grid w-full max-w-[85%] gap-2 justify-self-end', className)}\n {...props}\n >\n <textarea\n aria-label=\"Edit message\"\n value={value}\n // eslint-disable-next-line jsx-a11y/no-autofocus -- editing was just asked for\n autoFocus\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={(e) => {\n if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) return;\n if (e.key === 'Escape') {\n e.preventDefault();\n onCancel();\n } else if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n send();\n }\n }}\n className=\"field-sizing-content max-h-60 min-h-16 w-full resize-none rounded-lg border border-brand bg-surface px-3 py-2 text-base leading-6 ring-[3px] ring-ring/15 outline-none sm:text-sm\"\n />\n <div className=\"flex justify-end gap-2\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={onCancel}>\n Cancel\n </Button>\n <Button type=\"submit\" size=\"sm\" disabled={!value.trim()}>\n {submitLabel}\n </Button>\n </div>\n </form>\n );\n}\n\nexport interface MessageFile {\n name: string;\n /** Bytes. */\n size?: number;\n /** MIME type; audio renders a player, images a thumbnail. */\n type?: string;\n /** Where to open or play it. */\n href?: string;\n /** Waveform peaks for audio (see computePeaks). */\n peaks?: number[];\n /** Seconds, for audio. */\n duration?: number;\n /** Transcript for audio. */\n transcript?: React.ReactNode;\n}\n\nexport interface MessageAttachmentsProps extends React.ComponentProps<'div'> {\n files: MessageFile[];\n}\n\n/**\n * Files sent with a message: voice notes play inline, images show a\n * thumbnail, anything else is a named chip that opens the file.\n */\nfunction MessageAttachments({ files, className, ...props }: MessageAttachmentsProps) {\n if (!files.length) return null;\n return (\n <div\n data-slot=\"message-attachments\"\n className={cn('flex flex-wrap gap-2', className)}\n {...props}\n >\n {files.map((f, i) => {\n const type = f.type ?? '';\n if (type.startsWith('audio/') && f.href) {\n return (\n <VoiceMessage\n key={`${f.name}-${i}`}\n src={f.href}\n peaks={f.peaks}\n duration={f.duration}\n transcript={f.transcript}\n title={f.name}\n />\n );\n }\n if (type.startsWith('image/') && f.href) {\n return (\n <a\n key={`${f.name}-${i}`}\n href={f.href}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"block overflow-hidden rounded-lg border outline-none focus-visible:ring-[3px] focus-visible:ring-ring/20\"\n >\n <img src={f.href} alt={f.name} className=\"h-28 w-auto max-w-56 object-cover\" />\n </a>\n );\n }\n const chip = (\n <>\n <FileText aria-hidden className=\"size-4 shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 truncate\">{f.name}</span>\n {f.size !== undefined && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{formatBytes(f.size)}</span>\n )}\n </>\n );\n const chipClass =\n 'inline-flex max-w-64 items-center gap-2 rounded-md border bg-surface px-2.5 py-1.5 text-sm';\n return f.href ? (\n <a\n key={`${f.name}-${i}`}\n href={f.href}\n target=\"_blank\"\n rel=\"noreferrer\"\n className={cn(\n chipClass,\n 'outline-none hover:bg-muted focus-visible:ring-[3px] focus-visible:ring-ring/20',\n )}\n >\n {chip}\n </a>\n ) : (\n <span key={`${f.name}-${i}`} className={chipClass}>\n {chip}\n </span>\n );\n })}\n </div>\n );\n}\n\nexport { MessageActions, MessageAttachments, MessageEditor };\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAkCA,SAAS,eAAe,EACtB,UACA,cACA,QACA,WAAW,MACX,YACA,WACA,GAAG,SACmB;CACtB,MAAM,QAAQ;CACd,OACE,qBAAC,OAAD;EACE,aAAU;EACV,MAAK;EACL,cAAW;EACX,WAAW,GAAG,6BAA6B,SAAS;EACpD,GAAI;EALN,UAAA;GAOG,aAAa,KAAA,KACZ,oBAAC,YAAD;IAAY,OAAO;IAAU,OAAM;IAAe,WAAW;GAAQ,CAAA;GAEtE,UACC,oBAAC,YAAD;IACE,SAAQ;IACR,MAAK;IACL,OAAM;IACN,SAAS;IACT,WAAW;IAEX,UAAA,oBAAC,MAAD,CAAO,CAAA;GACG,CAAA;GAEb,gBACC,oBAAC,YAAD;IACE,SAAQ;IACR,MAAK;IACL,OAAM;IACN,SAAS;IACT,WAAW;IAEX,UAAA,oBAAC,WAAD,CAAY,CAAA;GACF,CAAA;GAEb,cACC,qBAAAA,UAAA,EAAA,UAAA,CACE,oBAAC,YAAD;IACE,SAAQ;IACR,MAAK;IACL,OAAM;IACN,gBAAc,aAAa;IAC3B,eAAe,WAAW,aAAa,OAAO,OAAO,IAAI;IACzD,WAAW,GAAG,OAAO,aAAa,QAAQ,6BAA6B;IAEvE,UAAA,oBAAC,UAAD,EAAU,WAAW,GAAG,aAAa,QAAQ,cAAc,EAAI,CAAA;GACrD,CAAA,GACZ,oBAAC,YAAD;IACE,SAAQ;IACR,MAAK;IACL,OAAM;IACN,gBAAc,aAAa;IAC3B,eAAe,WAAW,aAAa,SAAS,OAAO,MAAM;IAC7D,WAAW,GAAG,OAAO,aAAa,UAAU,iBAAiB;IAE7D,UAAA,oBAAC,YAAD,EAAY,WAAW,GAAG,aAAa,UAAU,cAAc,EAAI,CAAA;GACzD,CAAA,CACZ,EAAA,CAAA;EAED;;AAET;;;;;AAeA,SAAS,cAAc,EACrB,cACA,UACA,UACA,cAAc,QACd,WACA,GAAG,SACkB;CACrB,MAAM,CAAC,OAAO,YAAY,MAAM,SAAS,YAAY;CACrD,MAAM,aAAa;EACjB,IAAI,MAAM,KAAK,GAAG,SAAS,MAAM,KAAK,CAAC;CACzC;CACA,OACE,qBAAC,QAAD;EACE,aAAU;EACV,WAAW,MAAM;GACf,EAAE,eAAe;GACjB,KAAK;EACP;EACA,WAAW,GAAG,kDAAkD,SAAS;EACzE,GAAI;EAPN,UAAA,CASE,oBAAC,YAAD;GACE,cAAW;GACJ;GAEP,WAAA;GACA,WAAW,MAAM,SAAS,EAAE,OAAO,KAAK;GACxC,YAAY,MAAM;IAChB,IAAI,EAAE,YAAY,eAAe,EAAE,YAAY,YAAY,KAAK;IAChE,IAAI,EAAE,QAAQ,UAAU;KACtB,EAAE,eAAe;KACjB,SAAS;IACX,OAAO,IAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,UAAU;KAC3C,EAAE,eAAe;KACjB,KAAK;IACP;GACF;GACA,WAAU;EACX,CAAA,GACD,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,oBAAC,QAAD;IAAQ,MAAK;IAAS,SAAQ;IAAQ,MAAK;IAAK,SAAS;IAAU,UAAA;GAE3D,CAAA,GACR,oBAAC,QAAD;IAAQ,MAAK;IAAS,MAAK;IAAK,UAAU,CAAC,MAAM,KAAK;IACnD,UAAA;GACK,CAAA,CACL;EACD,CAAA,CAAA;;AAEV;;;;;AA0BA,SAAS,mBAAmB,EAAE,OAAO,WAAW,GAAG,SAAkC;CACnF,IAAI,CAAC,MAAM,QAAQ,OAAO;CAC1B,OACE,oBAAC,OAAD;EACE,aAAU;EACV,WAAW,GAAG,wBAAwB,SAAS;EAC/C,GAAI;EAEH,UAAA,MAAM,KAAK,GAAG,MAAM;GACnB,MAAM,OAAO,EAAE,QAAQ;GACvB,IAAI,KAAK,WAAW,QAAQ,KAAK,EAAE,MACjC,OACE,oBAAC,cAAD;IAEE,KAAK,EAAE;IACP,OAAO,EAAE;IACT,UAAU,EAAE;IACZ,YAAY,EAAE;IACd,OAAO,EAAE;GACV,GANM,GAAG,EAAE,KAAK,GAAG,GAMnB;GAGL,IAAI,KAAK,WAAW,QAAQ,KAAK,EAAE,MACjC,OACE,oBAAC,KAAD;IAEE,MAAM,EAAE;IACR,QAAO;IACP,KAAI;IACJ,WAAU;IAEV,UAAA,oBAAC,OAAD;KAAK,KAAK,EAAE;KAAM,KAAK,EAAE;KAAM,WAAU;IAAqC,CAAA;GAC7E,GAPI,GAAG,EAAE,KAAK,GAAG,GAOjB;GAGP,MAAM,OACJ,qBAAAA,UAAA,EAAA,UAAA;IACE,oBAAC,UAAD;KAAU,eAAA;KAAY,WAAU;IAAyC,CAAA;IACzE,oBAAC,QAAD;KAAM,WAAU;KAAoB,UAAA,EAAE;IAAW,CAAA;IAChD,EAAE,SAAS,KAAA,KACV,oBAAC,QAAD;KAAM,WAAU;KAA0C,UAAA,YAAY,EAAE,IAAI;IAAQ,CAAA;GAEtF,EAAA,CAAA;GAEJ,MAAM,YACJ;GACF,OAAO,EAAE,OACP,oBAAC,KAAD;IAEE,MAAM,EAAE;IACR,QAAO;IACP,KAAI;IACJ,WAAW,GACT,WACA,iFACF;IAEC,UAAA;GACA,GAVI,GAAG,EAAE,KAAK,GAAG,GAUjB,IAEH,oBAAC,QAAD;IAA6B,WAAW;IACrC,UAAA;GACG,GAFK,GAAG,EAAE,KAAK,GAAG,GAElB;EAEV,CAAC;CACE,CAAA;AAET"}
1
+ {"version":3,"file":"message-actions.js","names":["_Fragment"],"sources":["../../src/components/message-actions.tsx"],"sourcesContent":["import Edit from '@burtson-labs/icons/react/edit';\nimport FileText from '@burtson-labs/icons/react/file-text';\nimport RotateCcw from '@burtson-labs/icons/react/rotate-ccw';\nimport ThumbsDown from '@burtson-labs/icons/react/thumbs-down';\nimport ThumbsUp from '@burtson-labs/icons/react/thumbs-up';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { formatBytes } from './attachment';\nimport { VoiceMessage } from './audio-player';\nimport { Button } from './button';\nimport { CopyButton } from './copy-button';\nimport { IconButton } from './icon-button';\n\nexport type MessageFeedback = 'up' | 'down' | null;\n\nexport interface MessageActionsProps extends React.ComponentProps<'div'> {\n /** Text for the copy button; leave out to hide it. */\n copyText?: string;\n onRegenerate?: () => void;\n /** Edit a sent message (user turns). Pair with MessageEditor. */\n onEdit?: () => void;\n /** The current rating; controlled. */\n feedback?: MessageFeedback;\n /** Adds thumbs up and down. Clicking the chosen one again clears it (null). */\n onFeedback?: (value: MessageFeedback) => void;\n}\n\n/**\n * The row under a message: copy, regenerate, edit and a thumbs rating, as\n * small icon buttons. Pass it to Message's `actions`, which shows it on\n * hover and focus (always on touch screens).\n */\nfunction MessageActions({\n copyText,\n onRegenerate,\n onEdit,\n feedback = null,\n onFeedback,\n className,\n ...props\n}: MessageActionsProps) {\n const small = 'size-7 text-muted-foreground hover:text-foreground pointer-coarse:size-10';\n return (\n <div\n data-slot=\"message-actions\"\n role=\"toolbar\"\n aria-label=\"Message actions\"\n className={cn('flex items-center gap-0.5', className)}\n {...props}\n >\n {copyText !== undefined && (\n <CopyButton value={copyText} label=\"Copy message\" className={small} />\n )}\n {onEdit && (\n <IconButton\n variant=\"ghost\"\n size=\"icon-sm\"\n label=\"Edit message\"\n onClick={onEdit}\n className={small}\n >\n <Edit />\n </IconButton>\n )}\n {onRegenerate && (\n <IconButton\n variant=\"ghost\"\n size=\"icon-sm\"\n label=\"Regenerate response\"\n onClick={onRegenerate}\n className={small}\n >\n <RotateCcw />\n </IconButton>\n )}\n {onFeedback && (\n <>\n <IconButton\n variant=\"ghost\"\n size=\"icon-sm\"\n label=\"Good response\"\n aria-pressed={feedback === 'up'}\n onClick={() => onFeedback(feedback === 'up' ? null : 'up')}\n className={cn(small, feedback === 'up' && 'text-brand hover:text-brand')}\n >\n <ThumbsUp className={cn(feedback === 'up' && 'fill-current')} />\n </IconButton>\n <IconButton\n variant=\"ghost\"\n size=\"icon-sm\"\n label=\"Bad response\"\n aria-pressed={feedback === 'down'}\n onClick={() => onFeedback(feedback === 'down' ? null : 'down')}\n className={cn(small, feedback === 'down' && 'text-foreground')}\n >\n <ThumbsDown className={cn(feedback === 'down' && 'fill-current')} />\n </IconButton>\n </>\n )}\n </div>\n );\n}\n\nexport interface MessageEditorProps extends Omit<React.ComponentProps<'form'>, 'onSubmit'> {\n /** The text being edited. */\n defaultValue: string;\n /** Save and send the edited message again. */\n onSubmit: (text: string) => void;\n onCancel: () => void;\n submitLabel?: string;\n}\n\n/**\n * Edit-and-resend in place of a sent message. Enter sends (never mid-IME\n * composition), Shift+Enter adds a line, Escape cancels.\n */\nfunction MessageEditor({\n defaultValue,\n onSubmit,\n onCancel,\n submitLabel = 'Send',\n className,\n ...props\n}: MessageEditorProps) {\n const [value, setValue] = React.useState(defaultValue);\n const send = () => {\n if (value.trim()) onSubmit(value.trim());\n };\n return (\n <form\n data-slot=\"message-editor\"\n onSubmit={(e) => {\n e.preventDefault();\n send();\n }}\n className={cn('grid w-full max-w-[85%] gap-2 justify-self-end', className)}\n {...props}\n >\n <textarea\n aria-label=\"Edit message\"\n value={value}\n // eslint-disable-next-line jsx-a11y/no-autofocus -- editing was just asked for\n autoFocus\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={(e) => {\n if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) return;\n if (e.key === 'Escape') {\n e.preventDefault();\n onCancel();\n } else if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n send();\n }\n }}\n className=\"field-sizing-content max-h-60 min-h-16 w-full resize-none rounded-lg border border-ring bg-surface px-3 py-2 text-base leading-6 inset-ring-1 inset-ring-ring outline-hidden! sm:text-sm\"\n />\n <div className=\"flex justify-end gap-2\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={onCancel}>\n Cancel\n </Button>\n <Button type=\"submit\" size=\"sm\" disabled={!value.trim()}>\n {submitLabel}\n </Button>\n </div>\n </form>\n );\n}\n\nexport interface MessageFile {\n name: string;\n /** Bytes. */\n size?: number;\n /** MIME type; audio renders a player, images a thumbnail. */\n type?: string;\n /** Where to open or play it. */\n href?: string;\n /** Waveform peaks for audio (see computePeaks). */\n peaks?: number[];\n /** Seconds, for audio. */\n duration?: number;\n /** Transcript for audio. */\n transcript?: React.ReactNode;\n}\n\nexport interface MessageAttachmentsProps extends React.ComponentProps<'div'> {\n files: MessageFile[];\n}\n\n/**\n * Files sent with a message: voice notes play inline, images show a\n * thumbnail, anything else is a named chip that opens the file.\n */\nfunction MessageAttachments({ files, className, ...props }: MessageAttachmentsProps) {\n if (!files.length) return null;\n return (\n <div\n data-slot=\"message-attachments\"\n className={cn('flex flex-wrap gap-2', className)}\n {...props}\n >\n {files.map((f, i) => {\n const type = f.type ?? '';\n if (type.startsWith('audio/') && f.href) {\n return (\n <VoiceMessage\n key={`${f.name}-${i}`}\n src={f.href}\n peaks={f.peaks}\n duration={f.duration}\n transcript={f.transcript}\n title={f.name}\n />\n );\n }\n if (type.startsWith('image/') && f.href) {\n return (\n <a\n key={`${f.name}-${i}`}\n href={f.href}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"block overflow-hidden rounded-lg border outline-none focus-visible:ring-[3px] focus-visible:ring-ring/20\"\n >\n <img src={f.href} alt={f.name} className=\"h-28 w-auto max-w-56 object-cover\" />\n </a>\n );\n }\n const chip = (\n <>\n <FileText aria-hidden className=\"size-4 shrink-0 text-muted-foreground\" />\n <span className=\"min-w-0 truncate\">{f.name}</span>\n {f.size !== undefined && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{formatBytes(f.size)}</span>\n )}\n </>\n );\n const chipClass =\n 'inline-flex max-w-64 items-center gap-2 rounded-md border bg-surface px-2.5 py-1.5 text-sm';\n return f.href ? (\n <a\n key={`${f.name}-${i}`}\n href={f.href}\n target=\"_blank\"\n rel=\"noreferrer\"\n className={cn(\n chipClass,\n 'outline-none hover:bg-muted focus-visible:ring-[3px] focus-visible:ring-ring/20',\n )}\n >\n {chip}\n </a>\n ) : (\n <span key={`${f.name}-${i}`} className={chipClass}>\n {chip}\n </span>\n );\n })}\n </div>\n );\n}\n\nexport { MessageActions, MessageAttachments, MessageEditor };\n"],"mappings":"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"}
@@ -5,8 +5,13 @@ import * as React from 'react';
5
5
  * with a strong border, and the one place a heavy shadow is allowed.
6
6
  */
7
7
  export declare const surfaceClasses = "z-50 animate-in rounded-lg border border-border-strong bg-surface-raised text-popover-foreground shadow-[0_16px_48px_rgb(0_0_0_/_0.18)] data-[state=closed]:animate-out data-[side=bottom]:[--bl-ty:-6px] data-[side=top]:[--bl-ty:6px] data-[side=left]:[--bl-tx:6px] data-[side=right]:[--bl-tx:-6px]";
8
- /** A menu row: 32px, 8px radius; the focused row is a quiet fill, like an active tab. */
9
- export declare const menuItemClasses = "relative flex min-h-8 cursor-default items-center gap-2 rounded-sm px-2 text-[13px] outline-hidden select-none focus:bg-muted focus:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground";
8
+ /**
9
+ * A menu row: 32px, 8px radius (the surface's 12px less its 4px padding); the
10
+ * focused row is a quiet secondary fill (muted is too close to the raised
11
+ * surface in dark mode to read). The outline is suppressed
12
+ * with !important so a host page's global focus outline cannot box the row.
13
+ */
14
+ export declare const menuItemClasses = "relative flex min-h-8 cursor-default items-center gap-2 rounded-sm px-2 text-[13px] outline-hidden! select-none focus:bg-secondary focus:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground";
10
15
  declare function Popover(props: React.ComponentProps<typeof PopoverPrimitive.Root>): React.JSX.Element;
11
16
  declare function PopoverTrigger(props: React.ComponentProps<typeof PopoverPrimitive.Trigger>): React.JSX.Element;
12
17
  declare function PopoverAnchor(props: React.ComponentProps<typeof PopoverPrimitive.Anchor>): React.JSX.Element;
@@ -8,8 +8,13 @@ import { jsx } from "react/jsx-runtime";
8
8
  * with a strong border, and the one place a heavy shadow is allowed.
9
9
  */
10
10
  var surfaceClasses = "z-50 animate-in rounded-lg border border-border-strong bg-surface-raised text-popover-foreground shadow-[0_16px_48px_rgb(0_0_0_/_0.18)] data-[state=closed]:animate-out data-[side=bottom]:[--bl-ty:-6px] data-[side=top]:[--bl-ty:6px] data-[side=left]:[--bl-tx:6px] data-[side=right]:[--bl-tx:-6px]";
11
- /** A menu row: 32px, 8px radius; the focused row is a quiet fill, like an active tab. */
12
- var menuItemClasses = "relative flex min-h-8 cursor-default items-center gap-2 rounded-sm px-2 text-[13px] outline-hidden select-none focus:bg-muted focus:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground";
11
+ /**
12
+ * A menu row: 32px, 8px radius (the surface's 12px less its 4px padding); the
13
+ * focused row is a quiet secondary fill (muted is too close to the raised
14
+ * surface in dark mode to read). The outline is suppressed
15
+ * with !important so a host page's global focus outline cannot box the row.
16
+ */
17
+ var menuItemClasses = "relative flex min-h-8 cursor-default items-center gap-2 rounded-sm px-2 text-[13px] outline-hidden! select-none focus:bg-secondary focus:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground";
13
18
  function Popover$1(props) {
14
19
  return /* @__PURE__ */ jsx(Popover.Root, {
15
20
  "data-slot": "popover",
@@ -1 +1 @@
1
- {"version":3,"file":"popover.js","names":["Popover","PopoverPrimitive"],"sources":["../../src/components/popover.tsx"],"sourcesContent":["import { Popover as PopoverPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\n/**\n * The floating surface shared by popovers, menus and select lists: raised,\n * with a strong border, and the one place a heavy shadow is allowed.\n */\nexport const surfaceClasses =\n 'z-50 animate-in rounded-lg border border-border-strong bg-surface-raised text-popover-foreground shadow-[0_16px_48px_rgb(0_0_0_/_0.18)] data-[state=closed]:animate-out data-[side=bottom]:[--bl-ty:-6px] data-[side=top]:[--bl-ty:6px] data-[side=left]:[--bl-tx:6px] data-[side=right]:[--bl-tx:-6px]';\n\n/** A menu row: 32px, 8px radius; the focused row is a quiet fill, like an active tab. */\nexport const menuItemClasses =\n \"relative flex min-h-8 cursor-default items-center gap-2 rounded-sm px-2 text-[13px] outline-hidden select-none focus:bg-muted focus:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground\";\n\nfunction Popover(props: React.ComponentProps<typeof PopoverPrimitive.Root>) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n}\n\nfunction PopoverTrigger(props: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />;\n}\n\nfunction PopoverAnchor(props: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {\n return <PopoverPrimitive.Anchor data-slot=\"popover-anchor\" {...props} />;\n}\n\nfunction PopoverContent({\n className,\n align = 'center',\n sideOffset = 6,\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Content>) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n surfaceClasses,\n 'w-72 max-w-[calc(100vw-2rem)] max-h-(--radix-popover-content-available-height) overflow-y-auto origin-(--radix-popover-content-transform-origin) p-4 outline-hidden',\n className,\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n );\n}\n\nexport { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };\n"],"mappings":";;;;;;;;;AASA,IAAa,iBACX;;AAGF,IAAa,kBACX;AAEF,SAASA,UAAQ,OAA2D;CAC1E,OAAO,oBAACC,QAAiB,MAAlB;EAAuB,aAAU;EAAU,GAAI;CAAQ,CAAA;AAChE;AAEA,SAAS,eAAe,OAA8D;CACpF,OAAO,oBAACA,QAAiB,SAAlB;EAA0B,aAAU;EAAkB,GAAI;CAAQ,CAAA;AAC3E;AAEA,SAAS,cAAc,OAA6D;CAClF,OAAO,oBAACA,QAAiB,QAAlB;EAAyB,aAAU;EAAiB,GAAI;CAAQ,CAAA;AACzE;AAEA,SAAS,eAAe,EACtB,WACA,QAAQ,UACR,aAAa,GACb,GAAG,SACqD;CACxD,OACE,oBAACA,QAAiB,QAAlB,EAAA,UACE,oBAACA,QAAiB,SAAlB;EACE,aAAU;EACH;EACK;EACZ,WAAW,GACT,gBACA,uKACA,SACF;EACA,GAAI;CACL,CAAA,EACsB,CAAA;AAE7B"}
1
+ {"version":3,"file":"popover.js","names":["Popover","PopoverPrimitive"],"sources":["../../src/components/popover.tsx"],"sourcesContent":["import { Popover as PopoverPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\n/**\n * The floating surface shared by popovers, menus and select lists: raised,\n * with a strong border, and the one place a heavy shadow is allowed.\n */\nexport const surfaceClasses =\n 'z-50 animate-in rounded-lg border border-border-strong bg-surface-raised text-popover-foreground shadow-[0_16px_48px_rgb(0_0_0_/_0.18)] data-[state=closed]:animate-out data-[side=bottom]:[--bl-ty:-6px] data-[side=top]:[--bl-ty:6px] data-[side=left]:[--bl-tx:6px] data-[side=right]:[--bl-tx:-6px]';\n\n/**\n * A menu row: 32px, 8px radius (the surface's 12px less its 4px padding); the\n * focused row is a quiet secondary fill (muted is too close to the raised\n * surface in dark mode to read). The outline is suppressed\n * with !important so a host page's global focus outline cannot box the row.\n */\nexport const menuItemClasses =\n \"relative flex min-h-8 cursor-default items-center gap-2 rounded-sm px-2 text-[13px] outline-hidden! select-none focus:bg-secondary focus:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground\";\n\nfunction Popover(props: React.ComponentProps<typeof PopoverPrimitive.Root>) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n}\n\nfunction PopoverTrigger(props: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />;\n}\n\nfunction PopoverAnchor(props: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {\n return <PopoverPrimitive.Anchor data-slot=\"popover-anchor\" {...props} />;\n}\n\nfunction PopoverContent({\n className,\n align = 'center',\n sideOffset = 6,\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Content>) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n surfaceClasses,\n 'w-72 max-w-[calc(100vw-2rem)] max-h-(--radix-popover-content-available-height) overflow-y-auto origin-(--radix-popover-content-transform-origin) p-4 outline-hidden',\n className,\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n );\n}\n\nexport { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };\n"],"mappings":";;;;;;;;;AASA,IAAa,iBACX;;;;;;;AAQF,IAAa,kBACX;AAEF,SAASA,UAAQ,OAA2D;CAC1E,OAAO,oBAACC,QAAiB,MAAlB;EAAuB,aAAU;EAAU,GAAI;CAAQ,CAAA;AAChE;AAEA,SAAS,eAAe,OAA8D;CACpF,OAAO,oBAACA,QAAiB,SAAlB;EAA0B,aAAU;EAAkB,GAAI;CAAQ,CAAA;AAC3E;AAEA,SAAS,cAAc,OAA6D;CAClF,OAAO,oBAACA,QAAiB,QAAlB;EAAyB,aAAU;EAAiB,GAAI;CAAQ,CAAA;AACzE;AAEA,SAAS,eAAe,EACtB,WACA,QAAQ,UACR,aAAa,GACb,GAAG,SACqD;CACxD,OACE,oBAACA,QAAiB,QAAlB,EAAA,UACE,oBAACA,QAAiB,SAAlB;EACE,aAAU;EACH;EACK;EACZ,WAAW,GACT,gBACA,uKACA,SACF;EACA,GAAI;CACL,CAAA,EACsB,CAAA;AAE7B"}
@@ -1,6 +1,6 @@
1
1
  import { cn } from "../lib/utils.js";
2
- import { IconButton } from "./icon-button.js";
3
2
  import { Input } from "./input.js";
3
+ import { IconButton } from "./icon-button.js";
4
4
  import * as React from "react";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  import Eye from "@burtson-labs/icons/react/eye";
@@ -79,7 +79,7 @@ function SelectLabel({ className, ...props }) {
79
79
  function SelectItem({ className, children, ...props }) {
80
80
  return /* @__PURE__ */ jsxs(Select.Item, {
81
81
  "data-slot": "select-item",
82
- className: cn("relative flex min-h-8 w-full cursor-default items-center gap-2 rounded-sm pr-8 pl-2 text-[13px] outline-hidden select-none focus:bg-muted focus:text-foreground data-[state=checked]:font-semibold data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
82
+ className: cn("relative flex min-h-8 w-full cursor-default items-center gap-2 rounded-sm pr-8 pl-2 text-[13px] outline-hidden! select-none focus:bg-secondary focus:text-foreground data-[state=checked]:font-semibold data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
83
83
  ...props,
84
84
  children: [/* @__PURE__ */ jsx("span", {
85
85
  className: "absolute right-2 flex size-3.5 items-center justify-center",
@@ -1 +1 @@
1
- {"version":3,"file":"select.js","names":["Select","SelectPrimitive"],"sources":["../../src/components/select.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronDown from '@burtson-labs/icons/react/chevron-down';\nimport ChevronUp from '@burtson-labs/icons/react/chevron-up';\nimport { Select as SelectPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { fieldClasses } from './input';\nimport { surfaceClasses } from './popover';\n\nfunction Select(props: React.ComponentProps<typeof SelectPrimitive.Root>) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />;\n}\n\nfunction SelectGroup(props: React.ComponentProps<typeof SelectPrimitive.Group>) {\n return <SelectPrimitive.Group data-slot=\"select-group\" {...props} />;\n}\n\nfunction SelectValue(props: React.ComponentProps<typeof SelectPrimitive.Value>) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />;\n}\n\nfunction SelectTrigger({\n className,\n size = 'default',\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Trigger> & { size?: 'sm' | 'default' }) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={size}\n className={cn(\n fieldClasses,\n \"flex w-fit items-center justify-between gap-2 py-2 whitespace-nowrap data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDown className=\"size-4 opacity-60\" aria-hidden />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n );\n}\n\nfunction SelectContent({\n className,\n children,\n position = 'popper',\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Content>) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n className={cn(\n surfaceClasses,\n 'relative max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto',\n position === 'popper' &&\n 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n className,\n )}\n position={position}\n {...props}\n >\n <SelectPrimitive.ScrollUpButton className=\"flex cursor-default items-center justify-center py-1\">\n <ChevronUp className=\"size-4\" aria-hidden />\n </SelectPrimitive.ScrollUpButton>\n <SelectPrimitive.Viewport\n className={cn(\n 'p-1',\n position === 'popper' &&\n 'h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width) scroll-my-1',\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectPrimitive.ScrollDownButton className=\"flex cursor-default items-center justify-center py-1\">\n <ChevronDown className=\"size-4\" aria-hidden />\n </SelectPrimitive.ScrollDownButton>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n );\n}\n\nfunction SelectLabel({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Label>) {\n return (\n <SelectPrimitive.Label\n data-slot=\"select-label\"\n className={cn(\n 'px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SelectItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Item>) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"relative flex min-h-8 w-full cursor-default items-center gap-2 rounded-sm pr-8 pl-2 text-[13px] outline-hidden select-none focus:bg-muted focus:text-foreground data-[state=checked]:font-semibold data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex size-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <Check className=\"size-4 text-brand\" aria-hidden />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n );\n}\n\nfunction SelectSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Separator>) {\n return (\n <SelectPrimitive.Separator\n data-slot=\"select-separator\"\n className={cn('pointer-events-none -mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n};\n"],"mappings":";;;;;;;;;;AAWA,SAASA,SAAO,OAA0D;CACxE,OAAO,oBAACC,OAAgB,MAAjB;EAAsB,aAAU;EAAS,GAAI;CAAQ,CAAA;AAC9D;AAEA,SAAS,YAAY,OAA2D;CAC9E,OAAO,oBAACA,OAAgB,OAAjB;EAAuB,aAAU;EAAe,GAAI;CAAQ,CAAA;AACrE;AAEA,SAAS,YAAY,OAA2D;CAC9E,OAAO,oBAACA,OAAgB,OAAjB;EAAuB,aAAU;EAAe,GAAI;CAAQ,CAAA;AACrE;AAEA,SAAS,cAAc,EACrB,WACA,OAAO,WACP,UACA,GAAG,SACkF;CACrF,OACE,qBAACA,OAAgB,SAAjB;EACE,aAAU;EACV,aAAW;EACX,WAAW,GACT,cACA,+XACA,SACF;EACA,GAAI;EARN,UAAA,CAUG,UACD,oBAACA,OAAgB,MAAjB;GAAsB,SAAA;GACpB,UAAA,oBAAC,aAAD;IAAa,WAAU;IAAoB,eAAA;GAAa,CAAA;EACpC,CAAA,CACC;;AAE7B;AAEA,SAAS,cAAc,EACrB,WACA,UACA,WAAW,UACX,GAAG,SACoD;CACvD,OACE,oBAACA,OAAgB,QAAjB,EAAA,UACE,qBAACA,OAAgB,SAAjB;EACE,aAAU;EACV,WAAW,GACT,gBACA,4JACA,aAAa,YACX,mIACF,SACF;EACU;EACV,GAAI;EAVN,UAAA;GAYE,oBAACA,OAAgB,gBAAjB;IAAgC,WAAU;IACxC,UAAA,oBAAC,WAAD;KAAW,WAAU;KAAS,eAAA;IAAa,CAAA;GACb,CAAA;GAChC,oBAACA,OAAgB,UAAjB;IACE,WAAW,GACT,OACA,aAAa,YACX,2FACJ;IAEC;GACuB,CAAA;GAC1B,oBAACA,OAAgB,kBAAjB;IAAkC,WAAU;IAC1C,UAAA,oBAAC,aAAD;KAAa,WAAU;KAAS,eAAA;IAAa,CAAA;GACb,CAAA;EACX;CACH,CAAA,EAAA,CAAA;AAE5B;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,SAA6D;CAChG,OACE,oBAACA,OAAgB,OAAjB;EACE,aAAU;EACV,WAAW,GACT,8FACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAClB,WACA,UACA,GAAG,SACiD;CACpD,OACE,qBAACA,OAAgB,MAAjB;EACE,aAAU;EACV,WAAW,GACT,uVACA,SACF;EACA,GAAI;EANN,UAAA,CAQE,oBAAC,QAAD;GAAM,WAAU;GACd,UAAA,oBAACA,OAAgB,eAAjB,EAAA,UACE,oBAAC,OAAD;IAAO,WAAU;IAAoB,eAAA;GAAa,CAAA,EACrB,CAAA;EAC3B,CAAA,GACN,oBAACA,OAAgB,UAAjB,EAA2B,SAAmC,CAAA,CAC1C;;AAE1B;AAEA,SAAS,gBAAgB,EACvB,WACA,GAAG,SACsD;CACzD,OACE,oBAACA,OAAgB,WAAjB;EACE,aAAU;EACV,WAAW,GAAG,iDAAiD,SAAS;EACxE,GAAI;CACL,CAAA;AAEL"}
1
+ {"version":3,"file":"select.js","names":["Select","SelectPrimitive"],"sources":["../../src/components/select.tsx"],"sourcesContent":["import Check from '@burtson-labs/icons/react/check';\nimport ChevronDown from '@burtson-labs/icons/react/chevron-down';\nimport ChevronUp from '@burtson-labs/icons/react/chevron-up';\nimport { Select as SelectPrimitive } from 'radix-ui';\nimport * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nimport { fieldClasses } from './input';\nimport { surfaceClasses } from './popover';\n\nfunction Select(props: React.ComponentProps<typeof SelectPrimitive.Root>) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />;\n}\n\nfunction SelectGroup(props: React.ComponentProps<typeof SelectPrimitive.Group>) {\n return <SelectPrimitive.Group data-slot=\"select-group\" {...props} />;\n}\n\nfunction SelectValue(props: React.ComponentProps<typeof SelectPrimitive.Value>) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />;\n}\n\nfunction SelectTrigger({\n className,\n size = 'default',\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Trigger> & { size?: 'sm' | 'default' }) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={size}\n className={cn(\n fieldClasses,\n \"flex w-fit items-center justify-between gap-2 py-2 whitespace-nowrap data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDown className=\"size-4 opacity-60\" aria-hidden />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n );\n}\n\nfunction SelectContent({\n className,\n children,\n position = 'popper',\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Content>) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n className={cn(\n surfaceClasses,\n 'relative max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto',\n position === 'popper' &&\n 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n className,\n )}\n position={position}\n {...props}\n >\n <SelectPrimitive.ScrollUpButton className=\"flex cursor-default items-center justify-center py-1\">\n <ChevronUp className=\"size-4\" aria-hidden />\n </SelectPrimitive.ScrollUpButton>\n <SelectPrimitive.Viewport\n className={cn(\n 'p-1',\n position === 'popper' &&\n 'h-(--radix-select-trigger-height) w-full min-w-(--radix-select-trigger-width) scroll-my-1',\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectPrimitive.ScrollDownButton className=\"flex cursor-default items-center justify-center py-1\">\n <ChevronDown className=\"size-4\" aria-hidden />\n </SelectPrimitive.ScrollDownButton>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n );\n}\n\nfunction SelectLabel({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Label>) {\n return (\n <SelectPrimitive.Label\n data-slot=\"select-label\"\n className={cn(\n 'px-2 pt-2 pb-1 text-[11px] font-semibold tracking-[0.08em] text-muted-foreground uppercase',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction SelectItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Item>) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"relative flex min-h-8 w-full cursor-default items-center gap-2 rounded-sm pr-8 pl-2 text-[13px] outline-hidden! select-none focus:bg-secondary focus:text-foreground data-[state=checked]:font-semibold data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n >\n <span className=\"absolute right-2 flex size-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <Check className=\"size-4 text-brand\" aria-hidden />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n );\n}\n\nfunction SelectSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Separator>) {\n return (\n <SelectPrimitive.Separator\n data-slot=\"select-separator\"\n className={cn('pointer-events-none -mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n );\n}\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n};\n"],"mappings":";;;;;;;;;;AAWA,SAASA,SAAO,OAA0D;CACxE,OAAO,oBAACC,OAAgB,MAAjB;EAAsB,aAAU;EAAS,GAAI;CAAQ,CAAA;AAC9D;AAEA,SAAS,YAAY,OAA2D;CAC9E,OAAO,oBAACA,OAAgB,OAAjB;EAAuB,aAAU;EAAe,GAAI;CAAQ,CAAA;AACrE;AAEA,SAAS,YAAY,OAA2D;CAC9E,OAAO,oBAACA,OAAgB,OAAjB;EAAuB,aAAU;EAAe,GAAI;CAAQ,CAAA;AACrE;AAEA,SAAS,cAAc,EACrB,WACA,OAAO,WACP,UACA,GAAG,SACkF;CACrF,OACE,qBAACA,OAAgB,SAAjB;EACE,aAAU;EACV,aAAW;EACX,WAAW,GACT,cACA,+XACA,SACF;EACA,GAAI;EARN,UAAA,CAUG,UACD,oBAACA,OAAgB,MAAjB;GAAsB,SAAA;GACpB,UAAA,oBAAC,aAAD;IAAa,WAAU;IAAoB,eAAA;GAAa,CAAA;EACpC,CAAA,CACC;;AAE7B;AAEA,SAAS,cAAc,EACrB,WACA,UACA,WAAW,UACX,GAAG,SACoD;CACvD,OACE,oBAACA,OAAgB,QAAjB,EAAA,UACE,qBAACA,OAAgB,SAAjB;EACE,aAAU;EACV,WAAW,GACT,gBACA,4JACA,aAAa,YACX,mIACF,SACF;EACU;EACV,GAAI;EAVN,UAAA;GAYE,oBAACA,OAAgB,gBAAjB;IAAgC,WAAU;IACxC,UAAA,oBAAC,WAAD;KAAW,WAAU;KAAS,eAAA;IAAa,CAAA;GACb,CAAA;GAChC,oBAACA,OAAgB,UAAjB;IACE,WAAW,GACT,OACA,aAAa,YACX,2FACJ;IAEC;GACuB,CAAA;GAC1B,oBAACA,OAAgB,kBAAjB;IAAkC,WAAU;IAC1C,UAAA,oBAAC,aAAD;KAAa,WAAU;KAAS,eAAA;IAAa,CAAA;GACb,CAAA;EACX;CACH,CAAA,EAAA,CAAA;AAE5B;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,SAA6D;CAChG,OACE,oBAACA,OAAgB,OAAjB;EACE,aAAU;EACV,WAAW,GACT,8FACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,WAAW,EAClB,WACA,UACA,GAAG,SACiD;CACpD,OACE,qBAACA,OAAgB,MAAjB;EACE,aAAU;EACV,WAAW,GACT,4VACA,SACF;EACA,GAAI;EANN,UAAA,CAQE,oBAAC,QAAD;GAAM,WAAU;GACd,UAAA,oBAACA,OAAgB,eAAjB,EAAA,UACE,oBAAC,OAAD;IAAO,WAAU;IAAoB,eAAA;GAAa,CAAA,EACrB,CAAA;EAC3B,CAAA,GACN,oBAACA,OAAgB,UAAjB,EAA2B,SAAmC,CAAA,CAC1C;;AAE1B;AAEA,SAAS,gBAAgB,EACvB,WACA,GAAG,SACsD;CACzD,OACE,oBAACA,OAAgB,WAAjB;EACE,aAAU;EACV,WAAW,GAAG,iDAAiD,SAAS;EACxE,GAAI;CACL,CAAA;AAEL"}
@@ -5,8 +5,20 @@ export interface TableProps extends React.ComponentProps<'table'> {
5
5
  /** Keep the header visible while the container scrolls; give it a height. */
6
6
  stickyHeader?: boolean;
7
7
  containerClassName?: string;
8
+ /**
9
+ * Props for the scrolling wrapper (`tabIndex`, `role`, `aria-*`, `ref`, ...).
10
+ * Anything set here wins over what `scrollLabel` sets.
11
+ */
12
+ containerProps?: React.ComponentProps<'div'>;
13
+ /**
14
+ * Accessible name for the scroll container. With it (or an `aria-label` /
15
+ * `aria-labelledby` in `containerProps`) the wrapper becomes a named region
16
+ * that joins the tab order while its content overflows, so keyboard users
17
+ * can scroll it (WCAG 2.1.1, axe scrollable-region-focusable).
18
+ */
19
+ scrollLabel?: string;
8
20
  }
9
- declare function Table({ className, density, stickyHeader, containerClassName, ...props }: TableProps): React.JSX.Element;
21
+ declare function Table({ className, density, stickyHeader, containerClassName, containerProps, scrollLabel, ...props }: TableProps): React.JSX.Element;
10
22
  declare function TableHeader({ className, ...props }: React.ComponentProps<'thead'>): React.JSX.Element;
11
23
  declare function TableBody({ className, ...props }: React.ComponentProps<'tbody'>): React.JSX.Element;
12
24
  declare function TableFooter({ className, ...props }: React.ComponentProps<'tfoot'>): React.JSX.Element;
@@ -1,13 +1,46 @@
1
1
  import { cn } from "../lib/utils.js";
2
- import "react";
2
+ import * as React from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  //#region src/components/table.tsx
5
- function Table({ className, density = "default", stickyHeader = false, containerClassName, ...props }) {
5
+ /** True while the element's content is larger than its box. */
6
+ function useOverflows(ref, enabled) {
7
+ const [overflows, setOverflows] = React.useState(false);
8
+ React.useEffect(() => {
9
+ const el = ref.current;
10
+ if (!enabled || !el) return;
11
+ const update = () => setOverflows(el.scrollWidth > el.clientWidth || el.scrollHeight > el.clientHeight);
12
+ update();
13
+ if (typeof ResizeObserver === "undefined") return;
14
+ const ro = new ResizeObserver(update);
15
+ ro.observe(el);
16
+ if (el.firstElementChild) ro.observe(el.firstElementChild);
17
+ return () => ro.disconnect();
18
+ }, [ref, enabled]);
19
+ return overflows;
20
+ }
21
+ function assignRef(ref, node) {
22
+ if (typeof ref === "function") ref(node);
23
+ else if (ref) ref.current = node;
24
+ }
25
+ function Table({ className, density = "default", stickyHeader = false, containerClassName, containerProps, scrollLabel, ...props }) {
26
+ const { className: containerPropsClassName, ref: containerRef, ...wrapperProps } = containerProps ?? {};
27
+ const local = React.useRef(null);
28
+ const setRef = React.useCallback((node) => {
29
+ local.current = node;
30
+ assignRef(containerRef, node);
31
+ }, [containerRef]);
32
+ const named = Boolean(scrollLabel || wrapperProps["aria-label"] || wrapperProps["aria-labelledby"]);
33
+ const overflows = useOverflows(local, named);
6
34
  return /* @__PURE__ */ jsx("div", {
7
35
  "data-slot": "table-container",
8
36
  "data-density": density,
9
37
  "data-sticky": stickyHeader || void 0,
10
- className: cn("group/table relative w-full overflow-auto", containerClassName),
38
+ role: named ? "region" : void 0,
39
+ "aria-label": scrollLabel,
40
+ tabIndex: named && overflows ? 0 : void 0,
41
+ ...wrapperProps,
42
+ ref: setRef,
43
+ className: cn("group/table relative w-full overflow-auto", containerClassName, containerPropsClassName),
11
44
  children: /* @__PURE__ */ jsx("table", {
12
45
  "data-slot": "table",
13
46
  className: cn("w-full caption-bottom text-[13px]", className),
@@ -1 +1 @@
1
- {"version":3,"file":"table.js","names":[],"sources":["../../src/components/table.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nexport interface TableProps extends React.ComponentProps<'table'> {\n /** `compact` for dense ops screens (32px rows), `default` 40px. */\n density?: 'compact' | 'default';\n /** Keep the header visible while the container scrolls; give it a height. */\n stickyHeader?: boolean;\n containerClassName?: string;\n}\n\nfunction Table({\n className,\n density = 'default',\n stickyHeader = false,\n containerClassName,\n ...props\n}: TableProps) {\n return (\n <div\n data-slot=\"table-container\"\n data-density={density}\n data-sticky={stickyHeader || undefined}\n className={cn('group/table relative w-full overflow-auto', containerClassName)}\n >\n <table\n data-slot=\"table\"\n className={cn('w-full caption-bottom text-[13px]', className)}\n {...props}\n />\n </div>\n );\n}\n\nfunction TableHeader({ className, ...props }: React.ComponentProps<'thead'>) {\n return (\n <thead\n data-slot=\"table-header\"\n className={cn(\n 'bg-surface-muted [&_tr]:border-b group-data-[sticky]/table:sticky group-data-[sticky]/table:top-0 group-data-[sticky]/table:z-10',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TableBody({ className, ...props }: React.ComponentProps<'tbody'>) {\n return (\n <tbody\n data-slot=\"table-body\"\n className={cn('[&_tr:last-child]:border-0', className)}\n {...props}\n />\n );\n}\n\nfunction TableFooter({ className, ...props }: React.ComponentProps<'tfoot'>) {\n return (\n <tfoot\n data-slot=\"table-footer\"\n className={cn('border-t bg-surface-muted font-medium [&>tr]:last:border-b-0', className)}\n {...props}\n />\n );\n}\n\n/** Set `data-state=\"selected\"` (or `selected`) to mark a chosen row. */\nfunction TableRow({\n className,\n selected,\n ...props\n}: React.ComponentProps<'tr'> & { selected?: boolean }) {\n return (\n <tr\n data-slot=\"table-row\"\n data-state={selected ? 'selected' : undefined}\n aria-selected={selected || undefined}\n className={cn(\n 'border-b transition-colors hover:bg-muted/60 data-[state=selected]:bg-brand-soft/60 data-[state=selected]:shadow-[inset_2px_0_0_var(--color-brand)]',\n className,\n )}\n {...props}\n />\n );\n}\n\n/** `numeric` right-aligns with tabular figures, for counts, money and durations. */\nfunction TableHead({\n className,\n numeric,\n ...props\n}: React.ComponentProps<'th'> & { numeric?: boolean }) {\n return (\n <th\n data-slot=\"table-head\"\n className={cn(\n 'h-9 px-3 text-left align-middle text-[11px] font-semibold tracking-[0.06em] whitespace-nowrap text-muted-foreground uppercase group-data-[density=compact]/table:h-8 [&:has([role=checkbox])]:w-10 [&:has([role=checkbox])]:pr-0',\n numeric && 'text-right tabular-nums',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TableCell({\n className,\n numeric,\n ...props\n}: React.ComponentProps<'td'> & { numeric?: boolean }) {\n return (\n <td\n data-slot=\"table-cell\"\n className={cn(\n 'h-10 px-3 align-middle whitespace-nowrap group-data-[density=compact]/table:h-8 [&:has([role=checkbox])]:pr-0',\n numeric && 'text-right font-mono text-[12.5px] tabular-nums',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TableCaption({ className, ...props }: React.ComponentProps<'caption'>) {\n return (\n <caption\n data-slot=\"table-caption\"\n className={cn('mt-3 text-xs text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nexport { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };\n"],"mappings":";;;;AAYA,SAAS,MAAM,EACb,WACA,UAAU,WACV,eAAe,OACf,oBACA,GAAG,SACU;CACb,OACE,oBAAC,OAAD;EACE,aAAU;EACV,gBAAc;EACd,eAAa,gBAAgB,KAAA;EAC7B,WAAW,GAAG,6CAA6C,kBAAkB;EAE7E,UAAA,oBAAC,SAAD;GACE,aAAU;GACV,WAAW,GAAG,qCAAqC,SAAS;GAC5D,GAAI;EACL,CAAA;CACE,CAAA;AAET;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,SAAwC;CAC3E,OACE,oBAAC,SAAD;EACE,aAAU;EACV,WAAW,GACT,oIACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,UAAU,EAAE,WAAW,GAAG,SAAwC;CACzE,OACE,oBAAC,SAAD;EACE,aAAU;EACV,WAAW,GAAG,8BAA8B,SAAS;EACrD,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,SAAwC;CAC3E,OACE,oBAAC,SAAD;EACE,aAAU;EACV,WAAW,GAAG,gEAAgE,SAAS;EACvF,GAAI;CACL,CAAA;AAEL;;AAGA,SAAS,SAAS,EAChB,WACA,UACA,GAAG,SACmD;CACtD,OACE,oBAAC,MAAD;EACE,aAAU;EACV,cAAY,WAAW,aAAa,KAAA;EACpC,iBAAe,YAAY,KAAA;EAC3B,WAAW,GACT,uJACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;;AAGA,SAAS,UAAU,EACjB,WACA,SACA,GAAG,SACkD;CACrD,OACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GACT,oOACA,WAAW,2BACX,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,UAAU,EACjB,WACA,SACA,GAAG,SACkD;CACrD,OACE,oBAAC,MAAD;EACE,aAAU;EACV,WAAW,GACT,iHACA,WAAW,mDACX,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,aAAa,EAAE,WAAW,GAAG,SAA0C;CAC9E,OACE,oBAAC,WAAD;EACE,aAAU;EACV,WAAW,GAAG,sCAAsC,SAAS;EAC7D,GAAI;CACL,CAAA;AAEL"}
1
+ {"version":3,"file":"table.js","names":[],"sources":["../../src/components/table.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../lib/utils';\n\nexport interface TableProps extends React.ComponentProps<'table'> {\n /** `compact` for dense ops screens (32px rows), `default` 40px. */\n density?: 'compact' | 'default';\n /** Keep the header visible while the container scrolls; give it a height. */\n stickyHeader?: boolean;\n containerClassName?: string;\n /**\n * Props for the scrolling wrapper (`tabIndex`, `role`, `aria-*`, `ref`, ...).\n * Anything set here wins over what `scrollLabel` sets.\n */\n containerProps?: React.ComponentProps<'div'>;\n /**\n * Accessible name for the scroll container. With it (or an `aria-label` /\n * `aria-labelledby` in `containerProps`) the wrapper becomes a named region\n * that joins the tab order while its content overflows, so keyboard users\n * can scroll it (WCAG 2.1.1, axe scrollable-region-focusable).\n */\n scrollLabel?: string;\n}\n\n/** True while the element's content is larger than its box. */\nfunction useOverflows(ref: React.RefObject<HTMLElement | null>, enabled: boolean): boolean {\n const [overflows, setOverflows] = React.useState(false);\n React.useEffect(() => {\n const el = ref.current;\n if (!enabled || !el) return;\n const update = () =>\n setOverflows(el.scrollWidth > el.clientWidth || el.scrollHeight > el.clientHeight);\n update();\n if (typeof ResizeObserver === 'undefined') return;\n const ro = new ResizeObserver(update);\n ro.observe(el);\n if (el.firstElementChild) ro.observe(el.firstElementChild);\n return () => ro.disconnect();\n }, [ref, enabled]);\n return overflows;\n}\n\nfunction assignRef<T>(ref: React.Ref<T> | undefined, node: T | null) {\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n}\n\nfunction Table({\n className,\n density = 'default',\n stickyHeader = false,\n containerClassName,\n containerProps,\n scrollLabel,\n ...props\n}: TableProps) {\n const {\n className: containerPropsClassName,\n ref: containerRef,\n ...wrapperProps\n } = containerProps ?? {};\n const local = React.useRef<HTMLDivElement | null>(null);\n const setRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n local.current = node;\n assignRef(containerRef, node);\n },\n [containerRef],\n );\n const named = Boolean(\n scrollLabel || wrapperProps['aria-label'] || wrapperProps['aria-labelledby'],\n );\n const overflows = useOverflows(local, named);\n return (\n <div\n data-slot=\"table-container\"\n data-density={density}\n data-sticky={stickyHeader || undefined}\n role={named ? 'region' : undefined}\n aria-label={scrollLabel}\n // A scrollable region must be reachable by keyboard; only while it scrolls.\n tabIndex={named && overflows ? 0 : undefined}\n {...wrapperProps}\n ref={setRef}\n className={cn(\n 'group/table relative w-full overflow-auto',\n containerClassName,\n containerPropsClassName,\n )}\n >\n <table\n data-slot=\"table\"\n className={cn('w-full caption-bottom text-[13px]', className)}\n {...props}\n />\n </div>\n );\n}\n\nfunction TableHeader({ className, ...props }: React.ComponentProps<'thead'>) {\n return (\n <thead\n data-slot=\"table-header\"\n className={cn(\n 'bg-surface-muted [&_tr]:border-b group-data-[sticky]/table:sticky group-data-[sticky]/table:top-0 group-data-[sticky]/table:z-10',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TableBody({ className, ...props }: React.ComponentProps<'tbody'>) {\n return (\n <tbody\n data-slot=\"table-body\"\n className={cn('[&_tr:last-child]:border-0', className)}\n {...props}\n />\n );\n}\n\nfunction TableFooter({ className, ...props }: React.ComponentProps<'tfoot'>) {\n return (\n <tfoot\n data-slot=\"table-footer\"\n className={cn('border-t bg-surface-muted font-medium [&>tr]:last:border-b-0', className)}\n {...props}\n />\n );\n}\n\n/** Set `data-state=\"selected\"` (or `selected`) to mark a chosen row. */\nfunction TableRow({\n className,\n selected,\n ...props\n}: React.ComponentProps<'tr'> & { selected?: boolean }) {\n return (\n <tr\n data-slot=\"table-row\"\n data-state={selected ? 'selected' : undefined}\n aria-selected={selected || undefined}\n className={cn(\n 'border-b transition-colors hover:bg-muted/60 data-[state=selected]:bg-brand-soft/60 data-[state=selected]:shadow-[inset_2px_0_0_var(--color-brand)]',\n className,\n )}\n {...props}\n />\n );\n}\n\n/** `numeric` right-aligns with tabular figures, for counts, money and durations. */\nfunction TableHead({\n className,\n numeric,\n ...props\n}: React.ComponentProps<'th'> & { numeric?: boolean }) {\n return (\n <th\n data-slot=\"table-head\"\n className={cn(\n 'h-9 px-3 text-left align-middle text-[11px] font-semibold tracking-[0.06em] whitespace-nowrap text-muted-foreground uppercase group-data-[density=compact]/table:h-8 [&:has([role=checkbox])]:w-10 [&:has([role=checkbox])]:pr-0',\n numeric && 'text-right tabular-nums',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TableCell({\n className,\n numeric,\n ...props\n}: React.ComponentProps<'td'> & { numeric?: boolean }) {\n return (\n <td\n data-slot=\"table-cell\"\n className={cn(\n 'h-10 px-3 align-middle whitespace-nowrap group-data-[density=compact]/table:h-8 [&:has([role=checkbox])]:pr-0',\n numeric && 'text-right font-mono text-[12.5px] tabular-nums',\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction TableCaption({ className, ...props }: React.ComponentProps<'caption'>) {\n return (\n <caption\n data-slot=\"table-caption\"\n className={cn('mt-3 text-xs text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nexport { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@ import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, Breadcr
16
16
  import { Card, CardAction, CardContent, CardDescription, CardEyebrow, CardFooter, CardHeader, CardTitle, cardVariants } from "./components/card.js";
17
17
  import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger, menuItemClasses, surfaceClasses } from "./components/popover.js";
18
18
  import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "./components/dropdown-menu.js";
19
+ import { Input, fieldClasses, fieldFocusClasses } from "./components/input.js";
19
20
  import { ChatHistory, groupConversations, matchesConversation } from "./components/chat-history.js";
20
21
  import { IconButton } from "./components/icon-button.js";
21
22
  import { ResizablePanel, ResizablePanelGroup, ResizeHandle, useGroupRef, usePanelRef } from "./components/resizable.js";
@@ -25,7 +26,6 @@ import { Checkbox } from "./components/checkbox.js";
25
26
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./components/collapsible.js";
26
27
  import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from "./components/dialog.js";
27
28
  import { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut } from "./components/command.js";
28
- import { Input, fieldClasses } from "./components/input.js";
29
29
  import { Combobox } from "./components/combobox.js";
30
30
  import { Composer, Suggestions, acceptsFile } from "./components/composer.js";
31
31
  import { Status, StatusDot, statusDotVariants } from "./components/status.js";
@@ -71,4 +71,4 @@ import { Toolbar, ToolbarGroup, ToolbarSeparator, ToolbarSpacer } from "./compon
71
71
  import { Spotlight, Tour, TourAnchor, findTourTarget, tourTarget, waitForTourTarget } from "./components/tour.js";
72
72
  import { TreeView, flattenTree } from "./components/tree-view.js";
73
73
  import { VoiceRecorder } from "./components/voice-recorder.js";
74
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, AppShellBody, AppShellContent, AppShellHeader, AppShellMain, AppShellSidebar, AttachmentItem, AttachmentTray, AudioPlayer, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Card, CardAction, CardContent, CardDescription, CardEyebrow, CardFooter, CardHeader, CardTitle, ChatHistory, ChatLayout, Checkbox, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Composer, ConnectionBanner, ConnectionStatus, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, Conversation, CopyButton, DataTable, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EditorTabs, EmptyState, EmptyStateActions, EmptyStateDescription, EmptyStateIcon, EmptyStateTitle, Field, FieldDescription, FieldError, FieldHeader, FieldHint, FieldLabel, IconButton, Input, Kbd, KbdGroup, Label, Markdown, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, Message, MessageActions, MessageAttachments, MessageEditor, MobileNav, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, OnboardingChecklist, PageHeader, PageHeaderActions, PageHeaderDescription, PageHeaderEyebrow, PageHeaderMain, PageHeaderTitle, Pagination, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, Reasoning, ResizablePanel, ResizablePanelGroup, ResizeHandle, ScrollArea, ScrollBar, SecretInput, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Skeleton, Slider, SourceCitation, SourceList, Spinner, Spotlight, StatCard, Status, StatusDot, Steps, StreamingIndicator, Suggestions, Switch, SyncStatus, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toast, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport, Toaster, ToolApproval, ToolCall, Toolbar, ToolbarGroup, ToolbarSeparator, ToolbarSpacer, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Tour, TourAnchor, TreeView, UploadQueue, VoiceMessage, VoiceRecorder, accentTokens, acceptsFile, alertVariants, badgeVariants, brand, buttonVariants, cardVariants, cn, computePeaks, contrast, dark, duration, easing, elevation, fieldClasses, findTourTarget, flattenTree, fontMono, fontSans, formatBytes, formatDuration, groupConversations, isApplePlatform, light, matchesConversation, menuItemClasses, mix, modKeyLabel, motion, navigationMenuTriggerStyle, paginationRange, parseMarkdown, peaksFromChannelData, radius, safeSourceHref, shadow, shortcutLabel, statusDotVariants, surfaceClasses, toast, toastVariants, tokens, tourTarget, useFullscreen, useGroupRef, usePanelRef, waitForTourTarget };
74
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, AppShellBody, AppShellContent, AppShellHeader, AppShellMain, AppShellSidebar, AttachmentItem, AttachmentTray, AudioPlayer, Avatar, AvatarFallback, AvatarImage, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Card, CardAction, CardContent, CardDescription, CardEyebrow, CardFooter, CardHeader, CardTitle, ChatHistory, ChatLayout, Checkbox, CodeBlock, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Composer, ConnectionBanner, ConnectionStatus, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, Conversation, CopyButton, DataTable, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EditorTabs, EmptyState, EmptyStateActions, EmptyStateDescription, EmptyStateIcon, EmptyStateTitle, Field, FieldDescription, FieldError, FieldHeader, FieldHint, FieldLabel, IconButton, Input, Kbd, KbdGroup, Label, Markdown, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, Message, MessageActions, MessageAttachments, MessageEditor, MobileNav, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, OnboardingChecklist, PageHeader, PageHeaderActions, PageHeaderDescription, PageHeaderEyebrow, PageHeaderMain, PageHeaderTitle, Pagination, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, Reasoning, ResizablePanel, ResizablePanelGroup, ResizeHandle, ScrollArea, ScrollBar, SecretInput, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Skeleton, Slider, SourceCitation, SourceList, Spinner, Spotlight, StatCard, Status, StatusDot, Steps, StreamingIndicator, Suggestions, Switch, SyncStatus, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toast, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport, Toaster, ToolApproval, ToolCall, Toolbar, ToolbarGroup, ToolbarSeparator, ToolbarSpacer, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Tour, TourAnchor, TreeView, UploadQueue, VoiceMessage, VoiceRecorder, accentTokens, acceptsFile, alertVariants, badgeVariants, brand, buttonVariants, cardVariants, cn, computePeaks, contrast, dark, duration, easing, elevation, fieldClasses, fieldFocusClasses, findTourTarget, flattenTree, fontMono, fontSans, formatBytes, formatDuration, groupConversations, isApplePlatform, light, matchesConversation, menuItemClasses, mix, modKeyLabel, motion, navigationMenuTriggerStyle, paginationRange, parseMarkdown, peaksFromChannelData, radius, safeSourceHref, shadow, shortcutLabel, statusDotVariants, surfaceClasses, toast, toastVariants, tokens, tourTarget, useFullscreen, useGroupRef, usePanelRef, waitForTourTarget };
package/dist/mui/index.js CHANGED
@@ -189,11 +189,17 @@ function burtsonThemeOptions(modeOrConfig = "dark") {
189
189
  border: `1px solid ${p.border}`,
190
190
  boxShadow: shadow.md
191
191
  } } },
192
- MuiMenu: { styleOverrides: { paper: {
193
- borderRadius: radius.lg,
194
- border: `1px solid ${p.border}`,
195
- boxShadow: shadow.md
196
- } } },
192
+ MuiMenu: { styleOverrides: {
193
+ paper: {
194
+ borderRadius: radius.lg,
195
+ border: `1px solid ${p["border-strong"]}`,
196
+ boxShadow: shadow.md
197
+ },
198
+ list: {
199
+ paddingTop: 4,
200
+ paddingBottom: 4
201
+ }
202
+ } },
197
203
  MuiPopover: { styleOverrides: { paper: {
198
204
  borderRadius: radius.lg,
199
205
  border: `1px solid ${p.border}`
@@ -222,10 +228,38 @@ function burtsonThemeOptions(modeOrConfig = "dark") {
222
228
  "&:hover .MuiOutlinedInput-notchedOutline": { borderColor: p["border-strong"] },
223
229
  "&.Mui-focused .MuiOutlinedInput-notchedOutline": {
224
230
  borderColor: p.ring,
225
- borderWidth: 1
231
+ borderWidth: 2
226
232
  },
227
- "&.Mui-focused": { boxShadow: focusRing }
233
+ "&.Mui-error .MuiOutlinedInput-notchedOutline": { borderColor: p.destructive }
228
234
  } } },
235
+ MuiMenuItem: { styleOverrides: { root: {
236
+ margin: "0 4px",
237
+ borderRadius: radius.sm,
238
+ "&.Mui-focusVisible, &:hover": { backgroundColor: p.secondary },
239
+ "&.Mui-selected": {
240
+ backgroundColor: "transparent",
241
+ fontWeight: 600
242
+ },
243
+ "&.Mui-selected.Mui-focusVisible, &.Mui-selected:hover": { backgroundColor: p.secondary }
244
+ } } },
245
+ MuiAutocomplete: { styleOverrides: {
246
+ paper: {
247
+ borderRadius: radius.lg,
248
+ border: `1px solid ${p["border-strong"]}`
249
+ },
250
+ listbox: {
251
+ padding: 4,
252
+ "& .MuiAutocomplete-option": {
253
+ borderRadius: radius.sm,
254
+ "&.Mui-focused, &.Mui-focusVisible": { backgroundColor: p.secondary },
255
+ "&[aria-selected=\"true\"]": {
256
+ backgroundColor: "transparent",
257
+ fontWeight: 600
258
+ },
259
+ "&[aria-selected=\"true\"].Mui-focused": { backgroundColor: p.secondary }
260
+ }
261
+ }
262
+ } },
229
263
  MuiTextField: { defaultProps: { size: compact ? "small" : "medium" } },
230
264
  MuiAlert: { styleOverrides: { root: { borderRadius: radius.md } } },
231
265
  MuiTooltip: { styleOverrides: { tooltip: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/mui/index.ts"],"sourcesContent":["/**\n * The Burtson palette for MUI apps, so a screen built with MUI and one built\n * with Burtson UI components look like the same product.\n *\n * import { ThemeProvider } from '@mui/material/styles';\n * import { createBurtsonTheme } from '@burtson-labs/ui/mui';\n * <ThemeProvider theme={createBurtsonTheme('dark')}>…</ThemeProvider>\n * <ThemeProvider theme={createBurtsonTheme({ mode: 'dark', accent: '#2563eb', density: 'compact' })}>\n *\n * MUI is an adapter here: every colour, radius, shadow and timing comes from\n * the Burtson tokens, and the component overrides give MUI controls the same\n * shape and states as the Burtson components (focus ring, radius per role,\n * no uppercase buttons, quiet borders instead of heavy shadows).\n */\nimport { createTheme, type Shadows, type Theme, type ThemeOptions } from '@mui/material/styles';\n\nimport {\n accentTokens,\n contrast,\n dark,\n duration,\n easing,\n fontMono,\n fontSans,\n light,\n type Palette,\n radius,\n shadow,\n} from '../tokens';\n\nexport type BurtsonMode = 'light' | 'dark';\nexport type BurtsonDensity = 'comfortable' | 'compact';\n\nexport interface BurtsonThemeConfig {\n mode?: BurtsonMode;\n /** Any hex colour; primary, brand, soft and ring tones are derived with contrast kept. */\n accent?: string;\n /** `compact` for admin and data-dense screens: smaller controls, dense lists and tables. */\n density?: BurtsonDensity;\n /** Replace individual palette tokens (a product skin's tinted surfaces). */\n palette?: Partial<Palette>;\n}\n\nconst px = (rem: string) => Math.round(parseFloat(rem) * 16);\n\n/** The full token palette for a config: base mode, accent-derived brand tones, then explicit overrides. */\nexport function burtsonPalette(config: BurtsonThemeConfig = {}): Palette {\n const mode = config.mode ?? 'dark';\n const base = mode === 'dark' ? dark : light;\n return {\n ...base,\n ...(config.accent ? accentTokens(config.accent, mode) : {}),\n ...config.palette,\n };\n}\n\nfunction shadows(): Shadows {\n // MUI indexes elevation 0–24; the Burtson scale has three real levels.\n const levels = ['none', shadow.xs, shadow.xs, shadow.sm, shadow.sm, shadow.sm];\n return Array.from({ length: 25 }, (_, i) => levels[i] ?? shadow.md) as Shadows;\n}\n\n/** Theme options only, for apps that deep-merge their own overrides first. */\nexport function burtsonThemeOptions(\n modeOrConfig: BurtsonMode | BurtsonThemeConfig = 'dark',\n): ThemeOptions {\n const config = typeof modeOrConfig === 'string' ? { mode: modeOrConfig } : modeOrConfig;\n const mode = config.mode ?? 'dark';\n const compact = config.density === 'compact';\n const p = burtsonPalette(config);\n const focusRing = `0 0 0 3px color-mix(in srgb, ${p.ring} 24%, transparent)`;\n return {\n palette: {\n mode,\n primary: { main: p.primary, contrastText: p['primary-foreground'] },\n // Secondary fills use the brand text tone, which is light in dark mode;\n // their text is whichever of white or the page background reads.\n secondary: {\n main: p.brand,\n contrastText: contrast(p.brand, '#ffffff') >= 4.5 ? '#ffffff' : p.background,\n },\n info: { main: p.info, contrastText: p['info-foreground'] },\n error: { main: p.destructive, contrastText: p['destructive-foreground'] },\n warning: { main: p.warning, contrastText: p['warning-foreground'] },\n success: { main: p.success, contrastText: p['success-foreground'] },\n background: { default: p.background, paper: p.surface },\n text: { primary: p.foreground, secondary: p['muted-foreground'] },\n divider: p.border,\n action: { hover: p.muted, selected: p['brand-soft'], focus: p['brand-soft'] },\n },\n shape: { borderRadius: px(radius.md) },\n shadows: shadows(),\n typography: {\n fontFamily: fontSans,\n fontSize: compact ? 13 : 14,\n button: { textTransform: 'none', fontWeight: 600, letterSpacing: '-0.01em' },\n h1: { fontWeight: 700, letterSpacing: '-0.03em' },\n h2: { fontWeight: 700, letterSpacing: '-0.025em' },\n h3: { fontWeight: 650, letterSpacing: '-0.02em' },\n h4: { fontWeight: 650, letterSpacing: '-0.015em' },\n h5: { fontWeight: 600 },\n h6: { fontWeight: 600 },\n overline: { fontWeight: 600, letterSpacing: '0.08em' },\n },\n transitions: {\n duration: {\n shortest: duration.fast,\n shorter: duration.fast,\n short: duration.standard,\n standard: duration.standard,\n complex: duration.emphasis,\n enteringScreen: duration.emphasis,\n leavingScreen: duration.exit,\n },\n easing: {\n easeInOut: easing.standard,\n easeOut: easing.emphasized,\n easeIn: easing.exit,\n sharp: easing.standard,\n },\n },\n components: {\n MuiCssBaseline: {\n styleOverrides: {\n 'code, kbd, pre, samp': { fontFamily: fontMono },\n '@media (prefers-reduced-motion: reduce)': {\n '*, ::before, ::after': {\n animationDuration: '1ms !important',\n transitionDuration: '1ms !important',\n },\n },\n },\n },\n MuiButtonBase: { defaultProps: { disableRipple: true } },\n MuiButton: {\n defaultProps: { disableElevation: true, size: compact ? 'small' : 'medium' },\n styleOverrides: {\n root: {\n borderRadius: radius.md,\n '&:focus-visible': {\n boxShadow: focusRing,\n outline: `2px solid ${p.ring}`,\n outlineOffset: 2,\n },\n },\n outlined: { borderColor: p['border-strong'] },\n },\n },\n MuiIconButton: {\n defaultProps: { size: compact ? 'small' : 'medium' },\n styleOverrides: {\n root: {\n borderRadius: radius.md,\n '&:focus-visible': { outline: `2px solid ${p.ring}`, outlineOffset: 2 },\n },\n },\n },\n MuiPaper: {\n styleOverrides: {\n root: { backgroundImage: 'none' },\n outlined: { borderColor: p.border },\n rounded: { borderRadius: radius.lg },\n },\n },\n MuiCard: {\n defaultProps: { variant: 'outlined' },\n styleOverrides: {\n root: { borderRadius: radius.lg, backgroundColor: p.card, borderColor: p.border },\n },\n },\n MuiDialog: {\n styleOverrides: {\n paper: { borderRadius: radius.xl, border: `1px solid ${p.border}`, boxShadow: shadow.md },\n },\n },\n MuiMenu: {\n styleOverrides: {\n paper: { borderRadius: radius.lg, border: `1px solid ${p.border}`, boxShadow: shadow.md },\n },\n },\n MuiPopover: {\n styleOverrides: { paper: { borderRadius: radius.lg, border: `1px solid ${p.border}` } },\n },\n MuiChip: {\n defaultProps: { size: 'small' },\n styleOverrides: { root: { borderRadius: radius.full, fontWeight: 500 } },\n },\n MuiTabs: {\n styleOverrides: { indicator: { backgroundColor: p.brand, height: 2 } },\n },\n MuiTab: {\n styleOverrides: {\n root: {\n textTransform: 'none',\n fontWeight: 500,\n minHeight: compact ? 36 : 44,\n '&.Mui-selected': { color: p.foreground },\n },\n },\n },\n MuiOutlinedInput: {\n styleOverrides: {\n root: {\n borderRadius: radius.md,\n backgroundColor: p.surface,\n '& .MuiOutlinedInput-notchedOutline': { borderColor: p.input },\n '&:hover .MuiOutlinedInput-notchedOutline': { borderColor: p['border-strong'] },\n '&.Mui-focused .MuiOutlinedInput-notchedOutline': {\n borderColor: p.ring,\n borderWidth: 1,\n },\n '&.Mui-focused': { boxShadow: focusRing },\n },\n },\n },\n MuiTextField: { defaultProps: { size: compact ? 'small' : 'medium' } },\n MuiAlert: { styleOverrides: { root: { borderRadius: radius.md } } },\n MuiTooltip: {\n styleOverrides: {\n tooltip: {\n backgroundColor: p.code,\n color: p['code-foreground'],\n fontSize: 12,\n borderRadius: radius.sm,\n },\n },\n },\n MuiSwitch: {\n styleOverrides: {\n switchBase: {\n '&.Mui-checked + .MuiSwitch-track': { backgroundColor: p.brand, opacity: 1 },\n },\n track: { backgroundColor: p['border-strong'], opacity: 1 },\n },\n },\n MuiList: { defaultProps: { dense: compact } },\n MuiTable: { defaultProps: { size: compact ? 'small' : 'medium' } },\n MuiToolbar: { defaultProps: { variant: compact ? 'dense' : 'regular' } },\n MuiDivider: { styleOverrides: { root: { borderColor: p.border } } },\n },\n };\n}\n\n/**\n * `createBurtsonTheme('dark')` or `createBurtsonTheme({ mode, accent, density })`,\n * then any MUI overrides, merged in order.\n */\nexport function createBurtsonTheme(\n modeOrConfig: BurtsonMode | BurtsonThemeConfig = 'dark',\n ...overrides: ThemeOptions[]\n): Theme {\n return createTheme(burtsonThemeOptions(modeOrConfig), ...overrides);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/mui/index.ts"],"sourcesContent":["/**\n * The Burtson palette for MUI apps, so a screen built with MUI and one built\n * with Burtson UI components look like the same product.\n *\n * import { ThemeProvider } from '@mui/material/styles';\n * import { createBurtsonTheme } from '@burtson-labs/ui/mui';\n * <ThemeProvider theme={createBurtsonTheme('dark')}>…</ThemeProvider>\n * <ThemeProvider theme={createBurtsonTheme({ mode: 'dark', accent: '#2563eb', density: 'compact' })}>\n *\n * MUI is an adapter here: every colour, radius, shadow and timing comes from\n * the Burtson tokens, and the component overrides give MUI controls the same\n * shape and states as the Burtson components (focus ring, radius per role,\n * no uppercase buttons, quiet borders instead of heavy shadows).\n */\nimport { createTheme, type Shadows, type Theme, type ThemeOptions } from '@mui/material/styles';\n\nimport {\n accentTokens,\n contrast,\n dark,\n duration,\n easing,\n fontMono,\n fontSans,\n light,\n type Palette,\n radius,\n shadow,\n} from '../tokens';\n\nexport type BurtsonMode = 'light' | 'dark';\nexport type BurtsonDensity = 'comfortable' | 'compact';\n\nexport interface BurtsonThemeConfig {\n mode?: BurtsonMode;\n /** Any hex colour; primary, brand, soft and ring tones are derived with contrast kept. */\n accent?: string;\n /** `compact` for admin and data-dense screens: smaller controls, dense lists and tables. */\n density?: BurtsonDensity;\n /** Replace individual palette tokens (a product skin's tinted surfaces). */\n palette?: Partial<Palette>;\n}\n\nconst px = (rem: string) => Math.round(parseFloat(rem) * 16);\n\n/** The full token palette for a config: base mode, accent-derived brand tones, then explicit overrides. */\nexport function burtsonPalette(config: BurtsonThemeConfig = {}): Palette {\n const mode = config.mode ?? 'dark';\n const base = mode === 'dark' ? dark : light;\n return {\n ...base,\n ...(config.accent ? accentTokens(config.accent, mode) : {}),\n ...config.palette,\n };\n}\n\nfunction shadows(): Shadows {\n // MUI indexes elevation 0–24; the Burtson scale has three real levels.\n const levels = ['none', shadow.xs, shadow.xs, shadow.sm, shadow.sm, shadow.sm];\n return Array.from({ length: 25 }, (_, i) => levels[i] ?? shadow.md) as Shadows;\n}\n\n/** Theme options only, for apps that deep-merge their own overrides first. */\nexport function burtsonThemeOptions(\n modeOrConfig: BurtsonMode | BurtsonThemeConfig = 'dark',\n): ThemeOptions {\n const config = typeof modeOrConfig === 'string' ? { mode: modeOrConfig } : modeOrConfig;\n const mode = config.mode ?? 'dark';\n const compact = config.density === 'compact';\n const p = burtsonPalette(config);\n const focusRing = `0 0 0 3px color-mix(in srgb, ${p.ring} 24%, transparent)`;\n return {\n palette: {\n mode,\n primary: { main: p.primary, contrastText: p['primary-foreground'] },\n // Secondary fills use the brand text tone, which is light in dark mode;\n // their text is whichever of white or the page background reads.\n secondary: {\n main: p.brand,\n contrastText: contrast(p.brand, '#ffffff') >= 4.5 ? '#ffffff' : p.background,\n },\n info: { main: p.info, contrastText: p['info-foreground'] },\n error: { main: p.destructive, contrastText: p['destructive-foreground'] },\n warning: { main: p.warning, contrastText: p['warning-foreground'] },\n success: { main: p.success, contrastText: p['success-foreground'] },\n background: { default: p.background, paper: p.surface },\n text: { primary: p.foreground, secondary: p['muted-foreground'] },\n divider: p.border,\n action: { hover: p.muted, selected: p['brand-soft'], focus: p['brand-soft'] },\n },\n shape: { borderRadius: px(radius.md) },\n shadows: shadows(),\n typography: {\n fontFamily: fontSans,\n fontSize: compact ? 13 : 14,\n button: { textTransform: 'none', fontWeight: 600, letterSpacing: '-0.01em' },\n h1: { fontWeight: 700, letterSpacing: '-0.03em' },\n h2: { fontWeight: 700, letterSpacing: '-0.025em' },\n h3: { fontWeight: 650, letterSpacing: '-0.02em' },\n h4: { fontWeight: 650, letterSpacing: '-0.015em' },\n h5: { fontWeight: 600 },\n h6: { fontWeight: 600 },\n overline: { fontWeight: 600, letterSpacing: '0.08em' },\n },\n transitions: {\n duration: {\n shortest: duration.fast,\n shorter: duration.fast,\n short: duration.standard,\n standard: duration.standard,\n complex: duration.emphasis,\n enteringScreen: duration.emphasis,\n leavingScreen: duration.exit,\n },\n easing: {\n easeInOut: easing.standard,\n easeOut: easing.emphasized,\n easeIn: easing.exit,\n sharp: easing.standard,\n },\n },\n components: {\n MuiCssBaseline: {\n styleOverrides: {\n 'code, kbd, pre, samp': { fontFamily: fontMono },\n '@media (prefers-reduced-motion: reduce)': {\n '*, ::before, ::after': {\n animationDuration: '1ms !important',\n transitionDuration: '1ms !important',\n },\n },\n },\n },\n MuiButtonBase: { defaultProps: { disableRipple: true } },\n MuiButton: {\n defaultProps: { disableElevation: true, size: compact ? 'small' : 'medium' },\n styleOverrides: {\n root: {\n borderRadius: radius.md,\n '&:focus-visible': {\n boxShadow: focusRing,\n outline: `2px solid ${p.ring}`,\n outlineOffset: 2,\n },\n },\n outlined: { borderColor: p['border-strong'] },\n },\n },\n MuiIconButton: {\n defaultProps: { size: compact ? 'small' : 'medium' },\n styleOverrides: {\n root: {\n borderRadius: radius.md,\n '&:focus-visible': { outline: `2px solid ${p.ring}`, outlineOffset: 2 },\n },\n },\n },\n MuiPaper: {\n styleOverrides: {\n root: { backgroundImage: 'none' },\n outlined: { borderColor: p.border },\n rounded: { borderRadius: radius.lg },\n },\n },\n MuiCard: {\n defaultProps: { variant: 'outlined' },\n styleOverrides: {\n root: { borderRadius: radius.lg, backgroundColor: p.card, borderColor: p.border },\n },\n },\n MuiDialog: {\n styleOverrides: {\n paper: { borderRadius: radius.xl, border: `1px solid ${p.border}`, boxShadow: shadow.md },\n },\n },\n MuiMenu: {\n styleOverrides: {\n paper: {\n borderRadius: radius.lg,\n border: `1px solid ${p['border-strong']}`,\n boxShadow: shadow.md,\n },\n list: { paddingTop: 4, paddingBottom: 4 },\n },\n },\n MuiPopover: {\n styleOverrides: { paper: { borderRadius: radius.lg, border: `1px solid ${p.border}` } },\n },\n MuiChip: {\n defaultProps: { size: 'small' },\n styleOverrides: { root: { borderRadius: radius.full, fontWeight: 500 } },\n },\n MuiTabs: {\n styleOverrides: { indicator: { backgroundColor: p.brand, height: 2 } },\n },\n MuiTab: {\n styleOverrides: {\n root: {\n textTransform: 'none',\n fontWeight: 500,\n minHeight: compact ? 36 : 44,\n '&.Mui-selected': { color: p.foreground },\n },\n },\n },\n MuiOutlinedInput: {\n styleOverrides: {\n root: {\n borderRadius: radius.md,\n backgroundColor: p.surface,\n '& .MuiOutlinedInput-notchedOutline': { borderColor: p.input },\n '&:hover .MuiOutlinedInput-notchedOutline': { borderColor: p['border-strong'] },\n // Same focus as the Tailwind fields: a 2px ring-coloured edge inside\n // the radius, no outer halo that a scroll container could clip.\n '&.Mui-focused .MuiOutlinedInput-notchedOutline': {\n borderColor: p.ring,\n borderWidth: 2,\n },\n '&.Mui-error .MuiOutlinedInput-notchedOutline': { borderColor: p.destructive },\n },\n },\n },\n // Menu, Select and Autocomplete rows: inset 4px in a 12px surface, 8px\n // radius, a quiet secondary fill for the active row (as MenuItem and\n // SelectItem in the Tailwind kit).\n MuiMenuItem: {\n styleOverrides: {\n root: {\n margin: '0 4px',\n borderRadius: radius.sm,\n '&.Mui-focusVisible, &:hover': { backgroundColor: p.secondary },\n '&.Mui-selected': { backgroundColor: 'transparent', fontWeight: 600 },\n '&.Mui-selected.Mui-focusVisible, &.Mui-selected:hover': {\n backgroundColor: p.secondary,\n },\n },\n },\n },\n MuiAutocomplete: {\n styleOverrides: {\n paper: { borderRadius: radius.lg, border: `1px solid ${p['border-strong']}` },\n listbox: {\n padding: 4,\n '& .MuiAutocomplete-option': {\n borderRadius: radius.sm,\n '&.Mui-focused, &.Mui-focusVisible': { backgroundColor: p.secondary },\n '&[aria-selected=\"true\"]': { backgroundColor: 'transparent', fontWeight: 600 },\n '&[aria-selected=\"true\"].Mui-focused': { backgroundColor: p.secondary },\n },\n },\n },\n },\n MuiTextField: { defaultProps: { size: compact ? 'small' : 'medium' } },\n MuiAlert: { styleOverrides: { root: { borderRadius: radius.md } } },\n MuiTooltip: {\n styleOverrides: {\n tooltip: {\n backgroundColor: p.code,\n color: p['code-foreground'],\n fontSize: 12,\n borderRadius: radius.sm,\n },\n },\n },\n MuiSwitch: {\n styleOverrides: {\n switchBase: {\n '&.Mui-checked + .MuiSwitch-track': { backgroundColor: p.brand, opacity: 1 },\n },\n track: { backgroundColor: p['border-strong'], opacity: 1 },\n },\n },\n MuiList: { defaultProps: { dense: compact } },\n MuiTable: { defaultProps: { size: compact ? 'small' : 'medium' } },\n MuiToolbar: { defaultProps: { variant: compact ? 'dense' : 'regular' } },\n MuiDivider: { styleOverrides: { root: { borderColor: p.border } } },\n },\n };\n}\n\n/**\n * `createBurtsonTheme('dark')` or `createBurtsonTheme({ mode, accent, density })`,\n * then any MUI overrides, merged in order.\n */\nexport function createBurtsonTheme(\n modeOrConfig: BurtsonMode | BurtsonThemeConfig = 'dark',\n ...overrides: ThemeOptions[]\n): Theme {\n return createTheme(burtsonThemeOptions(modeOrConfig), ...overrides);\n}\n"],"mappings":"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"}