@exsto/ds 0.0.1-rc.10 → 0.0.1-rc.13

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.
@@ -146,6 +146,12 @@ var popupItemClass = (flavor = "base-ui", checkable = false) => cn(ITEM_BASE, IT
146
146
  var POPUP_ITEM_INDICATOR_CLASS = "pointer-events-none absolute right-2 flex size-4 items-center justify-center text-foreground";
147
147
  /** A group's heading in any of these lists. */
148
148
  var POPUP_GROUP_LABEL_CLASS = "px-2 py-1.5 text-xs font-medium text-muted-foreground";
149
+ /**
150
+ * How wide a combobox's list is: never narrower than the control it opens from, and as wide as its longest option up to
151
+ * 28rem or what the window leaves from the control's start (the list is aligned to that start), whichever is less. A
152
+ * control wider than that cap keeps its own width. Longer options are cut by their item, they do not widen the list.
153
+ */
154
+ var POPUP_LIST_WIDTH_CLASS = "min-w-(--anchor-width) max-w-[max(var(--anchor-width),min(28rem,var(--available-width)))]";
149
155
  //#endregion
150
156
  //#region ../ui/src/components/edyn/rich-text-content/allow-list.ts
151
157
  /**
@@ -479,6 +485,6 @@ var Toggle$1 = ({ className, variant = "default", size = "default", ...props })
479
485
  });
480
486
  };
481
487
  //#endregion
482
- export { useMergedRefs as A, RICH_TEXT_ELEMENTS as C, popupItemClass as D, POPUP_ITEM_INDICATOR_CLASS as E, ScrollArea$1 as O, RICH_TEXT_ATTRIBUTES as S, isAllowedRichTextHref as T, DropdownMenuTrigger as _, DropdownMenuContent as a, RichTextContent as b, DropdownMenuLabel as c, DropdownMenuRadioItem as d, DropdownMenuSeparator as f, DropdownMenuSubTrigger as g, DropdownMenuSubContent as h, DropdownMenuCheckboxItem as i, ScrollBar as k, DropdownMenuPortal as l, DropdownMenuSub as m, toggleVariants as n, DropdownMenuGroup as o, DropdownMenuShortcut as p, DropdownMenu as r, DropdownMenuItem as s, Toggle$1 as t, DropdownMenuRadioGroup as u, RICH_TEXT_BODY_CLASS as v, RICH_TEXT_LINK_PROTOCOLS as w, richTextToNodes as x, RICH_TEXT_MENTION_CLASS as y };
488
+ export { ScrollBar as A, RICH_TEXT_ELEMENTS as C, POPUP_LIST_WIDTH_CLASS as D, POPUP_ITEM_INDICATOR_CLASS as E, popupItemClass as O, RICH_TEXT_ATTRIBUTES as S, isAllowedRichTextHref as T, DropdownMenuTrigger as _, DropdownMenuContent as a, RichTextContent as b, DropdownMenuLabel as c, DropdownMenuRadioItem as d, DropdownMenuSeparator as f, DropdownMenuSubTrigger as g, DropdownMenuSubContent as h, DropdownMenuCheckboxItem as i, useMergedRefs as j, ScrollArea$1 as k, DropdownMenuPortal as l, DropdownMenuSub as m, toggleVariants as n, DropdownMenuGroup as o, DropdownMenuShortcut as p, DropdownMenu as r, DropdownMenuItem as s, Toggle$1 as t, DropdownMenuRadioGroup as u, RICH_TEXT_BODY_CLASS as v, RICH_TEXT_LINK_PROTOCOLS as w, richTextToNodes as x, RICH_TEXT_MENTION_CLASS as y };
483
489
 
484
- //# sourceMappingURL=toggle-CVnIkJVC.js.map
490
+ //# sourceMappingURL=toggle-Bxg8P-61.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toggle-Bxg8P-61.js","names":[],"sources":["../../../ui/src/hooks/use-merged-refs.ts","../../../ui/src/components/ui/scroll-area/scroll-area.tsx","../../../ui/src/lib/popup-list.ts","../../../ui/src/components/edyn/rich-text-content/allow-list.ts","../../../ui/src/components/edyn/rich-text-content/rich-text-content.tsx","../../../ui/src/components/ui/dropdown-menu/dropdown-menu.tsx","../../../ui/src/components/ui/toggle/toggle.tsx"],"sourcesContent":["import { type Ref, type RefCallback, useCallback } from 'react';\n\ntype TPossibleRef<T> = Ref<T> | undefined;\n\nconst assignRef = <T>(ref: TPossibleRef<T>, value: T) => {\n if (typeof ref === 'function') {\n ref(value);\n } else if (ref !== null) {\n // Using type assertion to RefObject since we know it's not null\n (ref as { current: T }).current = value;\n }\n};\n\nconst mergeRefs = <T>(...refs: TPossibleRef<T>[]) => {\n return (node: T) => {\n for (const ref of refs) {\n if (ref) {\n assignRef(ref, node);\n }\n }\n };\n};\n\nexport const useMergedRefs = <T>(...refs: TPossibleRef<T>[]) => {\n return useCallback(mergeRefs(...refs), [...refs]) as RefCallback<T>;\n};\n","import { ScrollArea as BaseScrollArea } from '@base-ui/react/scroll-area';\nimport { useMergedRefs } from '@edyn/ui/hooks/use-merged-refs';\nimport { cn } from '@edyn/ui/lib/utils';\nimport { type ComponentProps, type RefObject, useEffect, useRef } from 'react';\n\n/**\n * When the bar shows: 'hover' on area hover or while scrolling (default),\n * 'scroll' only while scrolling, 'always' permanent. In every mode the bar is\n * mounted only while that axis actually overflows, so 'always' means \"always\n * when there is something to scroll\", never a bar on a list that fits.\n */\nexport type TScrollbarVisibility = 'hover' | 'scroll' | 'always';\n\n/**\n * Surface the edge fades blended into, back when they were painted.\n *\n * @deprecated The fades are cut into the content by a mask, so they match any\n * surface without being told which one. Still accepted, and ignored.\n */\nexport type TScrollAreaFadeFrom = 'card' | 'background' | 'sidebar' | 'popover';\n\nexport interface IScrollBarProps extends ComponentProps<typeof BaseScrollArea.Scrollbar> {\n visibility?: TScrollbarVisibility;\n}\n\nexport const ScrollBar = ({ className, orientation = 'vertical', visibility = 'hover', ...props }: IScrollBarProps) => {\n return (\n <BaseScrollArea.Scrollbar\n data-slot=\"scroll-area-scrollbar\"\n orientation={orientation}\n className={cn(\n 'peer/scrollbar z-100 flex touch-none select-none motion-safe:transition-opacity motion-safe:duration-150',\n // Size, gap and start read --scroll-bar-size, --scroll-bar-gap and --scroll-bar-start (see scroll-bar.css), whose\n // defaults are the 8px bar flush with the box that it has always been.\n orientation === 'vertical' &&\n 'h-(--scroll-bar-length) w-(--scroll-bar-size) me-(--scroll-bar-gap) mt-(--scroll-bar-offset-top) border-l border-l-transparent p-px',\n orientation === 'horizontal' &&\n 'h-(--scroll-bar-size) ms-(--scroll-bar-gap) me-(--scroll-bar-gap) mb-(--scroll-bar-gap) flex-col border-t border-t-transparent p-px',\n visibility !== 'always' && 'opacity-0 data-scrolling:opacity-100',\n visibility === 'hover' && 'data-hovering:opacity-100 group-hover/scroll-area:opacity-100',\n className,\n )}\n {...props}\n >\n <BaseScrollArea.Thumb className=\"relative flex-1 rounded-full bg-muted-foreground/50 transition-colors hover:bg-muted-foreground/70 data-scrolling:bg-muted-foreground/70\" />\n </BaseScrollArea.Scrollbar>\n );\n};\n\nexport interface IScrollAreaProps extends ComponentProps<typeof BaseScrollArea.Root> {\n /** Which axes get a styled scrollbar; content decides what actually overflows. */\n orientation?: 'horizontal' | 'vertical' | 'both';\n /** Scrollbar reveal behavior (mirrors the Radix ScrollArea `type` prop). */\n type?: TScrollbarVisibility;\n /** Edge fades hinting at clipped content; each one shows only while its own edge hides something. */\n fade?: boolean;\n /**\n * @deprecated No longer read. The fades mask the content, so they sit correctly\n * on any surface; passing this does nothing and is safe to delete.\n */\n fadeFrom?: TScrollAreaFadeFrom;\n /** Places both bars, for a host that gives them a gutter of their own (a sidebar menu). */\n scrollbarClassName?: string;\n viewportId?: string;\n /** Access to the scrollable viewport (e.g. to reset scroll position on route changes). */\n viewportRef?: RefObject<HTMLDivElement | null>;\n viewportClassName?: string;\n /** Published on the viewport as data-scroll-restoration-id, for a router that restores scroll position. */\n scrollRestorationId?: string;\n /**\n * Whether the viewport is a tab stop of its own (default). Turn it off inside a\n * widget that already owns focus, a menu above all: its items are the tab\n * stops, and a focusable wrapper between the role and its items is both\n * redundant and an aria-required-children violation.\n */\n focusable?: boolean;\n /** @deprecated Use `viewportId`. */\n viewPortId?: string;\n /** @deprecated Use `viewportRef`. */\n viewPortRef?: RefObject<HTMLDivElement | null>;\n /** @deprecated Use `viewportClassName`. */\n viewPortClassName?: string;\n /** Places the vertical bar only; `scrollbarClassName` covers both. */\n scrollVerticalClassName?: string;\n /** Places the horizontal bar only; `scrollbarClassName` covers both. */\n scrollHorizontalClassName?: string;\n}\n\n/**\n * Which axes fade, published for scroll-fade.css to key its mask off. The\n * stylesheet reaches this element's own viewport through a child combinator, so a\n * ScrollArea nested in another one cannot pick up its ancestor's edges.\n */\n/**\n * Base UI gives the root, the viewport and the content `role=\"presentation\"`. On\n * a div that changes nothing for a screen reader, but it is an EXPLICIT role, and\n * axe treats explicit presentation children as foreign to a parent that owns\n * required children. A ScrollArea inside `role=\"menu\"` or `role=\"listbox\"` then\n * fails as a critical aria-required-children violation, while the same div with\n * no role passes straight through. Clearing it is what makes a ScrollArea legal\n * in a popup list. A spread because the literal `role={undefined}` is flagged by\n * the a11y lint rule, which cannot tell it from an invalid role.\n */\nconst NO_ROLE = { role: undefined } as const;\n\n/** Base UI makes the viewport a tab stop (0, or -1 with nothing to scroll); undefined takes that away. */\nconst NO_TAB_STOP = { tabIndex: undefined } as const;\n\nconst FADE_AXIS = {\n vertical: 'block',\n horizontal: 'inline',\n both: 'both',\n} as const;\n\n/**\n * Themed scroll container (Base UI): overflowing content scrolls INSIDE the component\n * with a slim overlay scrollbar instead of exposing a native browser scrollbar. House\n * rule: wide/tall content (tables, lists, code) always goes through this, never a bare\n * overflow-* utility.\n *\n * Cap the height with a plain class on the component itself, e.g.\n * `<ScrollArea className=\"max-h-88\">`. The viewport picks the cap up through\n * `max-h-inherit`, which matters because the viewport is the element that actually\n * scrolls: a cap that lands only on the root leaves tall content spilling out\n * underneath with no scrollbar, and that reads as a working height right up until the\n * content outgrows it.\n *\n * `fade` fades out each edge that is currently hiding content, rather than always\n * fading one: a permanent fade is a lie half the time, dimming the last row that fits\n * and promising more below when the reader is already at the end. It is cut into the\n * content by a mask (@edyn/theme/scroll-fade.css), so it needs no surface colour and\n * reads correctly over a tint, a gradient or a glow. A host that keeps something\n * unscrolled at the top, such as a sticky table header, exempts that band by setting\n * --scroll-fade-offset on the ScrollArea. The static faded-* utilities in\n * @edyn/theme/utilities.css are the other tool, for DECORATIVE edges that do not\n * track scroll position.\n *\n * The viewport publishes its size as --scroll-area-width/--scroll-area-height CSS vars\n * so children can size against the visible area.\n */\nexport const ScrollArea = ({\n className,\n children,\n orientation = 'vertical',\n type = 'hover',\n fade = false,\n fadeFrom = 'card',\n scrollbarClassName,\n viewportId,\n viewportRef,\n viewportClassName,\n scrollRestorationId,\n focusable = true,\n viewPortId,\n viewPortRef,\n viewPortClassName,\n scrollVerticalClassName,\n scrollHorizontalClassName,\n ...props\n}: IScrollAreaProps) => {\n const refInner = useRef<HTMLDivElement | null>(null);\n // The viewPort* spellings are the pre-rc.4 names, kept so existing callers\n // keep working; the viewport* ones match the rest of the ecosystem.\n const refsViewport = useMergedRefs(refInner, viewportRef ?? viewPortRef);\n\n useEffect(() => {\n const el = refInner.current;\n if (!el) {\n return;\n }\n const observer = new ResizeObserver(() => {\n el.style.setProperty('--scroll-area-width', `${el.clientWidth}px`);\n el.style.setProperty('--scroll-area-height', `${el.clientHeight}px`);\n });\n observer.observe(el);\n return () => {\n observer.disconnect();\n };\n }, []);\n\n return (\n <BaseScrollArea.Root\n data-slot=\"scroll-area\"\n // Everything inside clips at this box, so a focus ring drawn outside an\n // element at the edge would be cut off; see @edyn/theme/focus.css.\n data-focus=\"inset\"\n // The single-row grid is load-bearing rather than tidying. `h-full` on the viewport\n // cannot be trusted to size it: a percentage height only resolves against a definite\n // containing block, and a host that sizes this by flex inside a max-height column\n // (`min-h-0 flex-1`) is not definite, so the viewport fell back to auto and grew to\n // its content instead of scrolling. A grid item stretches to its track, and the track\n // is sized from the root's used height, which flex has already settled. `grid-rows-1`\n // is `repeat(1, minmax(0, 1fr))`: one track that may shrink below its content.\n className={cn('group/scroll-area relative grid min-w-0 grid-rows-1 overflow-hidden', className)}\n data-fade={fade ? FADE_AXIS[orientation] : undefined}\n {...NO_ROLE}\n {...props}\n >\n {(orientation === 'vertical' || orientation === 'both') && (\n <ScrollBar orientation=\"vertical\" visibility={type} className={cn(scrollbarClassName, scrollVerticalClassName)} />\n )}\n {(orientation === 'horizontal' || orientation === 'both') && (\n <ScrollBar orientation=\"horizontal\" visibility={type} className={cn(scrollbarClassName, scrollHorizontalClassName)} />\n )}\n <BaseScrollArea.Corner />\n <BaseScrollArea.Viewport\n data-slot=\"scroll-area-viewport\"\n id={viewportId ?? viewPortId}\n ref={refsViewport}\n data-scroll-restoration-id={scrollRestorationId}\n {...NO_ROLE}\n {...(focusable ? null : NO_TAB_STOP)}\n // One axis means one axis. Base UI leaves both axes scrollable, so a\n // vertical list could still be dragged sideways, and anything that put a\n // row in view (focus moving, scrollIntoView with inline: nearest) slid\n // the whole list across. The clamp is marked important because Base UI\n // sets the viewport's overflow itself.\n className={cn(\n 'max-h-inherit w-full rounded-[inherit]',\n orientation === 'vertical' && 'overflow-x-hidden!',\n orientation === 'horizontal' && 'overflow-y-hidden!',\n viewportClassName ?? viewPortClassName,\n )}\n >\n {/* Content is NOT optional: it carries the ResizeObserver that recomputes the\n thumb when the CONTENT resizes without the viewport resizing (e.g. a route\n swap to a shorter page). Without it the thumb keeps the previous page's\n geometry and a fully-visible page still shows a scrollbar.\n\n A vertical scroller also pins its content to the viewport's width, so a\n long label truncates instead of widening the list and inventing a\n horizontal scroll. Base UI sets min-width: fit-content inline, which is\n what makes that happen and why this is an inline style too. */}\n <BaseScrollArea.Content {...NO_ROLE} style={orientation === 'vertical' ? { minWidth: 0 } : undefined}>\n {children}\n </BaseScrollArea.Content>\n </BaseScrollArea.Viewport>\n </BaseScrollArea.Root>\n );\n};\n","import { cn } from '@edyn/ui/lib/utils';\n\n/**\n * The one look for a list in a popup or a menu: the command palette, Select,\n * Combobox, MultiSelect and the dropdown menus.\n *\n * These lists used to disagree with each other in every detail that shows:\n * three different radii, two different paddings, a grey fill for the highlight\n * in one and the accent in another, and the chosen item marked by a check on\n * the left in Select and on the right in the menus. Picking something from one\n * list then felt like a different product from picking something in the next.\n *\n * It lives here as classes rather than as a stylesheet so a caller's own\n * className still wins: an unlayered rule would beat every utility, including\n * the one someone passes for a single list.\n *\n * ONE ITEM: transparent at rest, 32px tall, 6px radius (--radius-sm), 6px by\n * 8px of padding, text-sm, its own icons 16px and muted. Under the pointer or\n * the keyboard it takes one translucent fill of the text colour, and its icons\n * the text colour. Chosen is medium weight with a check at the END, never a\n * fill, so \"where I am\" and \"what I picked\" can be told apart at a glance.\n */\n\n/**\n * Which primitive renders the item, because the two disagree about the same\n * attribute names in a way that silently breaks the styling:\n *\n * - cmdk writes `data-selected=\"false\"` and `data-disabled=\"false\"` on items\n * that are neither, so a bare `data-selected:` variant matches EVERY item and\n * highlights the whole list. Its states have to be matched by value.\n * - Base UI omits the attribute instead, so presence is the test there. That\n * needs the BRACKET form for `selected`: shadcn redefines the bare\n * `data-selected:` variant to match only data-selected=\"true\" (for the\n * calendar), and Base UI writes it as an empty string, so the bare form\n * compiles and silently never applies. `highlighted` and `disabled` have no\n * such override, so those stay bare.\n * - And the same name means different things: cmdk's `data-selected` is the\n * keyboard cursor, Base UI's is the chosen value. In cmdk the chosen state is\n * `data-checked`, which the DS's own CommandItem sets.\n */\nexport type TPopupItemFlavor = 'base-ui' | 'cmdk';\n\nconst ITEM_BASE =\n \"relative flex min-h-8 cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-foreground outline-none select-none [&>svg]:pointer-events-none [&>svg]:shrink-0 [&>svg]:text-muted-foreground [&>svg:not([class*='size-'])]:size-4\";\n\nconst ITEM_STATES: Record<TPopupItemFlavor, string> = {\n 'base-ui':\n 'data-highlighted:bg-foreground/6 data-highlighted:[&>svg]:text-foreground data-[selected]:font-medium data-disabled:pointer-events-none data-disabled:opacity-50',\n cmdk: 'data-[selected=true]:bg-foreground/6 data-[selected=true]:[&>svg]:text-foreground data-[checked=true]:font-medium data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50',\n};\n\n/** The shared item look. `checkable` leaves room at the end for the check. */\nexport const popupItemClass = (flavor: TPopupItemFlavor = 'base-ui', checkable = false): string =>\n cn(ITEM_BASE, ITEM_STATES[flavor], checkable && 'pr-8');\n\n/**\n * The check's slot, at the end of the item and the same size whether or not the\n * check is in it, so a list does not shift as the choice moves.\n */\nexport const POPUP_ITEM_INDICATOR_CLASS = 'pointer-events-none absolute right-2 flex size-4 items-center justify-center text-foreground';\n\n/** A group's heading in any of these lists. */\nexport const POPUP_GROUP_LABEL_CLASS = 'px-2 py-1.5 text-xs font-medium text-muted-foreground';\n\n/**\n * How wide a combobox's list is: never narrower than the control it opens from, and as wide as its longest option up to\n * 28rem or what the window leaves from the control's start (the list is aligned to that start), whichever is less. A\n * control wider than that cap keeps its own width. Longer options are cut by their item, they do not widen the list.\n */\nexport const POPUP_LIST_WIDTH_CLASS = 'min-w-(--anchor-width) max-w-[max(var(--anchor-width),min(28rem,var(--available-width)))]';\n","/**\n * The HTML the rich-text editor emits, and the only HTML RichTextContent renders. An app that\n * sanitises on a server takes its allow-list from here: nothing outside these elements and this\n * attribute ever comes out of the editor, whatever was pasted into it.\n */\nexport const RICH_TEXT_ELEMENTS = ['p', 'br', 'hr', 'strong', 'em', 'u', 'ul', 'ol', 'li', 'a'] as const;\n\n/** The attributes each element may carry. Every other element carries none (no class, no style). */\nexport const RICH_TEXT_ATTRIBUTES: Readonly<Record<string, readonly string[]>> = { a: ['href'] };\n\n/** A link must be absolute and use one of these. `javascript:`, `data:` and relative links are refused. */\nexport const RICH_TEXT_LINK_PROTOCOLS = ['http', 'https', 'mailto'] as const;\n\nexport const isAllowedRichTextHref = (href: string): boolean => {\n const cleaned = Array.from(href)\n .filter((char) => char.charCodeAt(0) > 32)\n .join('');\n const colon = cleaned.indexOf(':');\n if (colon < 1) {\n return false;\n }\n const protocol = cleaned.slice(0, colon).toLowerCase();\n return (RICH_TEXT_LINK_PROTOCOLS as readonly string[]).includes(protocol);\n};\n","import { cn } from '@edyn/ui/lib/utils';\nimport { createElement, type HTMLAttributes, type ReactNode, useMemo } from 'react';\nimport { isAllowedRichTextHref } from './allow-list';\n\n/**\n * How rich text looks, shared by the editor and by RichTextContent so a comment reads the same while it is typed and\n * after it is saved. Descendant selectors rather than classes on the elements, because the HTML that is stored carries\n * no classes.\n */\nexport const RICH_TEXT_BODY_CLASS =\n 'text-sm leading-6 wrap-break-word [&_a]:text-primary [&_a]:underline [&_a]:underline-offset-2 [&_hr]:my-3 [&_hr]:border-0 [&_hr]:border-t [&_hr]:border-border [&_ol]:list-decimal [&_ol]:ps-5 [&_p+p]:mt-2 [&_ul]:list-disc [&_ul]:ps-5 [&_ul+p]:mt-2 [&_ol+p]:mt-2 [&_p+ul]:mt-2 [&_p+ol]:mt-2';\n\nconst MENTION_PATTERN = /(?<![\\w.+-])@(?:assignees\\b|[A-Za-z0-9._%+-]+@[A-Za-z0-9-]+(?:\\.[A-Za-z0-9-]+)+)/g;\n\nexport const RICH_TEXT_MENTION_CLASS = 'rounded-sm bg-primary/10 px-1 py-0.5 font-medium text-primary';\n\nconst TAG_FOR: Readonly<Record<string, string>> = { b: 'strong', i: 'em' };\nconst KEPT = new Set(['p', 'strong', 'em', 'u', 'ul', 'ol', 'li', 'a', 'br', 'hr']);\nconst DROPPED_WITH_CONTENT = new Set(['script', 'style', 'template', 'iframe', 'object', 'embed', 'noscript', 'svg', 'math', 'head', 'title']);\n\nconst withMentions = (text: string, key: string): ReactNode[] => {\n const parts: ReactNode[] = [];\n let last = 0;\n for (const match of text.matchAll(MENTION_PATTERN)) {\n const start = match.index ?? 0;\n if (start > last) {\n parts.push(text.slice(last, start));\n }\n parts.push(\n <span key={`${key}-${start}`} data-slot=\"rich-text-mention\" className={RICH_TEXT_MENTION_CLASS}>\n {match[0]}\n </span>,\n );\n last = start + match[0].length;\n }\n if (last < text.length) {\n parts.push(text.slice(last));\n }\n return parts;\n};\n\nconst toNodes = (parent: Node, key: string, insideLink: boolean): ReactNode[] => {\n const out: ReactNode[] = [];\n parent.childNodes.forEach((child, index) => {\n const childKey = `${key}.${index}`;\n if (child.nodeType === 3) {\n const text = child.textContent ?? '';\n out.push(...(insideLink ? [text] : withMentions(text, childKey)));\n return;\n }\n if (child.nodeType !== 1) {\n return;\n }\n const element = child as Element;\n const name = element.tagName.toLowerCase();\n if (DROPPED_WITH_CONTENT.has(name)) {\n return;\n }\n const tag = TAG_FOR[name] ?? name;\n if (!KEPT.has(tag)) {\n out.push(...toNodes(element, childKey, insideLink));\n return;\n }\n if (tag === 'br') {\n out.push(<br key={childKey} />);\n return;\n }\n if (tag === 'hr') {\n out.push(<hr key={childKey} />);\n return;\n }\n if (tag === 'a') {\n const href = element.getAttribute('href') ?? '';\n const inner = toNodes(element, childKey, true);\n out.push(\n ...(isAllowedRichTextHref(href)\n ? [\n <a key={childKey} href={href.trim()} rel=\"noopener noreferrer\" target=\"_blank\">\n {inner}\n </a>,\n ]\n : inner),\n );\n return;\n }\n out.push(createElement(tag, { key: childKey }, ...toNodes(element, childKey, insideLink)));\n });\n return out;\n};\n\n/** The HTML as React elements, keeping only what the editor can produce. Browser only (it needs a DOM parser). */\nexport const richTextToNodes = (html: string): ReactNode[] => {\n if (typeof DOMParser === 'undefined' || html === '') {\n return [];\n }\n const parsed = new DOMParser().parseFromString(`<body>${html}`, 'text/html');\n return toNodes(parsed.body, 'r', false);\n};\n\nexport interface IRichTextContentProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'dangerouslySetInnerHTML'> {\n /** The HTML to show. Only the editor's elements are rendered, whatever else it holds. */\n html: string;\n}\n\n/**\n * Shows rich text the editor produced (or any HTML), as the same elements the editor emits and nothing else:\n * `p`, `br`, `hr`, `strong`, `em`, `u`, `ul`, `ol`, `li` and `a` with an `href` (http, https or mailto; it opens in a new tab\n * with `rel=\"noopener noreferrer\"`). Everything else is dropped and its text kept. Built as React elements, not injected\n * as markup, so it is safe on HTML that has not been cleaned. A run like `@name@example.test` or `@assignees` is shown\n * as a chip.\n */\nexport const RichTextContent = ({ html, className, ...props }: IRichTextContentProps) => {\n const nodes = useMemo(() => richTextToNodes(html), [html]);\n return (\n <div data-slot=\"rich-text-content\" className={cn(RICH_TEXT_BODY_CLASS, className)} {...props}>\n {nodes}\n </div>\n );\n};\n","import { Menu as MenuPrimitive } from '@base-ui/react/menu';\nimport { POPUP_GROUP_LABEL_CLASS, POPUP_ITEM_INDICATOR_CLASS, popupItemClass } from '@edyn/ui/lib/popup-list';\nimport { cn } from '@edyn/ui/lib/utils';\nimport { IconCheck, IconChevronRight } from '@tabler/icons-react';\nimport type * as React from 'react';\nimport { ScrollArea } from '../scroll-area';\n\nexport const DropdownMenu = ({ ...props }: MenuPrimitive.Root.Props) => {\n return <MenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n};\n\nexport const DropdownMenuPortal = ({ ...props }: MenuPrimitive.Portal.Props) => {\n return <MenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />;\n};\n\nexport const DropdownMenuTrigger = ({ ...props }: MenuPrimitive.Trigger.Props) => {\n return <MenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />;\n};\n\n/**\n * Scrolls inside a DS ScrollArea like the other popup lists, with the bar shown\n * for as long as the menu overflows and a fade on whichever end is cut off.\n *\n * Base UI puts `role=\"menu\"` on this popup itself and offers no inner list part\n * to move it onto, so the ScrollArea sits INSIDE the role. That is only legal\n * because ScrollArea drops the `role=\"presentation\"` Base UI gives its root,\n * viewport and content: a menu may not own presentation wrappers (axe reports\n * a critical aria-required-children violation), but it may own plain divs.\n * e2e/a11y.spec.ts scans the open menu in both themes to keep it that way.\n */\nexport const DropdownMenuContent = ({\n align = 'start',\n alignOffset = 0,\n side = 'bottom',\n sideOffset = 4,\n className,\n children,\n ...props\n}: MenuPrimitive.Popup.Props & Pick<MenuPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>) => {\n return (\n <MenuPrimitive.Portal>\n <MenuPrimitive.Positioner className=\"isolate z-50 outline-none\" align={align} alignOffset={alignOffset} side={side} sideOffset={sideOffset}>\n <MenuPrimitive.Popup\n data-slot=\"dropdown-menu-content\"\n className={cn(\n 'z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95',\n 'motion-reduce:animate-none',\n className,\n )}\n {...props}\n >\n {/* max-h-inherit hands the positioner's measured height to the element that\n scrolls; the padding sits on the content so the cap is the popup's exactly. */}\n <ScrollArea type=\"always\" fade focusable={false} className=\"max-h-inherit\">\n <div className=\"p-1\">{children}</div>\n </ScrollArea>\n </MenuPrimitive.Popup>\n </MenuPrimitive.Positioner>\n </MenuPrimitive.Portal>\n );\n};\n\nexport const DropdownMenuGroup = ({ ...props }: MenuPrimitive.Group.Props) => {\n return <MenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />;\n};\n\nexport const DropdownMenuLabel = ({\n className,\n inset,\n ...props\n}: MenuPrimitive.GroupLabel.Props & {\n inset?: boolean;\n}) => {\n return (\n <MenuPrimitive.GroupLabel\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(POPUP_GROUP_LABEL_CLASS, 'data-[inset=true]:pl-7', className)}\n {...props}\n />\n );\n};\n\nexport const DropdownMenuItem = ({\n className,\n inset,\n variant = 'default',\n ...props\n}: MenuPrimitive.Item.Props & {\n inset?: boolean;\n variant?: 'default' | 'destructive';\n}) => {\n return (\n <MenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n 'group/dropdown-menu-item',\n popupItemClass(),\n 'data-[inset=true]:pl-7',\n // A destructive item keeps its own colour, and its own highlight with it:\n // the shared translucent one would make it read like any other item.\n 'data-[variant=destructive]:text-destructive data-[variant=destructive]:[&>svg]:text-destructive',\n 'data-[variant=destructive]:data-highlighted:bg-destructive/10 data-[variant=destructive]:data-highlighted:text-destructive',\n className,\n )}\n {...props}\n />\n );\n};\n\nexport const DropdownMenuSub = ({ ...props }: MenuPrimitive.SubmenuRoot.Props) => {\n return <MenuPrimitive.SubmenuRoot data-slot=\"dropdown-menu-sub\" {...props} />;\n};\n\nexport const DropdownMenuSubTrigger = ({\n className,\n inset,\n children,\n ...props\n}: MenuPrimitive.SubmenuTrigger.Props & {\n inset?: boolean;\n}) => {\n return (\n <MenuPrimitive.SubmenuTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n popupItemClass(),\n // An open submenu holds its trigger in the highlight while the pointer is\n // down in its panel.\n 'data-[inset=true]:pl-7 data-popup-open:bg-foreground/6 data-popup-open:[&>svg]:text-foreground',\n className,\n )}\n {...props}\n >\n {children}\n <IconChevronRight className=\"ml-auto\" />\n </MenuPrimitive.SubmenuTrigger>\n );\n};\n\nexport const DropdownMenuSubContent = ({\n align = 'start',\n alignOffset = -3,\n side = 'right',\n sideOffset = 0,\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuContent>) => {\n return (\n <DropdownMenuContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n 'w-auto min-w-[96px] rounded-lg bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95',\n 'motion-reduce:animate-none',\n className,\n )}\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n {...props}\n />\n );\n};\n\nexport const DropdownMenuCheckboxItem = ({\n className,\n children,\n checked,\n inset,\n ...props\n}: MenuPrimitive.CheckboxItem.Props & {\n inset?: boolean;\n}) => {\n return (\n <MenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n data-inset={inset}\n className={cn(popupItemClass('base-ui', true), 'data-checked:font-medium data-[inset=true]:pl-7', className)}\n checked={checked}\n {...props}\n >\n <span className={POPUP_ITEM_INDICATOR_CLASS} data-slot=\"dropdown-menu-checkbox-item-indicator\">\n <MenuPrimitive.CheckboxItemIndicator>\n <IconCheck />\n </MenuPrimitive.CheckboxItemIndicator>\n </span>\n {children}\n </MenuPrimitive.CheckboxItem>\n );\n};\n\nexport const DropdownMenuRadioGroup = ({ ...props }: MenuPrimitive.RadioGroup.Props) => {\n return <MenuPrimitive.RadioGroup data-slot=\"dropdown-menu-radio-group\" {...props} />;\n};\n\nexport const DropdownMenuRadioItem = ({\n className,\n children,\n inset,\n ...props\n}: MenuPrimitive.RadioItem.Props & {\n inset?: boolean;\n}) => {\n return (\n <MenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n data-inset={inset}\n className={cn(popupItemClass('base-ui', true), 'data-checked:font-medium data-[inset=true]:pl-7', className)}\n {...props}\n >\n <span className={POPUP_ITEM_INDICATOR_CLASS} data-slot=\"dropdown-menu-radio-item-indicator\">\n <MenuPrimitive.RadioItemIndicator>\n <IconCheck />\n </MenuPrimitive.RadioItemIndicator>\n </span>\n {children}\n </MenuPrimitive.RadioItem>\n );\n};\n\nexport const DropdownMenuSeparator = ({ className, ...props }: MenuPrimitive.Separator.Props) => {\n return <MenuPrimitive.Separator data-slot=\"dropdown-menu-separator\" className={cn('-mx-1 my-1 h-px bg-border', className)} {...props} />;\n};\n\nexport const DropdownMenuShortcut = ({ className, ...props }: React.ComponentProps<'span'>) => {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn('ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground', className)}\n {...props}\n />\n );\n};\n","import { Toggle as TogglePrimitive } from '@base-ui/react/toggle';\nimport { cn } from '@edyn/ui/lib/utils';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nexport const toggleVariants = cva(\n 'inline-flex shrink-0 cursor-pointer items-center justify-center gap-1.5 rounded-lg border border-transparent text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 data-pressed:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\"size-\"])]:size-4',\n {\n variants: {\n variant: {\n default: 'bg-transparent hover:bg-muted hover:text-foreground data-pressed:bg-muted',\n outline:\n 'border-border bg-background hover:bg-muted hover:text-foreground data-pressed:bg-muted dark:border-input dark:bg-input/30 dark:hover:bg-input/50',\n },\n size: {\n sm: 'h-7 px-2.5 text-[0.8rem]',\n default: 'h-8 px-2.5',\n lg: 'h-9 px-3',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n);\n\nexport type TToggleVariants = VariantProps<typeof toggleVariants>;\n\nexport const Toggle = <Value extends string>({\n className,\n variant = 'default',\n size = 'default',\n ...props\n}: TogglePrimitive.Props<Value> & TToggleVariants) => {\n return <TogglePrimitive data-slot=\"toggle\" className={cn(toggleVariants({ variant, size, className }))} {...props} />;\n};\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { a as PopoverHeader, c as Button, d as cssLength, i as PopoverDescription, l as buttonVariants, n as Popover, o as PopoverTitle, r as PopoverContent, s as PopoverTrigger, t as Input, u as cn } from "./chunks/input-syWxjY2U.js";
2
2
  import { a as useIsMobile, n as dateToDay, o as Calendar, r as dayToDate, s as CalendarDayButton, t as DateRangePicker } from "./chunks/date-range-picker-CWVcHgy2.js";
3
- import { A as useMergedRefs, C as RICH_TEXT_ELEMENTS, D as popupItemClass, E as POPUP_ITEM_INDICATOR_CLASS, O as ScrollArea, S as RICH_TEXT_ATTRIBUTES, T as isAllowedRichTextHref, _ as DropdownMenuTrigger, a as DropdownMenuContent, b as RichTextContent, c as DropdownMenuLabel, d as DropdownMenuRadioItem, f as DropdownMenuSeparator, g as DropdownMenuSubTrigger, h as DropdownMenuSubContent, i as DropdownMenuCheckboxItem, k as ScrollBar, l as DropdownMenuPortal, m as DropdownMenuSub, n as toggleVariants, o as DropdownMenuGroup, p as DropdownMenuShortcut, r as DropdownMenu, s as DropdownMenuItem, t as Toggle, u as DropdownMenuRadioGroup, v as RICH_TEXT_BODY_CLASS, w as RICH_TEXT_LINK_PROTOCOLS, x as richTextToNodes, y as RICH_TEXT_MENTION_CLASS } from "./chunks/toggle-CVnIkJVC.js";
3
+ import { A as ScrollBar, C as RICH_TEXT_ELEMENTS, D as POPUP_LIST_WIDTH_CLASS, E as POPUP_ITEM_INDICATOR_CLASS, O as popupItemClass, S as RICH_TEXT_ATTRIBUTES, T as isAllowedRichTextHref, _ as DropdownMenuTrigger, a as DropdownMenuContent, b as RichTextContent, c as DropdownMenuLabel, d as DropdownMenuRadioItem, f as DropdownMenuSeparator, g as DropdownMenuSubTrigger, h as DropdownMenuSubContent, i as DropdownMenuCheckboxItem, j as useMergedRefs, k as ScrollArea, l as DropdownMenuPortal, m as DropdownMenuSub, n as toggleVariants, o as DropdownMenuGroup, p as DropdownMenuShortcut, r as DropdownMenu, s as DropdownMenuItem, t as Toggle, u as DropdownMenuRadioGroup, v as RICH_TEXT_BODY_CLASS, w as RICH_TEXT_LINK_PROTOCOLS, x as richTextToNodes, y as RICH_TEXT_MENTION_CLASS } from "./chunks/toggle-Bxg8P-61.js";
4
4
  import * as React from "react";
5
5
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
6
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -597,7 +597,7 @@ var summarize = (chosen, placeholder, labels, summary = "selection") => {
597
597
  };
598
598
  /** Every chosen name, for a tooltip on a trigger whose text is cut. With `label` the names are not shown, so it is the text itself. */
599
599
  var fullSelection = (chosen, placeholder, labels, summary = "selection") => summary === "selection" && chosen.length > 0 ? chosen.map((option) => option.label).join(", ") : summarize(chosen, placeholder, labels, summary);
600
- var POPUP = "flex max-h-(--available-height) w-(--anchor-width) min-w-64 max-w-sm origin-(--transform-origin) flex-col overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-md outline-none duration-100 motion-reduce:animate-none data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95";
600
+ var POPUP = "flex max-h-(--available-height) w-(--anchor-width) min-w-64 max-w-[max(24rem,var(--anchor-width))] origin-(--transform-origin) flex-col overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-md outline-none duration-100 motion-reduce:animate-none data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95";
601
601
  var TRIGGER = "flex h-8 w-full min-w-0 cursor-pointer items-center justify-between gap-2 rounded-lg border border-input bg-transparent px-2.5 text-sm text-foreground transition-colors outline-none focus-visible:border-ring disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive data-popup-open:border-ring dark:bg-input/30";
602
602
  var Option = ({ option, index, style, measure, highlighted }) => {
603
603
  const [cut, setCut] = useState(false);
@@ -2016,10 +2016,11 @@ var ComboboxContent = ({ className, children, empty, portalContainer, ...props }
2016
2016
  children: /* @__PURE__ */ jsx(Combobox$1.Positioner, {
2017
2017
  "data-slot": "combobox-positioner",
2018
2018
  sideOffset: 4,
2019
+ align: "start",
2019
2020
  className: "z-50",
2020
2021
  children: /* @__PURE__ */ jsxs(Combobox$1.Popup, {
2021
2022
  "data-slot": "combobox-content",
2022
- className: cn("min-w-[var(--anchor-width)] overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-md outline-none motion-reduce:animate-none data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className),
2023
+ className: cn(POPUP_LIST_WIDTH_CLASS, "overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-md outline-none motion-reduce:animate-none data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className),
2023
2024
  ...props,
2024
2025
  children: [/* @__PURE__ */ jsx(ComboboxEmpty, { children: empty }), /* @__PURE__ */ jsx(ScrollArea, {
2025
2026
  type: "always",
@@ -3691,6 +3692,7 @@ var SelectContent = ({ className, children, portalContainer, ...props }) => {
3691
3692
  children: /* @__PURE__ */ jsx(Select$1.Positioner, {
3692
3693
  "data-slot": "select-positioner",
3693
3694
  sideOffset: 4,
3695
+ align: "start",
3694
3696
  alignItemWithTrigger: false,
3695
3697
  children: /* @__PURE__ */ jsx(Select$1.Popup, {
3696
3698
  "data-slot": "select-content",
@@ -3949,7 +3951,7 @@ var Sidebar = ({ side = "left", variant = "sidebar", collapsible = "offcanvas",
3949
3951
  }), /* @__PURE__ */ jsx("div", {
3950
3952
  "data-slot": "sidebar-container",
3951
3953
  "data-side": side,
3952
- className: cn("fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 motion-reduce:transition-none ease-linear data-[side=left]:left-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:right-0 data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)] md:flex", variant === "floating" || variant === "inset" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l", className),
3954
+ className: cn("fixed inset-y-0 top-(--sidebar-top) z-10 hidden h-[calc(100svh-var(--sidebar-top))] w-(--sidebar-width) transition-[left,right,width] duration-200 motion-reduce:transition-none ease-linear data-[side=left]:left-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:right-0 data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)] md:flex", variant === "floating" || variant === "inset" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l", className),
3953
3955
  ...props,
3954
3956
  children: /* @__PURE__ */ jsx("div", {
3955
3957
  "data-sidebar": "sidebar",
@@ -4240,11 +4242,11 @@ var Switch = ({ className, size = "default", ...props }) => {
4240
4242
  };
4241
4243
  //#endregion
4242
4244
  //#region ../ui/src/components/ui/table/table.tsx
4243
- var Table = ({ className, ...props }) => {
4245
+ var Table = ({ className, containerClassName, ...props }) => {
4244
4246
  return /* @__PURE__ */ jsx("div", {
4245
4247
  "data-slot": "table-container",
4246
4248
  "data-focus": "inset",
4247
- className: "relative w-full overflow-x-auto",
4249
+ className: cn("relative w-full overflow-x-auto", containerClassName),
4248
4250
  children: /* @__PURE__ */ jsx("table", {
4249
4251
  "data-slot": "table",
4250
4252
  className: cn("w-full caption-bottom text-sm", className),
@@ -4283,14 +4285,14 @@ var TableRow = ({ className, ...props }) => {
4283
4285
  var TableHead = ({ className, ...props }) => {
4284
4286
  return /* @__PURE__ */ jsx("th", {
4285
4287
  "data-slot": "table-head",
4286
- className: cn("h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", className),
4288
+ className: cn("h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0", className),
4287
4289
  ...props
4288
4290
  });
4289
4291
  };
4290
4292
  var TableCell = ({ className, ...props }) => {
4291
4293
  return /* @__PURE__ */ jsx("td", {
4292
4294
  "data-slot": "table-cell",
4293
- className: cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", className),
4295
+ className: cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0", className),
4294
4296
  ...props
4295
4297
  });
4296
4298
  };