@keboola/design 16.0.0 → 17.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -122,7 +122,7 @@ const Content = ({ ref, className, nav, children, ...props }) => {
122
122
  className: "tw:flex tw:w-full tw:@[640px]/section-nav:flex-row tw:@[640px]/section-nav:gap-8 tw:@max-[640px]/section-nav:flex-col tw:@max-[640px]/section-nav:gap-4",
123
123
  children: [/* @__PURE__ */ jsx("div", {
124
124
  "data-slot": "page-layout-nav",
125
- className: "tw:sticky tw:top-[calc(var(--page-header-height,0px)+1rem)] tw:z-10 tw:shrink-0 tw:self-start tw:@[640px]/section-nav:max-h-[var(--section-nav-available,100dvh)] tw:@[640px]/section-nav:w-64 tw:@[640px]/section-nav:overflow-y-auto tw:@[640px]/section-nav:supports-[animation-timeline:scroll()]:scroll-fade-y tw:@max-[640px]/section-nav:w-full tw:@max-[640px]/section-nav:bg-background tw:@max-[640px]/section-nav:before:absolute tw:@max-[640px]/section-nav:before:inset-x-[-0.5rem] tw:@max-[640px]/section-nav:before:top-[-1rem] tw:@max-[640px]/section-nav:before:bottom-0 tw:@max-[640px]/section-nav:before:-z-10 tw:@max-[640px]/section-nav:before:bg-background tw:@max-[640px]/section-nav:after:pointer-events-none tw:@max-[640px]/section-nav:after:absolute tw:@max-[640px]/section-nav:after:inset-x-0 tw:@max-[640px]/section-nav:after:top-full tw:@max-[640px]/section-nav:after:h-6 tw:@max-[640px]/section-nav:after:bg-linear-to-b tw:@max-[640px]/section-nav:after:from-background tw:@max-[640px]/section-nav:after:to-[rgb(var(--background)/0)]",
125
+ className: "tw:sticky tw:top-[calc(var(--page-header-height,0px)+1rem)] tw:z-10 tw:shrink-0 tw:self-start tw:@[640px]/section-nav:max-h-[var(--section-nav-available,100dvh)] tw:@[640px]/section-nav:w-64 tw:@[640px]/section-nav:overflow-y-auto tw:@[640px]/section-nav:scroll-fade-y tw:@max-[640px]/section-nav:w-full tw:@max-[640px]/section-nav:bg-background tw:@max-[640px]/section-nav:before:absolute tw:@max-[640px]/section-nav:before:inset-x-[-0.5rem] tw:@max-[640px]/section-nav:before:top-[-1rem] tw:@max-[640px]/section-nav:before:bottom-0 tw:@max-[640px]/section-nav:before:-z-10 tw:@max-[640px]/section-nav:before:bg-background tw:@max-[640px]/section-nav:after:pointer-events-none tw:@max-[640px]/section-nav:after:absolute tw:@max-[640px]/section-nav:after:inset-x-0 tw:@max-[640px]/section-nav:after:top-full tw:@max-[640px]/section-nav:after:h-6 tw:@max-[640px]/section-nav:after:bg-linear-to-b tw:@max-[640px]/section-nav:after:from-background tw:@max-[640px]/section-nav:after:to-[rgb(var(--background)/0)]",
126
126
  children: nav
127
127
  }), /* @__PURE__ */ jsx("div", {
128
128
  "data-slot": "page-layout-content-body",
@@ -162,4 +162,4 @@ const PageLayout = Object.assign(Root, {
162
162
  });
163
163
  export { PageLayout };
164
164
 
165
- //# sourceMappingURL=PageLayout-LcvJccOW.js.map
165
+ //# sourceMappingURL=PageLayout-kY31oUix.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageLayout-LcvJccOW.js","names":[],"sources":["../src/blocks/SectionNav/constants.ts","../src/blocks/PageLayout/context.ts","../src/blocks/PageLayout/PageLayout.tsx"],"sourcesContent":["/**\n * Names the container query `SectionNav` reads to pick the tree over the dropdown.\n *\n * It has to sit on an **ancestor**: a container query matches descendants only, so the element that\n * names the container can never read it — and it cannot be `SectionNav`'s own wrapper either, whose\n * width is what the switch changes (256px in a row, full width in a column), which would oscillate.\n * `PageLayout.Content nav={…}` puts it on the right element for you.\n */\nexport const SECTION_NAV_CONTAINER = 'tw:@container/section-nav';\n","import { createContext, use } from 'react';\nimport type { RefObject } from 'react';\n\n/**\n * The `PageLayout` root element, so `PageLayout.Header` can publish its measured height as a CSS\n * custom property the whole page can read — `PageLayout.Content nav={…}` pins the nav to it.\n *\n * A slot rendered outside a `PageLayout` reads `null` and skips publishing rather than throwing:\n * `PageLayout.Footer` is already documented as usable on its own.\n */\nexport const PageLayoutRootContext = createContext<RefObject<HTMLDivElement | null> | null>(null);\n\nexport const usePageLayoutRoot = () => use(PageLayoutRootContext);\n","import { useEffect, useRef } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\n\nimport { cn, mergeRefs } from '../../utils';\nimport { SECTION_NAV_CONTAINER } from '../SectionNav/constants';\n\nimport { PageLayoutRootContext, usePageLayoutRoot } from './context';\n\n/** `maxWidth`: `narrow` for forms, `default` for most pages, `wide` for dense detail views, `full` edge-to-edge. */\ntype RootProps = ComponentProps<'div'> & {\n maxWidth?: 'default' | 'narrow' | 'wide' | 'full';\n};\n\nconst maxWidthClass = {\n narrow: 'tw:max-w-[976px]',\n default: 'tw:max-w-[1280px]',\n wide: 'tw:max-w-[1600px]',\n full: 'tw:max-w-full',\n} as const;\n\nconst Root = ({ ref, className, maxWidth = 'full', children, ...props }: RootProps) => {\n const rootRef = useRef<HTMLDivElement>(null);\n\n return (\n <PageLayoutRootContext value={rootRef}>\n <div\n ref={mergeRefs(ref ?? null, rootRef)}\n className={cn(\n 'tw:flex tw:flex-col tw:gap-4 tw:w-full tw:mx-auto',\n maxWidthClass[maxWidth],\n className,\n )}\n {...props}\n >\n {children}\n </div>\n </PageLayoutRootContext>\n );\n};\n\nconst Breadcrumbs = ({ ref, className, children, ...props }: ComponentProps<'div'>) => (\n <div ref={ref} className={cn('tw:w-full', className)} {...props}>\n {children}\n </div>\n);\n\nconst STICKY_CHROME_BLEED =\n 'tw:before:absolute tw:before:inset-x-[-0.5rem] tw:before:inset-y-0 tw:before:-z-10 tw:before:bg-background';\n\ntype HeaderProps = ComponentProps<'header'> & {\n sticky?: boolean;\n};\n\nconst Header = ({ ref, className, sticky = false, children, ...props }: HeaderProps) => {\n const rootRef = usePageLayoutRoot();\n const headerRef = useRef<HTMLElement>(null);\n\n useEffect(() => {\n const header = headerRef.current;\n const root = rootRef?.current;\n\n if (!sticky || !header || !root || typeof ResizeObserver === 'undefined') return;\n\n const publish = () => {\n root.style.setProperty(\n '--page-header-height',\n `${Math.round(header.getBoundingClientRect().height)}px`,\n );\n };\n\n const observer = new ResizeObserver(publish);\n\n observer.observe(header);\n publish();\n\n return () => {\n observer.disconnect();\n root.style.removeProperty('--page-header-height');\n };\n }, [sticky, rootRef]);\n\n return (\n <header\n ref={mergeRefs(ref ?? null, headerRef)}\n className={cn(\n 'tw:w-full',\n sticky && ['tw:sticky tw:top-0 tw:z-20 tw:bg-background', STICKY_CHROME_BLEED],\n className,\n )}\n {...props}\n >\n {children}\n {sticky && (\n <div\n aria-hidden\n className=\"tw:pointer-events-none tw:absolute tw:inset-x-0 tw:top-full tw:h-6 tw:bg-linear-to-b tw:from-background tw:to-[rgb(var(--background)/0)]\"\n />\n )}\n </header>\n );\n};\n\nconst Tabs = ({ ref, className, children, ...props }: ComponentProps<'div'>) => (\n <div\n ref={ref}\n className={cn('tw:flex tw:w-full tw:items-center tw:border-b tw:border-border', className)}\n {...props}\n >\n {children}\n </div>\n);\n\ntype ContentProps = ComponentProps<'div'> & {\n nav?: ReactNode;\n};\n\nconst scrollParent = (from: HTMLElement): HTMLElement | null => {\n for (let el = from.parentElement; el; el = el.parentElement) {\n if (/auto|scroll/.test(getComputedStyle(el).overflowY)) return el;\n }\n\n return null;\n};\n\nconst useAvailableHeight = () => {\n const rowRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const row = rowRef.current;\n\n if (!row || typeof ResizeObserver === 'undefined') return;\n\n const scroller = scrollParent(row);\n\n const publish = () => {\n const top = row.getBoundingClientRect().top + (scroller?.scrollTop ?? window.scrollY);\n const room = scroller\n ? scroller.clientHeight - (top - scroller.getBoundingClientRect().top)\n : window.innerHeight - top;\n\n row.style.setProperty('--section-nav-available', `${Math.max(0, Math.round(room))}px`);\n };\n\n const observer = new ResizeObserver(publish);\n\n observer.observe(row);\n if (scroller) observer.observe(scroller);\n publish();\n\n return () => observer.disconnect();\n }, []);\n\n return rowRef;\n};\n\nconst Content = ({ ref, className, nav, children, ...props }: ContentProps) => {\n const rowRef = useAvailableHeight();\n\n if (!nav) {\n return (\n <div\n ref={ref}\n className={cn('tw:flex tw:w-full tw:flex-1 tw:flex-col', className)}\n {...props}\n >\n {children}\n </div>\n );\n }\n\n return (\n <div\n ref={ref}\n className={cn(\n 'tw:group/page-layout-content tw:flex tw:w-full tw:flex-1 tw:flex-col',\n SECTION_NAV_CONTAINER,\n className,\n )}\n {...props}\n >\n <div\n ref={rowRef}\n className=\"tw:flex tw:w-full tw:@[640px]/section-nav:flex-row tw:@[640px]/section-nav:gap-8 tw:@max-[640px]/section-nav:flex-col tw:@max-[640px]/section-nav:gap-4\"\n >\n <div\n data-slot=\"page-layout-nav\"\n className=\"tw:sticky tw:top-[calc(var(--page-header-height,0px)+1rem)] tw:z-10 tw:shrink-0 tw:self-start tw:@[640px]/section-nav:max-h-[var(--section-nav-available,100dvh)] tw:@[640px]/section-nav:w-64 tw:@[640px]/section-nav:overflow-y-auto tw:@[640px]/section-nav:supports-[animation-timeline:scroll()]:scroll-fade-y tw:@max-[640px]/section-nav:w-full tw:@max-[640px]/section-nav:bg-background tw:@max-[640px]/section-nav:before:absolute tw:@max-[640px]/section-nav:before:inset-x-[-0.5rem] tw:@max-[640px]/section-nav:before:top-[-1rem] tw:@max-[640px]/section-nav:before:bottom-0 tw:@max-[640px]/section-nav:before:-z-10 tw:@max-[640px]/section-nav:before:bg-background tw:@max-[640px]/section-nav:after:pointer-events-none tw:@max-[640px]/section-nav:after:absolute tw:@max-[640px]/section-nav:after:inset-x-0 tw:@max-[640px]/section-nav:after:top-full tw:@max-[640px]/section-nav:after:h-6 tw:@max-[640px]/section-nav:after:bg-linear-to-b tw:@max-[640px]/section-nav:after:from-background tw:@max-[640px]/section-nav:after:to-[rgb(var(--background)/0)]\"\n >\n {nav}\n </div>\n <div\n data-slot=\"page-layout-content-body\"\n className=\"tw:[--page-content-sticky-top:var(--page-header-height,0px)] tw:min-w-0 tw:flex-1\"\n >\n {children}\n </div>\n </div>\n </div>\n );\n};\n\ntype FooterProps = ComponentProps<'footer'> & {\n sticky?: boolean;\n};\n\nconst Footer = ({ ref, className, sticky = false, children, ...props }: FooterProps) => (\n <footer\n ref={ref}\n className={cn(\n 'tw:flex tw:w-full tw:items-center tw:justify-end tw:gap-3 tw:border-t tw:border-border tw:bg-background tw:px-6 tw:py-4',\n sticky && ['tw:sticky tw:bottom-0 tw:z-10', STICKY_CHROME_BLEED],\n className,\n )}\n {...props}\n >\n {children}\n </footer>\n);\n\n/**\n * Page chrome for every new kbc-ui page: max-width column + vertical rhythm + named slots.\n *\n * - No outer padding: the shell owns the gutter to the app frame.\n * - Not for modal bodies or embedded widgets; the `Sidebar` lives in the app shell.\n * - Search / filter pills go in `PageToolbar`, never in the header.\n *\n * @see RECIPES.md#list-detail\n * @see RECIPES.md#section-nav\n */\nexport const PageLayout = Object.assign(Root, {\n /** Usually composed by `PageHeader.Detail`; for layouts that fit neither `PageHeader` variant. */\n Breadcrumbs,\n /** `sticky` also publishes its height as `--page-header-height`, which `Content nav` pins to. */\n Header,\n /** Routing-based tab rows; use `Tabs` / `TabsContent` inside, never a raw `<button>`. */\n Tabs,\n /** `nav` (a `SectionNav`) makes it a two-column layout. */\n Content,\n /** Form submit bar; `sticky` pins it to the viewport. */\n Footer,\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"PageLayout-kY31oUix.js","names":[],"sources":["../src/blocks/SectionNav/constants.ts","../src/blocks/PageLayout/context.ts","../src/blocks/PageLayout/PageLayout.tsx"],"sourcesContent":["/**\n * Names the container query `SectionNav` reads to pick the tree over the dropdown.\n *\n * It has to sit on an **ancestor**: a container query matches descendants only, so the element that\n * names the container can never read it — and it cannot be `SectionNav`'s own wrapper either, whose\n * width is what the switch changes (256px in a row, full width in a column), which would oscillate.\n * `PageLayout.Content nav={…}` puts it on the right element for you.\n */\nexport const SECTION_NAV_CONTAINER = 'tw:@container/section-nav';\n","import { createContext, use } from 'react';\nimport type { RefObject } from 'react';\n\n/**\n * The `PageLayout` root element, so `PageLayout.Header` can publish its measured height as a CSS\n * custom property the whole page can read — `PageLayout.Content nav={…}` pins the nav to it.\n *\n * A slot rendered outside a `PageLayout` reads `null` and skips publishing rather than throwing:\n * `PageLayout.Footer` is already documented as usable on its own.\n */\nexport const PageLayoutRootContext = createContext<RefObject<HTMLDivElement | null> | null>(null);\n\nexport const usePageLayoutRoot = () => use(PageLayoutRootContext);\n","import { useEffect, useRef } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\n\nimport { cn, mergeRefs } from '../../utils';\nimport { SECTION_NAV_CONTAINER } from '../SectionNav/constants';\n\nimport { PageLayoutRootContext, usePageLayoutRoot } from './context';\n\n/** `maxWidth`: `narrow` for forms, `default` for most pages, `wide` for dense detail views, `full` edge-to-edge. */\ntype RootProps = ComponentProps<'div'> & {\n maxWidth?: 'default' | 'narrow' | 'wide' | 'full';\n};\n\nconst maxWidthClass = {\n narrow: 'tw:max-w-[976px]',\n default: 'tw:max-w-[1280px]',\n wide: 'tw:max-w-[1600px]',\n full: 'tw:max-w-full',\n} as const;\n\nconst Root = ({ ref, className, maxWidth = 'full', children, ...props }: RootProps) => {\n const rootRef = useRef<HTMLDivElement>(null);\n\n return (\n <PageLayoutRootContext value={rootRef}>\n <div\n ref={mergeRefs(ref ?? null, rootRef)}\n className={cn(\n 'tw:flex tw:flex-col tw:gap-4 tw:w-full tw:mx-auto',\n maxWidthClass[maxWidth],\n className,\n )}\n {...props}\n >\n {children}\n </div>\n </PageLayoutRootContext>\n );\n};\n\nconst Breadcrumbs = ({ ref, className, children, ...props }: ComponentProps<'div'>) => (\n <div ref={ref} className={cn('tw:w-full', className)} {...props}>\n {children}\n </div>\n);\n\nconst STICKY_CHROME_BLEED =\n 'tw:before:absolute tw:before:inset-x-[-0.5rem] tw:before:inset-y-0 tw:before:-z-10 tw:before:bg-background';\n\ntype HeaderProps = ComponentProps<'header'> & {\n sticky?: boolean;\n};\n\nconst Header = ({ ref, className, sticky = false, children, ...props }: HeaderProps) => {\n const rootRef = usePageLayoutRoot();\n const headerRef = useRef<HTMLElement>(null);\n\n useEffect(() => {\n const header = headerRef.current;\n const root = rootRef?.current;\n\n if (!sticky || !header || !root || typeof ResizeObserver === 'undefined') return;\n\n const publish = () => {\n root.style.setProperty(\n '--page-header-height',\n `${Math.round(header.getBoundingClientRect().height)}px`,\n );\n };\n\n const observer = new ResizeObserver(publish);\n\n observer.observe(header);\n publish();\n\n return () => {\n observer.disconnect();\n root.style.removeProperty('--page-header-height');\n };\n }, [sticky, rootRef]);\n\n return (\n <header\n ref={mergeRefs(ref ?? null, headerRef)}\n className={cn(\n 'tw:w-full',\n sticky && ['tw:sticky tw:top-0 tw:z-20 tw:bg-background', STICKY_CHROME_BLEED],\n className,\n )}\n {...props}\n >\n {children}\n {sticky && (\n <div\n aria-hidden\n className=\"tw:pointer-events-none tw:absolute tw:inset-x-0 tw:top-full tw:h-6 tw:bg-linear-to-b tw:from-background tw:to-[rgb(var(--background)/0)]\"\n />\n )}\n </header>\n );\n};\n\nconst Tabs = ({ ref, className, children, ...props }: ComponentProps<'div'>) => (\n <div\n ref={ref}\n className={cn('tw:flex tw:w-full tw:items-center tw:border-b tw:border-border', className)}\n {...props}\n >\n {children}\n </div>\n);\n\ntype ContentProps = ComponentProps<'div'> & {\n nav?: ReactNode;\n};\n\nconst scrollParent = (from: HTMLElement): HTMLElement | null => {\n for (let el = from.parentElement; el; el = el.parentElement) {\n if (/auto|scroll/.test(getComputedStyle(el).overflowY)) return el;\n }\n\n return null;\n};\n\nconst useAvailableHeight = () => {\n const rowRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const row = rowRef.current;\n\n if (!row || typeof ResizeObserver === 'undefined') return;\n\n const scroller = scrollParent(row);\n\n const publish = () => {\n const top = row.getBoundingClientRect().top + (scroller?.scrollTop ?? window.scrollY);\n const room = scroller\n ? scroller.clientHeight - (top - scroller.getBoundingClientRect().top)\n : window.innerHeight - top;\n\n row.style.setProperty('--section-nav-available', `${Math.max(0, Math.round(room))}px`);\n };\n\n const observer = new ResizeObserver(publish);\n\n observer.observe(row);\n if (scroller) observer.observe(scroller);\n publish();\n\n return () => observer.disconnect();\n }, []);\n\n return rowRef;\n};\n\nconst Content = ({ ref, className, nav, children, ...props }: ContentProps) => {\n const rowRef = useAvailableHeight();\n\n if (!nav) {\n return (\n <div\n ref={ref}\n className={cn('tw:flex tw:w-full tw:flex-1 tw:flex-col', className)}\n {...props}\n >\n {children}\n </div>\n );\n }\n\n return (\n <div\n ref={ref}\n className={cn(\n 'tw:group/page-layout-content tw:flex tw:w-full tw:flex-1 tw:flex-col',\n SECTION_NAV_CONTAINER,\n className,\n )}\n {...props}\n >\n <div\n ref={rowRef}\n className=\"tw:flex tw:w-full tw:@[640px]/section-nav:flex-row tw:@[640px]/section-nav:gap-8 tw:@max-[640px]/section-nav:flex-col tw:@max-[640px]/section-nav:gap-4\"\n >\n <div\n data-slot=\"page-layout-nav\"\n className=\"tw:sticky tw:top-[calc(var(--page-header-height,0px)+1rem)] tw:z-10 tw:shrink-0 tw:self-start tw:@[640px]/section-nav:max-h-[var(--section-nav-available,100dvh)] tw:@[640px]/section-nav:w-64 tw:@[640px]/section-nav:overflow-y-auto tw:@[640px]/section-nav:scroll-fade-y tw:@max-[640px]/section-nav:w-full tw:@max-[640px]/section-nav:bg-background tw:@max-[640px]/section-nav:before:absolute tw:@max-[640px]/section-nav:before:inset-x-[-0.5rem] tw:@max-[640px]/section-nav:before:top-[-1rem] tw:@max-[640px]/section-nav:before:bottom-0 tw:@max-[640px]/section-nav:before:-z-10 tw:@max-[640px]/section-nav:before:bg-background tw:@max-[640px]/section-nav:after:pointer-events-none tw:@max-[640px]/section-nav:after:absolute tw:@max-[640px]/section-nav:after:inset-x-0 tw:@max-[640px]/section-nav:after:top-full tw:@max-[640px]/section-nav:after:h-6 tw:@max-[640px]/section-nav:after:bg-linear-to-b tw:@max-[640px]/section-nav:after:from-background tw:@max-[640px]/section-nav:after:to-[rgb(var(--background)/0)]\"\n >\n {nav}\n </div>\n <div\n data-slot=\"page-layout-content-body\"\n className=\"tw:[--page-content-sticky-top:var(--page-header-height,0px)] tw:min-w-0 tw:flex-1\"\n >\n {children}\n </div>\n </div>\n </div>\n );\n};\n\ntype FooterProps = ComponentProps<'footer'> & {\n sticky?: boolean;\n};\n\nconst Footer = ({ ref, className, sticky = false, children, ...props }: FooterProps) => (\n <footer\n ref={ref}\n className={cn(\n 'tw:flex tw:w-full tw:items-center tw:justify-end tw:gap-3 tw:border-t tw:border-border tw:bg-background tw:px-6 tw:py-4',\n sticky && ['tw:sticky tw:bottom-0 tw:z-10', STICKY_CHROME_BLEED],\n className,\n )}\n {...props}\n >\n {children}\n </footer>\n);\n\n/**\n * Page chrome for every new kbc-ui page: max-width column + vertical rhythm + named slots.\n *\n * - No outer padding: the shell owns the gutter to the app frame.\n * - Not for modal bodies or embedded widgets; the `Sidebar` lives in the app shell.\n * - Search / filter pills go in `PageToolbar`, never in the header.\n *\n * @see RECIPES.md#list-detail\n * @see RECIPES.md#section-nav\n */\nexport const PageLayout = Object.assign(Root, {\n /** Usually composed by `PageHeader.Detail`; for layouts that fit neither `PageHeader` variant. */\n Breadcrumbs,\n /** `sticky` also publishes its height as `--page-header-height`, which `Content nav` pins to. */\n Header,\n /** Routing-based tab rows; use `Tabs` / `TabsContent` inside, never a raw `<button>`. */\n Tabs,\n /** `nav` (a `SectionNav`) makes it a two-column layout. */\n Content,\n /** Form submit bar; `sticky` pins it to the viewport. */\n Footer,\n});\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -4678,21 +4678,9 @@ declare namespace Markdown {
4678
4678
  export { MarkdownRoot as Root };
4679
4679
  export { MarkdownBlock as Block };
4680
4680
  }
4681
- /**
4682
- * The fade's end colour — must match the host's surface, or it draws a strip over the data.
4683
- *
4684
- * - Full class strings: Tailwind reads literals.
4685
- */
4686
- declare const FADE_SURFACE: {
4687
- readonly card: 'tw:from-card';
4688
- readonly background: 'tw:from-background';
4689
- };
4690
- type Surface = keyof typeof FADE_SURFACE;
4691
4681
  type Props$129 = {
4692
4682
  /** A `Table bordered` at intrinsic width (`tw:min-w-max`) — otherwise it wraps and never overflows. */
4693
4683
  children: ReactNode;
4694
- /** What the host paints behind the table; paint `Table`'s header band this colour too. */
4695
- surface?: Surface;
4696
4684
  /** Host controls left of the expand action; hover reveal is the host's (`tw:group` on `className`). */
4697
4685
  actions?: ReactNode;
4698
4686
  /** Opens the table somewhere wider; omit where there is nowhere to go (the fade still draws). */
@@ -4706,11 +4694,11 @@ type Props$129 = {
4706
4694
  *
4707
4695
  * - Controls sit in a fixed-height rail above the grid, so they never cover rows or shift them.
4708
4696
  * - The fade shows only while content remains to the right.
4709
- * - A painted gradient, not `tw:scroll-fade-x`: that needs scroll-driven animations, which the
4697
+ * - A static mask, not `tw:scroll-fade-x`: that needs scroll-driven animations, which the
4710
4698
  * `baseline-widely-available` build floor lacks, and must sit on `Table`'s own container.
4711
4699
  * - Past `EXPAND_RATIO` the expand action shows without hover.
4712
4700
  */
4713
- declare const MarkdownTable: ({ children, actions, onExpand, surface, sortable, className }: Props$129) => import("react").JSX.Element;
4701
+ declare const MarkdownTable: ({ children, actions, onExpand, sortable, className }: Props$129) => import("react").JSX.Element;
4714
4702
  type Props$128 = {
4715
4703
  user?: {
4716
4704
  name: string | undefined;
package/dist/index.js CHANGED
@@ -69,7 +69,7 @@ import { OtpInput, REGEXP_ONLY_CHARS, REGEXP_ONLY_DIGITS, REGEXP_ONLY_DIGITS_AND
69
69
  import { SearchInput } from "./SearchInput-eLS-uvOn.js";
70
70
  import { SearchInputWithNavigation } from "./internal/blocks/SearchInputWithNavigation.js";
71
71
  import { FileUpload, useFileDropTarget, useFileUploadRejections } from "./FileUpload-DskvxhAr.js";
72
- import { ANSWER_SOURCES_VISIBLE, AnswerActions, AnswerSources, AnswerSummary, AttachmentChip, CONTEXT_CHIP_EXPANDABLE_LENGTH, ChatInlineIcon, ChatNotice, CollapsibleStepHeader, ContextChip, FileDownloadChip, FileGallery, InlineStepDetail, InlineStepGroup, InlineStepLabel, JumpToLatest, Markdown, MarkdownTable, MessageBubble, ModeChip, PROMPT_INPUT_CONTAINER, PlanApproval, PlanRewritingIndicator, PromptInput, Question, QuestionBlock, SourceChip, SuggestedPrompt, ThinkingIndicator, ToolCallApproval, ToolCallChip, ToolCallStatusHeader, UsageBar, UsageStats, clampPercentage, findMentionToken, findSlashToken, formatPercentage, getChatInlineIconName, splitSealedBlocks, withholdOpenTail } from "./AIKit-Cf5plya2.js";
72
+ import { ANSWER_SOURCES_VISIBLE, AnswerActions, AnswerSources, AnswerSummary, AttachmentChip, CONTEXT_CHIP_EXPANDABLE_LENGTH, ChatInlineIcon, ChatNotice, CollapsibleStepHeader, ContextChip, FileDownloadChip, FileGallery, InlineStepDetail, InlineStepGroup, InlineStepLabel, JumpToLatest, Markdown, MarkdownTable, MessageBubble, ModeChip, PROMPT_INPUT_CONTAINER, PlanApproval, PlanRewritingIndicator, PromptInput, Question, QuestionBlock, SourceChip, SuggestedPrompt, ThinkingIndicator, ToolCallApproval, ToolCallChip, ToolCallStatusHeader, UsageBar, UsageStats, clampPercentage, findMentionToken, findSlashToken, formatPercentage, getChatInlineIconName, splitSealedBlocks, withholdOpenTail } from "./AIKit-CxKkvN0q.js";
73
73
  import { Collapsible } from "./Collapsible-zsXk4Vpp.js";
74
74
  import { Alert } from "./Alert-DziS8n1H.js";
75
75
  import { Table, tableAriaSort } from "./Table-BwgBm3hJ.js";
@@ -94,7 +94,7 @@ import { DEFAULT_BRAND_ID, DEFAULT_COLOR_SCHEME } from "./themeScopeContext-BZGP
94
94
  import { AppShell, appShellSlotSelector } from "./AppShell-BUa3U7-e.js";
95
95
  import { BrandLogo } from "./BrandLogo-Dn7hhp2c.js";
96
96
  import { AuthLayout } from "./internal/blocks/AuthLayout.js";
97
- import { PageLayout } from "./PageLayout-LcvJccOW.js";
97
+ import { PageLayout } from "./PageLayout-kY31oUix.js";
98
98
  import { PageHeader } from "./PageHeader-DosMyar2.js";
99
99
  import { PageToolbar } from "./PageToolbar-By2HznxO.js";
100
100
  import { SectionNav } from "./SectionNav-L81iJBo3.js";
@@ -1 +1 @@
1
- export { ANSWER_SOURCES_VISIBLE, AnswerActions, AnswerSources, AnswerSummary, AttachmentChip, CONTEXT_CHIP_EXPANDABLE_LENGTH, ChatInlineIcon, ChatNotice, CollapsibleStepHeader, ContextChip, FileDownloadChip, FileGallery, InlineStepDetail, InlineStepGroup, InlineStepLabel, JumpToLatest, Markdown, MarkdownTable, MessageBubble, ModeChip, PROMPT_INPUT_CONTAINER, PlanApproval, PlanRewritingIndicator, PromptInput, Question, QuestionBlock, SourceChip, SuggestedPrompt, ThinkingIndicator, ToolCallApproval, ToolCallChip, ToolCallStatusHeader, UsageBar, UsageStats, clampPercentage, findMentionToken, findSlashToken, formatPercentage, getChatInlineIconName, splitSealedBlocks, withholdOpenTail } from "../../AIKit-Cf5plya2.js";
1
+ export { ANSWER_SOURCES_VISIBLE, AnswerActions, AnswerSources, AnswerSummary, AttachmentChip, CONTEXT_CHIP_EXPANDABLE_LENGTH, ChatInlineIcon, ChatNotice, CollapsibleStepHeader, ContextChip, FileDownloadChip, FileGallery, InlineStepDetail, InlineStepGroup, InlineStepLabel, JumpToLatest, Markdown, MarkdownTable, MessageBubble, ModeChip, PROMPT_INPUT_CONTAINER, PlanApproval, PlanRewritingIndicator, PromptInput, Question, QuestionBlock, SourceChip, SuggestedPrompt, ThinkingIndicator, ToolCallApproval, ToolCallChip, ToolCallStatusHeader, UsageBar, UsageStats, clampPercentage, findMentionToken, findSlashToken, formatPercentage, getChatInlineIconName, splitSealedBlocks, withholdOpenTail } from "../../AIKit-CxKkvN0q.js";
@@ -44,7 +44,8 @@ const emptyStateIconClassnames = cva([
44
44
  const emptyStateTitleClassnames = cva([
45
45
  "tw:m-0",
46
46
  "tw:font-semibold",
47
- "tw:text-foreground"
47
+ "tw:text-foreground",
48
+ "tw:text-balance"
48
49
  ], {
49
50
  variants: { variant: {
50
51
  default: ["tw:text-lg", "tw:leading-7"],
@@ -52,7 +53,11 @@ const emptyStateTitleClassnames = cva([
52
53
  } },
53
54
  defaultVariants: { variant: "default" }
54
55
  });
55
- const emptyStateDescriptionClassnames = cva(["tw:m-0", "tw:text-muted-foreground"], {
56
+ const emptyStateDescriptionClassnames = cva([
57
+ "tw:m-0",
58
+ "tw:text-muted-foreground",
59
+ "tw:text-pretty"
60
+ ], {
56
61
  variants: { variant: {
57
62
  default: [
58
63
  "tw:text-sm",
@@ -1 +1 @@
1
- {"version":3,"file":"EmptyState.js","names":[],"sources":["../../../src/blocks/EmptyState/EmptyState.tsx"],"sourcesContent":["import type { ComponentProps } from 'react';\nimport type { VariantProps } from 'class-variance-authority';\nimport { cva } from 'class-variance-authority';\n\nconst emptyStateClassnames = cva(['tw:flex', 'tw:flex-col', 'tw:items-center', 'tw:text-center'], {\n variants: {\n variant: {\n default: ['tw:py-16', 'tw:px-8', 'tw:gap-4'],\n compact: ['tw:py-8', 'tw:px-4', 'tw:gap-2'],\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\nconst emptyStateIconClassnames = cva(\n ['tw:flex', 'tw:items-center', 'tw:justify-center', 'tw:text-muted-foreground'],\n {\n variants: {\n variant: {\n default: ['tw:size-16', 'tw:text-4xl', 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-10'],\n compact: ['tw:size-10', 'tw:text-2xl', 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-6'],\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n },\n);\n\nconst emptyStateTitleClassnames = cva(['tw:m-0', 'tw:font-semibold', 'tw:text-foreground'], {\n variants: {\n variant: {\n default: ['tw:text-lg', 'tw:leading-7'],\n compact: ['tw:text-base', 'tw:leading-6'],\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\nconst emptyStateDescriptionClassnames = cva(['tw:m-0', 'tw:text-muted-foreground'], {\n variants: {\n variant: {\n default: ['tw:text-sm', 'tw:leading-5', 'tw:max-w-sm'],\n compact: ['tw:text-xs', 'tw:leading-4', 'tw:max-w-xs'],\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\nconst emptyStateActionsClassnames = cva(['tw:flex', 'tw:items-center', 'tw:flex-wrap'], {\n variants: {\n variant: {\n default: ['tw:gap-3', 'tw:mt-2'],\n compact: ['tw:gap-2', 'tw:mt-1'],\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\ntype Variant = VariantProps<typeof emptyStateClassnames>['variant'];\n\n/** `variant`: `\"default\"` for full-page, `\"compact\"` inside cards / small surfaces. */\ntype RootProps = ComponentProps<'div'> &\n VariantProps<typeof emptyStateClassnames> & {\n variant?: Variant;\n };\n\n/**\n * \"Nothing here yet\" placeholder with icon, title, description and actions slots.\n *\n * - For intentionally empty surfaces; guide the user to the next action.\n * - Not for errors (`ErrorState`), loading (`Skeleton`) or search misses (`EmptySearchContent`).\n * - Use `variant=\"compact\"` inside a `Card`.\n * @see RECIPES.md#card-with-empty-state\n */\nconst EmptyStateRoot = ({ className, variant = 'default', children, ...rest }: RootProps) => (\n <div role=\"status\" className={emptyStateClassnames({ className, variant })} {...rest}>\n {children}\n </div>\n);\n\ntype SlotProps = ComponentProps<'div'> & { variant?: Variant };\n\nconst EmptyStateIcon = ({ className, variant = 'default', children, ...rest }: SlotProps) => (\n <div className={emptyStateIconClassnames({ className, variant })} {...rest}>\n {children}\n </div>\n);\n\ntype TitleProps = ComponentProps<'h3'> & { variant?: Variant };\n\nconst EmptyStateTitle = ({ className, variant = 'default', children, ...rest }: TitleProps) => (\n <h3 className={emptyStateTitleClassnames({ className, variant })} {...rest}>\n {children}\n </h3>\n);\n\ntype DescriptionProps = ComponentProps<'p'> & { variant?: Variant };\n\nconst EmptyStateDescription = ({\n className,\n variant = 'default',\n children,\n ...rest\n}: DescriptionProps) => (\n <p className={emptyStateDescriptionClassnames({ className, variant })} {...rest}>\n {children}\n </p>\n);\n\ntype ActionsProps = ComponentProps<'div'> & { variant?: Variant };\n\nconst EmptyStateActions = ({ className, variant = 'default', children, ...rest }: ActionsProps) => (\n <div className={emptyStateActionsClassnames({ className, variant })} {...rest}>\n {children}\n </div>\n);\n\nexport const EmptyState = EmptyStateRoot as typeof EmptyStateRoot & {\n Icon: typeof EmptyStateIcon;\n Title: typeof EmptyStateTitle;\n Description: typeof EmptyStateDescription;\n Actions: typeof EmptyStateActions;\n};\n\nEmptyState.Icon = EmptyStateIcon;\nEmptyState.Title = EmptyStateTitle;\nEmptyState.Description = EmptyStateDescription;\nEmptyState.Actions = EmptyStateActions;\n\nexport type { RootProps as EmptyStateProps, Variant as EmptyStateVariant };\n"],"mappings":";;;AAIA,MAAM,uBAAuB,IAAI;CAAC;CAAW;CAAe;CAAmB;AAAgB,GAAG;CAChG,UAAU,EACR,SAAS;EACP,SAAS;GAAC;GAAY;GAAW;EAAU;EAC3C,SAAS;GAAC;GAAW;GAAW;EAAU;CAC5C,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CAAC;AAED,MAAM,2BAA2B,IAC/B;CAAC;CAAW;CAAmB;CAAqB;AAA0B,GAC9E;CACE,UAAU,EACR,SAAS;EACP,SAAS;GAAC;GAAc;GAAe;EAA6C;EACpF,SAAS;GAAC;GAAc;GAAe;EAA4C;CACrF,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CACF;AAEA,MAAM,4BAA4B,IAAI;CAAC;CAAU;CAAoB;AAAoB,GAAG;CAC1F,UAAU,EACR,SAAS;EACP,SAAS,CAAC,cAAc,cAAc;EACtC,SAAS,CAAC,gBAAgB,cAAc;CAC1C,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CAAC;AAED,MAAM,kCAAkC,IAAI,CAAC,UAAU,0BAA0B,GAAG;CAClF,UAAU,EACR,SAAS;EACP,SAAS;GAAC;GAAc;GAAgB;EAAa;EACrD,SAAS;GAAC;GAAc;GAAgB;EAAa;CACvD,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CAAC;AAED,MAAM,8BAA8B,IAAI;CAAC;CAAW;CAAmB;AAAc,GAAG;CACtF,UAAU,EACR,SAAS;EACP,SAAS,CAAC,YAAY,SAAS;EAC/B,SAAS,CAAC,YAAY,SAAS;CACjC,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CAAC;;;;;;;;;AAkBD,MAAM,kBAAkB,EAAE,WAAW,UAAU,WAAW,UAAU,GAAG,WACrE,oBAAC,OAAD;CAAK,MAAK;CAAS,WAAW,qBAAqB;EAAE;EAAW;CAAQ,CAAC;CAAG,GAAI;CAC7E;AACE,CAAA;AAKP,MAAM,kBAAkB,EAAE,WAAW,UAAU,WAAW,UAAU,GAAG,WACrE,oBAAC,OAAD;CAAK,WAAW,yBAAyB;EAAE;EAAW;CAAQ,CAAC;CAAG,GAAI;CACnE;AACE,CAAA;AAKP,MAAM,mBAAmB,EAAE,WAAW,UAAU,WAAW,UAAU,GAAG,WACtE,oBAAC,MAAD;CAAI,WAAW,0BAA0B;EAAE;EAAW;CAAQ,CAAC;CAAG,GAAI;CACnE;AACC,CAAA;AAKN,MAAM,yBAAyB,EAC7B,WACA,UAAU,WACV,UACA,GAAG,WAEH,oBAAC,KAAD;CAAG,WAAW,gCAAgC;EAAE;EAAW;CAAQ,CAAC;CAAG,GAAI;CACxE;AACA,CAAA;AAKL,MAAM,qBAAqB,EAAE,WAAW,UAAU,WAAW,UAAU,GAAG,WACxE,oBAAC,OAAD;CAAK,WAAW,4BAA4B;EAAE;EAAW;CAAQ,CAAC;CAAG,GAAI;CACtE;AACE,CAAA;AAGP,MAAa,aAAa;AAO1B,WAAW,OAAO;AAClB,WAAW,QAAQ;AACnB,WAAW,cAAc;AACzB,WAAW,UAAU"}
1
+ {"version":3,"file":"EmptyState.js","names":[],"sources":["../../../src/blocks/EmptyState/EmptyState.tsx"],"sourcesContent":["import type { ComponentProps } from 'react';\nimport type { VariantProps } from 'class-variance-authority';\nimport { cva } from 'class-variance-authority';\n\nconst emptyStateClassnames = cva(['tw:flex', 'tw:flex-col', 'tw:items-center', 'tw:text-center'], {\n variants: {\n variant: {\n default: ['tw:py-16', 'tw:px-8', 'tw:gap-4'],\n compact: ['tw:py-8', 'tw:px-4', 'tw:gap-2'],\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\nconst emptyStateIconClassnames = cva(\n ['tw:flex', 'tw:items-center', 'tw:justify-center', 'tw:text-muted-foreground'],\n {\n variants: {\n variant: {\n default: ['tw:size-16', 'tw:text-4xl', 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-10'],\n compact: ['tw:size-10', 'tw:text-2xl', 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-6'],\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n },\n);\n\nconst emptyStateTitleClassnames = cva(\n ['tw:m-0', 'tw:font-semibold', 'tw:text-foreground', 'tw:text-balance'],\n {\n variants: {\n variant: {\n default: ['tw:text-lg', 'tw:leading-7'],\n compact: ['tw:text-base', 'tw:leading-6'],\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n },\n);\n\nconst emptyStateDescriptionClassnames = cva(\n ['tw:m-0', 'tw:text-muted-foreground', 'tw:text-pretty'],\n {\n variants: {\n variant: {\n default: ['tw:text-sm', 'tw:leading-5', 'tw:max-w-sm'],\n compact: ['tw:text-xs', 'tw:leading-4', 'tw:max-w-xs'],\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n },\n);\n\nconst emptyStateActionsClassnames = cva(['tw:flex', 'tw:items-center', 'tw:flex-wrap'], {\n variants: {\n variant: {\n default: ['tw:gap-3', 'tw:mt-2'],\n compact: ['tw:gap-2', 'tw:mt-1'],\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\ntype Variant = VariantProps<typeof emptyStateClassnames>['variant'];\n\n/** `variant`: `\"default\"` for full-page, `\"compact\"` inside cards / small surfaces. */\ntype RootProps = ComponentProps<'div'> &\n VariantProps<typeof emptyStateClassnames> & {\n variant?: Variant;\n };\n\n/**\n * \"Nothing here yet\" placeholder with icon, title, description and actions slots.\n *\n * - For intentionally empty surfaces; guide the user to the next action.\n * - Not for errors (`ErrorState`), loading (`Skeleton`) or search misses (`EmptySearchContent`).\n * - Use `variant=\"compact\"` inside a `Card`.\n * @see RECIPES.md#card-with-empty-state\n */\nconst EmptyStateRoot = ({ className, variant = 'default', children, ...rest }: RootProps) => (\n <div role=\"status\" className={emptyStateClassnames({ className, variant })} {...rest}>\n {children}\n </div>\n);\n\ntype SlotProps = ComponentProps<'div'> & { variant?: Variant };\n\nconst EmptyStateIcon = ({ className, variant = 'default', children, ...rest }: SlotProps) => (\n <div className={emptyStateIconClassnames({ className, variant })} {...rest}>\n {children}\n </div>\n);\n\ntype TitleProps = ComponentProps<'h3'> & { variant?: Variant };\n\nconst EmptyStateTitle = ({ className, variant = 'default', children, ...rest }: TitleProps) => (\n <h3 className={emptyStateTitleClassnames({ className, variant })} {...rest}>\n {children}\n </h3>\n);\n\ntype DescriptionProps = ComponentProps<'p'> & { variant?: Variant };\n\nconst EmptyStateDescription = ({\n className,\n variant = 'default',\n children,\n ...rest\n}: DescriptionProps) => (\n <p className={emptyStateDescriptionClassnames({ className, variant })} {...rest}>\n {children}\n </p>\n);\n\ntype ActionsProps = ComponentProps<'div'> & { variant?: Variant };\n\nconst EmptyStateActions = ({ className, variant = 'default', children, ...rest }: ActionsProps) => (\n <div className={emptyStateActionsClassnames({ className, variant })} {...rest}>\n {children}\n </div>\n);\n\nexport const EmptyState = EmptyStateRoot as typeof EmptyStateRoot & {\n Icon: typeof EmptyStateIcon;\n Title: typeof EmptyStateTitle;\n Description: typeof EmptyStateDescription;\n Actions: typeof EmptyStateActions;\n};\n\nEmptyState.Icon = EmptyStateIcon;\nEmptyState.Title = EmptyStateTitle;\nEmptyState.Description = EmptyStateDescription;\nEmptyState.Actions = EmptyStateActions;\n\nexport type { RootProps as EmptyStateProps, Variant as EmptyStateVariant };\n"],"mappings":";;;AAIA,MAAM,uBAAuB,IAAI;CAAC;CAAW;CAAe;CAAmB;AAAgB,GAAG;CAChG,UAAU,EACR,SAAS;EACP,SAAS;GAAC;GAAY;GAAW;EAAU;EAC3C,SAAS;GAAC;GAAW;GAAW;EAAU;CAC5C,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CAAC;AAED,MAAM,2BAA2B,IAC/B;CAAC;CAAW;CAAmB;CAAqB;AAA0B,GAC9E;CACE,UAAU,EACR,SAAS;EACP,SAAS;GAAC;GAAc;GAAe;EAA6C;EACpF,SAAS;GAAC;GAAc;GAAe;EAA4C;CACrF,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CACF;AAEA,MAAM,4BAA4B,IAChC;CAAC;CAAU;CAAoB;CAAsB;AAAiB,GACtE;CACE,UAAU,EACR,SAAS;EACP,SAAS,CAAC,cAAc,cAAc;EACtC,SAAS,CAAC,gBAAgB,cAAc;CAC1C,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CACF;AAEA,MAAM,kCAAkC,IACtC;CAAC;CAAU;CAA4B;AAAgB,GACvD;CACE,UAAU,EACR,SAAS;EACP,SAAS;GAAC;GAAc;GAAgB;EAAa;EACrD,SAAS;GAAC;GAAc;GAAgB;EAAa;CACvD,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CACF;AAEA,MAAM,8BAA8B,IAAI;CAAC;CAAW;CAAmB;AAAc,GAAG;CACtF,UAAU,EACR,SAAS;EACP,SAAS,CAAC,YAAY,SAAS;EAC/B,SAAS,CAAC,YAAY,SAAS;CACjC,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CAAC;;;;;;;;;AAkBD,MAAM,kBAAkB,EAAE,WAAW,UAAU,WAAW,UAAU,GAAG,WACrE,oBAAC,OAAD;CAAK,MAAK;CAAS,WAAW,qBAAqB;EAAE;EAAW;CAAQ,CAAC;CAAG,GAAI;CAC7E;AACE,CAAA;AAKP,MAAM,kBAAkB,EAAE,WAAW,UAAU,WAAW,UAAU,GAAG,WACrE,oBAAC,OAAD;CAAK,WAAW,yBAAyB;EAAE;EAAW;CAAQ,CAAC;CAAG,GAAI;CACnE;AACE,CAAA;AAKP,MAAM,mBAAmB,EAAE,WAAW,UAAU,WAAW,UAAU,GAAG,WACtE,oBAAC,MAAD;CAAI,WAAW,0BAA0B;EAAE;EAAW;CAAQ,CAAC;CAAG,GAAI;CACnE;AACC,CAAA;AAKN,MAAM,yBAAyB,EAC7B,WACA,UAAU,WACV,UACA,GAAG,WAEH,oBAAC,KAAD;CAAG,WAAW,gCAAgC;EAAE;EAAW;CAAQ,CAAC;CAAG,GAAI;CACxE;AACA,CAAA;AAKL,MAAM,qBAAqB,EAAE,WAAW,UAAU,WAAW,UAAU,GAAG,WACxE,oBAAC,OAAD;CAAK,WAAW,4BAA4B;EAAE;EAAW;CAAQ,CAAC;CAAG,GAAI;CACtE;AACE,CAAA;AAGP,MAAa,aAAa;AAO1B,WAAW,OAAO;AAClB,WAAW,QAAQ;AACnB,WAAW,cAAc;AACzB,WAAW,UAAU"}
@@ -1 +1 @@
1
- export { PageLayout } from "../../PageLayout-LcvJccOW.js";
1
+ export { PageLayout } from "../../PageLayout-kY31oUix.js";