@photon-ai/pho-ui 1.4.0 → 2.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.
- package/dist/chunks/IconAlertCircleFilled-VxKU8TYK.js +11 -0
- package/dist/chunks/IconAlertCircleFilled-VxKU8TYK.js.map +1 -0
- package/dist/chunks/IconArrowUpRight-DGgKzQwV.js +14 -0
- package/dist/chunks/IconArrowUpRight-DGgKzQwV.js.map +1 -0
- package/dist/chunks/IconChevronLeft-CSWMKQ4C.js +11 -0
- package/dist/chunks/IconChevronLeft-CSWMKQ4C.js.map +1 -0
- package/dist/chunks/IconInfoCircle-L0zfhg7R.js +21 -0
- package/dist/chunks/IconInfoCircle-L0zfhg7R.js.map +1 -0
- package/dist/chunks/animated-height-DhNSac85.js +50 -0
- package/dist/chunks/animated-height-DhNSac85.js.map +1 -0
- package/dist/chunks/basic-page-D1zm81YS.js +481 -0
- package/dist/chunks/basic-page-D1zm81YS.js.map +1 -0
- package/dist/chunks/{close-button-B8gF5UNk.js → button-X5wsWvRa.js} +127 -147
- package/dist/chunks/button-X5wsWvRa.js.map +1 -0
- package/dist/chunks/close-button-xadxp0j8.js +29 -0
- package/dist/chunks/close-button-xadxp0j8.js.map +1 -0
- package/dist/chunks/combobox-rLdS6fl-.js +117 -0
- package/dist/chunks/combobox-rLdS6fl-.js.map +1 -0
- package/dist/chunks/dialog-Caze1vkf.js +252 -0
- package/dist/chunks/dialog-Caze1vkf.js.map +1 -0
- package/dist/chunks/error-DR6G2LmG.js +251 -0
- package/dist/chunks/error-DR6G2LmG.js.map +1 -0
- package/dist/chunks/{input-CxS7ndpb.js → input-D3XQcC4J.js} +29 -31
- package/dist/chunks/input-D3XQcC4J.js.map +1 -0
- package/dist/chunks/{menu-BSXds3Rt.js → menu-BC-9IP29.js} +39 -39
- package/dist/chunks/menu-BC-9IP29.js.map +1 -0
- package/dist/chunks/popover-EL1SE1kj.js +46 -0
- package/dist/chunks/popover-EL1SE1kj.js.map +1 -0
- package/dist/chunks/{sidebar-DGpEKxOn.js → sidebar-DDJC1MeD.js} +72 -64
- package/dist/chunks/sidebar-DDJC1MeD.js.map +1 -0
- package/dist/components/button.js +13 -12
- package/dist/components/combobox.js +2 -114
- package/dist/components/command.js +242 -0
- package/dist/components/command.js.map +1 -0
- package/dist/components/context-menu.js +1 -1
- package/dist/components/dialog.js +1 -1
- package/dist/components/drawer.js.map +1 -1
- package/dist/components/error.js +13 -0
- package/dist/components/input.js +1 -1
- package/dist/components/menu.js +1 -1
- package/dist/components/notification.js +27 -39
- package/dist/components/notification.js.map +1 -1
- package/dist/components/phone-input.js +17001 -0
- package/dist/components/phone-input.js.map +1 -0
- package/dist/components/popover.js +2 -43
- package/dist/components/toast.js.map +1 -1
- package/dist/index.js +62 -50
- package/dist/primitives.js +1 -1
- package/dist/sections/basic-page.js +1 -1
- package/dist/sections/sidebar.js +1 -1
- package/dist/src/components/command/command.d.ts +114 -0
- package/dist/src/components/command/index.d.ts +1 -0
- package/dist/src/components/dialog/dialog.d.ts +89 -1
- package/dist/src/components/drawer/drawer.d.ts +2 -2
- package/dist/src/components/error/error.d.ts +56 -0
- package/dist/src/components/error/index.d.ts +2 -0
- package/dist/src/components/error/problem.d.ts +80 -0
- package/dist/src/components/notification/notification.d.ts +1 -1
- package/dist/src/components/phone-input/country-alpha3.d.ts +250 -0
- package/dist/src/components/phone-input/country-search.d.ts +8 -0
- package/dist/src/components/phone-input/index.d.ts +1 -0
- package/dist/src/components/phone-input/phone-input.d.ts +47 -0
- package/dist/src/components/toast/toast.d.ts +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/sections/basic-page/basic-page.d.ts +165 -45
- package/dist/src/sections/sidebar/sidebar.d.ts +8 -3
- package/dist/src/utils/animated-height.d.ts +13 -0
- package/package.json +16 -5
- package/src/styles/theme.css +27 -0
- package/dist/chunks/basic-page-4_GZOvRr.js +0 -255
- package/dist/chunks/basic-page-4_GZOvRr.js.map +0 -1
- package/dist/chunks/close-button-B8gF5UNk.js.map +0 -1
- package/dist/chunks/dialog-Ba0UUE5g.js +0 -155
- package/dist/chunks/dialog-Ba0UUE5g.js.map +0 -1
- package/dist/chunks/input-CxS7ndpb.js.map +0 -1
- package/dist/chunks/menu-BSXds3Rt.js.map +0 -1
- package/dist/chunks/sidebar-DGpEKxOn.js.map +0 -1
- package/dist/components/alert-dialog.js +0 -59
- package/dist/components/alert-dialog.js.map +0 -1
- package/dist/components/combobox.js.map +0 -1
- package/dist/components/popover.js.map +0 -1
- package/dist/src/components/alert-dialog/alert-dialog.d.ts +0 -41
- package/dist/src/components/alert-dialog/index.d.ts +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button-X5wsWvRa.js","names":[],"sources":["../../src/components/button/button.tsx"],"sourcesContent":["import {\n isValidElement,\n useEffect,\n useMemo,\n useRef,\n useState,\n type AnchorHTMLAttributes,\n type ButtonHTMLAttributes,\n type ComponentType,\n type FC,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n type Ref,\n} from \"react\";\nimport { motion, useReducedMotion } from \"motion/react\";\nimport { cn } from \"../../utils/cn\";\nimport { resolveVariant, type VariantMap } from \"../../utils/resolve-variant\";\nimport { isReactComponent } from \"../../utils/is-react-component\";\nimport { useLinkComponent } from \"../../utils/link-provider\";\nimport { Spinner } from \"../spinner/spinner\";\n\n/**\n * Design notes:\n * - TWO visual axes: `variant` is the surface (filled / outlined / ghost /\n * effect) and `color` is the semantic ink (default / destructive). Dialog\n * confirms use the default `effect`; danger-zone triggers are `ghost` +\n * `destructive`. `effect` is the marketing pill: same-hue 1.5px outer rim\n * plus inset sheen that springs on hover.\n * - `iconReveal` is a separate boolean: on hover, prefix/suffix icons spring\n * in from collapsed — works with any variant, independent of `effect`.\n * - Press scale (Motion `whileTap` → 0.97) is shared by every variant; only\n * `effect` also springs its inset sheen on hover/press, and replays a\n * one-shot sheen glint when it leaves `disabled`/`loading` (wake).\n * - THREE sizes (`sm` / `md` / `lg`, default `md`). No `xs` / `xl`.\n * - `prefix` / `suffix` are generic slots (icon, spinner, count…), not\n * icon-only props. `svgOnly` makes an icon button and *requires* an\n * `aria-label`. `loading` is declarative. Effect’s rim/sheen are\n * box-shadow layers (not layout `border`).\n * - Navigation belongs to `ButtonLink`; an inline text link is an anchor.\n */\n\nconst COMMON_ROOT = cn(\n // Transition colors/shadows in CSS; transform (press scale) is owned by Motion.\n \"group relative inline-flex h-max cursor-pointer items-center justify-center whitespace-nowrap outline-pho-brand transition-[color,background-color,border-color,opacity,box-shadow,outline-color] duration-100 ease-linear focus-visible:outline-2 focus-visible:outline-offset-2\",\n // Disabled (native `disabled` on <button>, `aria-disabled` on links).\n \"disabled:cursor-not-allowed disabled:opacity-50 aria-disabled:cursor-not-allowed aria-disabled:opacity-50 aria-disabled:pointer-events-none\",\n);\n\n/**\n * Size axis — padding, text size, and icon-only (svgOnly) padding.\n *\n * Icon-side tuck (LiftKit-derived optical correction): a side that carries an\n * icon gets its padding divided by the golden ratio — an icon's rounded form\n * brings its own whitespace, so the full text-edge padding reads as a hole.\n * LiftKit: `--button-padX-sideWithIcon: calc(font-size / 1.618)`. Applied to\n * Pho's paddings: sm 14px/φ ≈ 8px · md 16px/φ ≈ 10px · lg 20px/φ ≈ 12px,\n * selected structurally via `:has()` on the slot markers (`data-icon` is\n * `prefix`, `suffix`, or `loading` — the spinner is an icon too).\n */\nexport const BUTTON_SIZES = {\n sm: {\n classes: cn(\n \"gap-1 px-3.5 py-1.5 text-base font-medium data-svg-only:p-2\",\n \"has-[[data-icon=prefix]]:pl-2 has-[[data-icon=loading]]:pl-2 has-[[data-icon=suffix]]:pr-2\",\n ),\n description: \"Small — compact rows, tables, and toolbars\",\n },\n md: {\n classes: cn(\n \"gap-1 px-4 py-2 text-base font-medium data-svg-only:p-2.5\",\n \"has-[[data-icon=prefix]]:pl-2.5 has-[[data-icon=loading]]:pl-2.5 has-[[data-icon=suffix]]:pr-2.5\",\n ),\n description: \"Medium — the default\",\n },\n lg: {\n classes: cn(\n \"gap-1.5 px-5 py-2.5 text-md font-medium data-svg-only:p-3\",\n \"has-[[data-icon=prefix]]:pl-3 has-[[data-icon=loading]]:pl-3 has-[[data-icon=suffix]]:pr-3\",\n ),\n description: \"Large — prominent and marketing actions\",\n },\n} satisfies VariantMap;\n\n/** Shape axis — corner treatment. Pills are the photon.codes default. */\nexport const BUTTON_SHAPES = {\n rounded: {\n classes: \"rounded-full\",\n description: \"Pill — the default; every button on photon.codes\",\n },\n square: {\n classes: \"rounded-base\",\n description: \"Gently rounded corners for dense app chrome\",\n },\n circle: {\n classes: \"rounded-full\",\n description: \"Circular — pair with svgOnly for round icon buttons\",\n },\n} satisfies VariantMap;\n\n/**\n * At `lg`, square buttons add squircle smoothing on top of `rounded-base`\n * (12px) — the same treatment as Input `lg`, so 44px buttons and fields share\n * a corner language. 12/44 ≈ 0.272 — LiftKit's half-step decimal (√φ − 1).\n */\nconst SQUARE_LG_RADIUS = \"squircle\";\n\n/**\n * Optical pad for `effect`: the 1.5px outer rim is a box-shadow (no layout\n * cost), so without this the painted height reads ~3px taller than filled /\n * outlined / ghost. Subtract 1.5px from each side so fill+rim matches siblings.\n */\nconst EFFECT_OPTICAL_PAD: Record<ButtonSize, string> = {\n sm: \"py-[4.5px] data-svg-only:p-[6.5px]\",\n md: \"py-[6.5px] data-svg-only:p-[8.5px]\",\n lg: \"py-[8.5px] data-svg-only:p-[10.5px]\",\n};\n\n/** Surface axis — how the control is drawn. `effect` is the default. */\nexport const BUTTON_VARIANTS = {\n effect: {\n classes: \"\",\n description:\n \"Default — marketing pill with same-hue outer rim and inset sheen\",\n },\n filled: {\n classes: \"\",\n description: \"Solid fill without sheen\",\n },\n outlined: {\n classes: \"\",\n description: \"Hairline ring — supporting action\",\n },\n ghost: {\n classes: \"\",\n description: \"Borderless — quiet / inline action\",\n },\n} satisfies VariantMap;\n\n/** Color axis — semantic ink. `default` is the default. */\nexport const BUTTON_COLORS = {\n default: {\n classes: \"\",\n description: \"Neutral / brand contrast\",\n },\n destructive: {\n classes: \"\",\n description: \"Destructive intent (delete, discard)\",\n },\n} satisfies VariantMap;\n\n/**\n * Surface × color looks. Kept as a matrix so each cell can own its tokens\n * (filled destructive is solid red; ghost destructive is red text only).\n */\nconst BUTTON_LOOKS: Record<\n keyof typeof BUTTON_VARIANTS,\n Record<keyof typeof BUTTON_COLORS, string>\n> = {\n // Icons inherit the label ink (currentColor) — no separate opacity/tint.\n // The rim replicates photon.codes' Framer CTA border: 1.5px in the fill hue\n // at 62% alpha, reading as a soft same-hue edge (the site has NO outer\n // glow — verified against live computed styles). Sheen geometry is CSS\n // vars that Motion springs on hover (see Button). All edges are shadows —\n // never a layout `border` — so height stays paired with other variants.\n effect: {\n default: cn(\n \"squircle overflow-hidden bg-pho-brand-solid text-pho-on-brand transition-none\",\n \"hover:bg-pho-brand-solid data-loading:bg-pho-brand-solid\",\n \"[--pho-rim:color-mix(in_oklab,var(--background-color-pho-brand-solid)_62%,transparent)]\",\n \"[--pho-sheen:light-dark(rgba(255,255,255,0.5),rgba(0,0,0,0.12))]\",\n \"shadow-[0_0_0_1.5px_var(--pho-rim),inset_0_0_0_1px_var(--border-color-pho-on-brand),inset_0_var(--pho-sheen-y,0px)_var(--pho-sheen-blur,5px)_var(--pho-sheen-spread,2px)_var(--pho-sheen)]\",\n ),\n destructive: cn(\n \"squircle overflow-hidden bg-pho-error-solid text-white outline-pho-error transition-none\",\n \"hover:bg-pho-error-solid data-loading:bg-pho-error-solid\",\n \"[--pho-rim:color-mix(in_oklab,var(--background-color-pho-error-solid)_62%,transparent)]\",\n \"[--pho-sheen:light-dark(rgba(255,255,255,0.45),rgba(0,0,0,0.18))]\",\n \"shadow-[0_0_0_1.5px_var(--pho-rim),inset_0_0_0_1px_oklch(1_0_0/0.2),inset_0_var(--pho-sheen-y,0px)_var(--pho-sheen-blur,5px)_var(--pho-sheen-spread,2px)_var(--pho-sheen)]\",\n ),\n },\n filled: {\n default:\n \"bg-pho-brand-solid text-pho-on-brand hover:bg-pho-brand-solid-hover data-loading:bg-pho-brand-solid-hover\",\n destructive:\n \"bg-pho-error-solid text-white outline-pho-error hover:bg-pho-error-solid-hover data-loading:bg-pho-error-solid-hover\",\n },\n outlined: {\n default:\n // Rest hairline is the card stroke; hover climbs to primary ink so the\n // edge reads as black (white in dark), matching the label's hover lift.\n // The ring spans the full ladder, so ease it in gently — 200ms ease-out\n // approximates the effect variant's soft spring instead of base's\n // 100ms linear snap. Prefer the named `ring-pho-ink` token over an\n // arbitrary value so consumers' Tailwind scanners pick it up reliably.\n \"bg-pho-primary text-pho-secondary ring-1 ring-pho-secondary ring-inset duration-200 ease-out hover:bg-pho-primary-hover hover:text-pho-secondary-hover hover:ring-pho-ink data-loading:bg-pho-primary-hover\",\n destructive:\n \"bg-pho-primary text-pho-error outline-pho-error ring-1 ring-pho-error ring-inset duration-200 ease-out hover:bg-pho-error-primary hover:text-pho-error-hover data-loading:bg-pho-error-primary\",\n },\n ghost: {\n default:\n \"text-pho-secondary hover:bg-pho-ghost-hover hover:text-pho-secondary-hover data-loading:bg-pho-ghost-hover\",\n destructive:\n \"text-pho-error outline-pho-error hover:bg-pho-error-primary hover:text-pho-error-hover data-loading:bg-pho-error-primary\",\n },\n};\n\nexport type ButtonSize = keyof typeof BUTTON_SIZES;\nexport type ButtonShape = keyof typeof BUTTON_SHAPES;\nexport type ButtonVariant = keyof typeof BUTTON_VARIANTS;\nexport type ButtonColor = keyof typeof BUTTON_COLORS;\n\n/** Compose the full class string for a button — exported for reuse/testing. */\nexport function buttonVariants(opts?: {\n variant?: ButtonVariant;\n color?: ButtonColor;\n size?: ButtonSize;\n shape?: ButtonShape;\n className?: string;\n}): string {\n const {\n variant = \"effect\",\n color = \"default\",\n size = \"md\",\n shape: shapeOpt = \"rounded\",\n className,\n } = opts ?? {};\n // Effect pills are always fully rounded — shape is ignored.\n const shape = variant === \"effect\" ? \"rounded\" : shapeOpt;\n const look =\n BUTTON_LOOKS[variant as keyof typeof BUTTON_LOOKS]?.[\n color as keyof (typeof BUTTON_LOOKS)[\"effect\"]\n ] ?? \"\";\n return cn(\n COMMON_ROOT,\n resolveVariant(BUTTON_SHAPES, shape),\n shape === \"square\" && size === \"lg\" && SQUARE_LG_RADIUS,\n resolveVariant(BUTTON_SIZES, size),\n // Outer rim is a 1.5px box-shadow (no layout cost). Shrink padding by the\n // same amount so fill+rim paints at the same visual size as filled /\n // outlined / ghost siblings of the same `size`.\n variant === \"effect\" && EFFECT_OPTICAL_PAD[size],\n look,\n className,\n );\n}\n\n/** An icon/element slot rendered before or after the label. */\ntype Slottable = ReactNode | FC<{ className?: string }>;\n\ninterface ButtonBaseProps {\n /** Surface variant. @default \"effect\" */\n variant?: ButtonVariant;\n /** Semantic color. @default \"default\" */\n color?: ButtonColor;\n /** Size variant. @default \"md\" */\n size?: ButtonSize;\n /** Corner shape. @default \"rounded\" */\n shape?: ButtonShape;\n /** Slot before the label — a component (`Plus`) or element (`<Plus />`). */\n prefix?: Slottable;\n /** Slot after the label. */\n suffix?: Slottable;\n /**\n * Reveal prefix/suffix icons on hover — collapsed and invisible at rest,\n * spring in on hover. Independent of `variant` (including `effect`).\n * Ignored when `svgOnly`. @default false\n */\n iconReveal?: boolean;\n /** Render as an icon-only button. Requires an `aria-label`. */\n svgOnly?: boolean;\n /** Show a spinner and block interaction while staying readable. */\n loading?: boolean;\n children?: ReactNode;\n className?: string;\n}\n\n/**\n * DOM event handlers whose React signatures clash with Motion's gesture\n * props of the same name (Motion re-types these on `motion.*` elements).\n * Excluded from the public API — Button renders through Motion when the\n * sheen or icon reveal is active, so these handlers would be intercepted.\n */\ntype MotionHandlerConflicts =\n | \"onAnimationStart\"\n | \"onAnimationEnd\"\n | \"onAnimationIteration\"\n | \"onDrag\"\n | \"onDragStart\"\n | \"onDragEnd\"\n | \"onDragEnter\"\n | \"onDragExit\"\n | \"onDragLeave\"\n | \"onDragOver\"\n | \"onDrop\";\n\nexport interface ButtonProps\n extends\n ButtonBaseProps,\n Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n keyof ButtonBaseProps | MotionHandlerConflicts\n > {\n ref?: Ref<HTMLButtonElement>;\n}\n\nexport interface ButtonLinkProps\n extends\n ButtonBaseProps,\n Omit<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n keyof ButtonBaseProps | MotionHandlerConflicts\n > {\n /** Navigate to this URL (rendered via the host's `LinkProvider`). */\n href: string;\n /** Visually and semantically disable the link. */\n disabled?: boolean;\n}\n\nconst SLOT_CLASS =\n // Icons scale with the label: 1.125em tracks the button's font size\n // (16px icon beside 14px text, 18px beside 16px) so small buttons never\n // carry an oversized glyph.\n \"transition-inherit-all pointer-events-none inline-flex shrink-0 items-center [&>svg]:size-[1.125em] [&>svg]:shrink-0\";\n\nfunction Slot({\n position,\n children,\n}: {\n position: \"prefix\" | \"suffix\" | \"loading\";\n children: ReactNode;\n}) {\n return (\n <span data-icon={position} className={SLOT_CLASS}>\n {children}\n </span>\n );\n}\n\nfunction renderSlot(icon: Slottable, position: \"prefix\" | \"suffix\") {\n if (icon == null || icon === false) return null;\n if (isReactComponent(icon)) {\n const Icon = icon;\n return (\n <Slot position={position}>\n <Icon />\n </Slot>\n );\n }\n if (isValidElement(icon)) return <Slot position={position}>{icon}</Slot>;\n return null;\n}\n\nfunction warnMissingLabel(svgOnly: boolean | undefined, label: unknown) {\n if (\n svgOnly &&\n !label &&\n typeof process !== \"undefined\" &&\n process.env?.NODE_ENV !== \"production\"\n ) {\n console.warn(\n \"Button: `svgOnly` buttons require an `aria-label` that names the action.\",\n );\n }\n}\n\n/* ======================== Motion: sheen + icon reveal ======================== */\n\n/** Framer source transition: `spring-physics 200 30 0.1`. */\nconst BUTTON_SPRING = {\n type: \"spring\",\n stiffness: 200,\n damping: 30,\n mass: 0.1,\n} as const;\n\nconst EFFECT_SHEEN_REST = {\n \"--pho-sheen-y\": \"0px\",\n \"--pho-sheen-blur\": \"5px\",\n \"--pho-sheen-spread\": \"2px\",\n} as const;\n\n/** Per-size sheen hover targets. */\nconst EFFECT_SHEEN_HOVER = {\n sm: {\n \"--pho-sheen-y\": \"-3px\",\n \"--pho-sheen-blur\": \"8px\",\n \"--pho-sheen-spread\": \"2px\",\n },\n md: {\n \"--pho-sheen-y\": \"-3px\",\n \"--pho-sheen-blur\": \"8px\",\n \"--pho-sheen-spread\": \"2px\",\n },\n lg: {\n \"--pho-sheen-y\": \"-6px\",\n \"--pho-sheen-blur\": \"14px\",\n \"--pho-sheen-spread\": \"1px\",\n },\n} as const;\n\n/**\n * Per-size sheen press targets — the inverse gesture of hover: the light\n * drops back below the rest line and tightens while the pill compresses\n * slightly, so hover → press reads as \"lift, then push in\".\n */\nconst EFFECT_SHEEN_PRESS = {\n sm: {\n \"--pho-sheen-y\": \"1.5px\",\n \"--pho-sheen-blur\": \"4px\",\n \"--pho-sheen-spread\": \"1px\",\n },\n md: {\n \"--pho-sheen-y\": \"1.5px\",\n \"--pho-sheen-blur\": \"4px\",\n \"--pho-sheen-spread\": \"1px\",\n },\n lg: {\n \"--pho-sheen-y\": \"3px\",\n \"--pho-sheen-blur\": \"7px\",\n \"--pho-sheen-spread\": \"1px\",\n },\n} as const;\n\n/** Pill compression while pressed — subtle, transform-only; every variant. */\nconst BUTTON_PRESS_SCALE = 0.97;\n\n/**\n * One-shot \"wake\" glint when an effect pill re-enables (disabled / loading →\n * interactive). The keyframes replay the pill's own gesture in reverse: the\n * sheen starts from its pressed-in position (low, tight — the dormant read),\n * springs up past the hover line, and settles at rest. Shadow-only, so the\n * pill never moves or resizes next to its neighbours.\n */\nconst EFFECT_SHEEN_WAKE = {\n sm: {\n \"--pho-sheen-y\": [\"1.5px\", \"-4px\", \"0px\"],\n \"--pho-sheen-blur\": [\"4px\", \"9px\", \"5px\"],\n \"--pho-sheen-spread\": [\"1px\", \"2px\", \"2px\"],\n },\n md: {\n \"--pho-sheen-y\": [\"1.5px\", \"-4px\", \"0px\"],\n \"--pho-sheen-blur\": [\"4px\", \"9px\", \"5px\"],\n \"--pho-sheen-spread\": [\"1px\", \"2px\", \"2px\"],\n },\n lg: {\n \"--pho-sheen-y\": [\"3px\", \"-8px\", \"0px\"],\n \"--pho-sheen-blur\": [\"7px\", \"16px\", \"5px\"],\n \"--pho-sheen-spread\": [\"1px\", \"1px\", \"2px\"],\n },\n} as const;\n\n/**\n * Wake timing: a short delay lets the 100ms opacity fade land first, then a\n * quick rise (feedback) and a relaxed settle. Keyframes need a tween — the\n * shared spring only animates between two values.\n */\nconst WAKE_TRANSITION = {\n duration: 0.6,\n delay: 0.05,\n times: [0, 0.4, 1],\n ease: [\"easeOut\", \"easeInOut\"],\n} as const;\n\n/**\n * Fire the wake glint on the disabled/loading → enabled edge (never on\n * mount), skipped under reduced motion. `data-waking` mirrors the window so\n * tests and styling can observe it.\n */\nfunction useWakeOnEnable(inert: boolean, sheen: boolean) {\n const [waking, setWaking] = useState(false);\n const prevInert = useRef(inert);\n const reduceMotion = useReducedMotion();\n\n useEffect(() => {\n if (prevInert.current && !inert && sheen && !reduceMotion) {\n setWaking(true);\n } else if (inert) {\n setWaking(false);\n }\n prevInert.current = inert;\n }, [inert, sheen, reduceMotion]);\n\n return {\n waking,\n onWakeComplete: (definition: unknown) => {\n if (definition === \"wake\") setWaking(false);\n },\n };\n}\n\n/**\n * Icon reveal sizes — collapsed at rest, full on hover. `lg` matches the\n * Framer 20×21 source; `sm`/`md` scale with the 14px label.\n */\nconst ICON_REVEAL_VARIANTS = {\n sm: {\n rest: { opacity: 0, width: 1, height: 9 },\n hover: { opacity: 1, width: 17, height: 18 },\n },\n md: {\n rest: { opacity: 0, width: 1, height: 9 },\n hover: { opacity: 1, width: 17, height: 18 },\n },\n lg: {\n rest: { opacity: 0, width: 1, height: 10 },\n hover: { opacity: 1, width: 20, height: 21 },\n },\n} as const;\n\n/**\n * When icons are hidden at rest, undo Button's icon-side padding tuck so the\n * pill doesn't look lopsided. Same `:has()` keys as the tuck (later wins).\n */\nconst ICON_REVEAL_PAD_RESTORE: Record<ButtonSize, string> = {\n sm: \"has-[[data-icon=prefix]]:pl-3.5 has-[[data-icon=loading]]:pl-3.5 has-[[data-icon=suffix]]:pr-3.5\",\n md: \"has-[[data-icon=prefix]]:pl-4 has-[[data-icon=loading]]:pl-4 has-[[data-icon=suffix]]:pr-4\",\n lg: \"has-[[data-icon=prefix]]:pl-5 has-[[data-icon=loading]]:pl-5 has-[[data-icon=suffix]]:pr-5\",\n};\n\nfunction RevealSlot({\n position,\n size,\n children,\n}: {\n position: \"prefix\" | \"suffix\";\n size: ButtonSize;\n children: ReactNode;\n}) {\n return (\n <motion.span\n data-icon={position}\n variants={ICON_REVEAL_VARIANTS[size]}\n transition={BUTTON_SPRING}\n style={{\n display: \"inline-flex\",\n flex: \"none\",\n alignItems: \"center\",\n overflow: \"hidden\",\n }}\n className=\"pointer-events-none [&>svg]:block [&>svg]:size-full\"\n >\n {children}\n </motion.span>\n );\n}\n\nfunction wrapRevealIcon(\n icon: Slottable,\n position: \"prefix\" | \"suffix\",\n size: ButtonSize,\n): ReactNode | undefined {\n if (icon == null || icon === false) return undefined;\n if (isReactComponent(icon)) {\n const Icon = icon;\n return (\n <RevealSlot position={position} size={size}>\n <Icon />\n </RevealSlot>\n );\n }\n if (isValidElement(icon)) {\n return (\n <RevealSlot position={position} size={size}>\n {icon}\n </RevealSlot>\n );\n }\n return (\n <RevealSlot position={position} size={size}>\n {icon}\n </RevealSlot>\n );\n}\n\nfunction buttonInner({\n svgOnly,\n loading,\n prefix,\n suffix,\n children,\n iconReveal,\n size,\n}: Pick<\n ButtonBaseProps,\n | \"svgOnly\"\n | \"loading\"\n | \"prefix\"\n | \"suffix\"\n | \"children\"\n | \"iconReveal\"\n | \"size\"\n> & { size: ButtonSize }) {\n if (svgOnly) {\n return loading ? <Spinner /> : children;\n }\n const reveal = Boolean(iconReveal);\n return (\n <>\n {loading ? (\n <Slot position=\"loading\">\n <Spinner />\n </Slot>\n ) : reveal ? (\n wrapRevealIcon(prefix, \"prefix\", size)\n ) : (\n renderSlot(prefix, \"prefix\")\n )}\n {children != null && children !== false && (\n <span data-text className=\"transition-inherit-all px-0.5\">\n {children}\n </span>\n )}\n {reveal\n ? wrapRevealIcon(suffix, \"suffix\", size)\n : renderSlot(suffix, \"suffix\")}\n </>\n );\n}\n\n/**\n * Root Motion props — press scale on every variant; sheen + icon-reveal gap\n * only when those features are on. Press composes over hover (`whileTap` >\n * `whileHover`): effect sheen inverts while the pill compresses; other\n * variants get the same scale with no sheen change. `waking` plays the\n * one-shot re-enable glint; a real hover mid-glint takes over seamlessly.\n */\nfunction buttonRootMotionProps(\n size: ButtonSize,\n inert: boolean | undefined,\n opts: { sheen: boolean; iconReveal: boolean; waking?: boolean },\n) {\n const rest: Record<string, string | number> = {\n scale: 1,\n ...(opts.sheen ? EFFECT_SHEEN_REST : {}),\n };\n const hover: Record<string, string | number> = opts.sheen\n ? { ...EFFECT_SHEEN_HOVER[size] }\n : {};\n const press: Record<string, string | number> = {\n scale: BUTTON_PRESS_SCALE,\n ...(opts.sheen ? EFFECT_SHEEN_PRESS[size] : {}),\n };\n const wake = opts.sheen\n ? { ...EFFECT_SHEEN_WAKE[size], transition: WAKE_TRANSITION }\n : {};\n if (opts.iconReveal) {\n // Collapse gap at rest so the hidden icon leaves no hole; lg eases open.\n rest.gap = 0;\n hover.gap = size === \"lg\" ? 4 : 0;\n }\n return {\n initial: false as const,\n animate: opts.waking && opts.sheen ? \"wake\" : \"rest\",\n whileHover: inert ? undefined : \"hover\",\n whileTap: inert ? undefined : \"press\",\n variants: { rest, hover, press, wake },\n transition: BUTTON_SPRING,\n };\n}\n\nfunction buttonClassName({\n variant,\n color,\n size,\n shape,\n loading,\n svgOnly,\n className,\n}: {\n variant?: ButtonVariant;\n color?: ButtonColor;\n size?: ButtonSize;\n shape?: ButtonShape;\n loading?: boolean;\n svgOnly?: boolean;\n className?: string;\n}) {\n return cn(\n buttonVariants({ variant, color, size, shape }),\n loading && \"pointer-events-none\",\n svgOnly && \"[&>svg]:size-[1.25em] [&>svg]:shrink-0\",\n className,\n );\n}\n\n/**\n * Button — triggers an action that mutates state (submit, save, delete).\n * For navigation that changes the URL, use {@link ButtonLink}.\n *\n * Default surface is `effect` (same-hue 1.5px outer rim + inset sheen). Use\n * `filled` for a solid fill without those layers. `iconReveal` springs\n * prefix/suffix icons in on hover — independent of variant.\n */\nexport function Button({\n variant = \"effect\",\n color,\n size = \"md\",\n shape,\n prefix,\n suffix,\n iconReveal = false,\n svgOnly,\n loading,\n children,\n className,\n ref,\n ...props\n}: ButtonProps) {\n warnMissingLabel(svgOnly, props[\"aria-label\"]);\n const sheen = variant === \"effect\";\n const reveal = iconReveal && !svgOnly;\n const inert = Boolean(props.disabled || loading);\n const { waking, onWakeComplete } = useWakeOnEnable(inert, sheen);\n const cls = buttonClassName({\n variant,\n color,\n size,\n shape,\n loading,\n svgOnly,\n className: cn(reveal && ICON_REVEAL_PAD_RESTORE[size], className),\n });\n const inner = buttonInner({\n svgOnly,\n loading,\n prefix,\n suffix,\n children,\n iconReveal: reveal,\n size,\n });\n\n return (\n <motion.button\n ref={ref}\n type=\"button\"\n {...buttonRootMotionProps(size, inert, {\n sheen,\n iconReveal: reveal,\n waking,\n })}\n onAnimationComplete={onWakeComplete}\n {...props}\n aria-busy={loading || undefined}\n data-loading={loading ? \"true\" : undefined}\n data-svg-only={svgOnly ? \"true\" : undefined}\n data-waking={waking || undefined}\n className={cls}\n >\n {inner}\n </motion.button>\n );\n}\n\nButton.displayName = \"Button\";\n\n/**\n * ButtonLink — a link styled as a button, for navigation that changes the URL.\n * Shares every visual prop with {@link Button}; renders the host router's link\n * via `LinkProvider`.\n */\nexport function ButtonLink({\n variant = \"effect\",\n color,\n size = \"md\",\n shape,\n prefix,\n suffix,\n iconReveal = false,\n svgOnly,\n loading,\n disabled,\n href,\n children,\n className,\n ...props\n}: ButtonLinkProps) {\n warnMissingLabel(svgOnly, props[\"aria-label\"]);\n const Link = useLinkComponent();\n const sheen = variant === \"effect\";\n const reveal = iconReveal && !svgOnly;\n const cls = buttonClassName({\n variant,\n color,\n size,\n shape,\n loading,\n svgOnly,\n className: cn(reveal && ICON_REVEAL_PAD_RESTORE[size], className),\n });\n const inner = buttonInner({\n svgOnly,\n loading,\n prefix,\n suffix,\n children,\n iconReveal: reveal,\n size,\n });\n // Hooks must run unconditionally — only used when Motion is needed.\n const MotionLink = useMemo(\n // LinkProvider requires `href`; motion.create needs an open prop record —\n // bridge the two through `unknown` (props are supplied at the call site).\n () =>\n motion.create(Link as unknown as ComponentType<Record<string, unknown>>),\n [Link],\n );\n\n const inert = Boolean(disabled || loading);\n const { waking, onWakeComplete } = useWakeOnEnable(inert, sheen);\n const shared = {\n ...props,\n ...(inert ? {} : { href }),\n \"aria-disabled\": inert || undefined,\n \"aria-busy\": loading || undefined,\n \"data-loading\": loading ? (\"true\" as const) : undefined,\n \"data-svg-only\": svgOnly ? (\"true\" as const) : undefined,\n className: cls,\n tabIndex: inert ? -1 : props.tabIndex,\n onClick: inert\n ? (event: ReactMouseEvent<HTMLAnchorElement>) => {\n event.preventDefault();\n }\n : props.onClick,\n };\n\n if (inert) {\n return <span {...shared}>{inner}</span>;\n }\n\n return (\n <MotionLink\n {...buttonRootMotionProps(size, inert, {\n sheen,\n iconReveal: reveal,\n waking,\n })}\n onAnimationComplete={onWakeComplete}\n data-waking={waking || undefined}\n {...shared}\n >\n {inner}\n </MotionLink>\n );\n}\n\nButtonLink.displayName = \"ButtonLink\";\n\n/* ======================= EffectButton (compat alias) ======================= */\n\nexport const EFFECT_BUTTON_SIZES = BUTTON_SIZES;\nexport type EffectButtonSize = ButtonSize;\n\n/** Compose classes for an effect pill — `Button` with `variant=\"effect\"`. */\nexport function effectButtonVariants(opts?: {\n size?: EffectButtonSize;\n fullWidth?: boolean;\n className?: string;\n}): string {\n const { size = \"md\", fullWidth, className } = opts ?? {};\n return buttonVariants({\n variant: \"effect\",\n size,\n className: cn(fullWidth && \"w-full\", className),\n });\n}\n\n/**\n * Legacy EffectButton also reserved `style` (sheen variables lived there) and\n * never exposed the HTML `color` attribute — Button's semantic `color` prop\n * now occupies that name.\n */\ntype MotionConflicts = MotionHandlerConflicts | \"style\" | \"color\";\n\ninterface EffectButtonBaseProps {\n /** Size variant — Button's scale (32 / 36 / 44px). @default \"md\" */\n size?: EffectButtonSize;\n /** Stretch to the container's full width (stacked login / OAuth pills). */\n fullWidth?: boolean;\n /**\n * @deprecated Use `iconReveal` on `Button` instead. Mapped to `iconReveal`\n * when set.\n */\n animated?: boolean;\n /** @see ButtonBaseProps.iconReveal */\n iconReveal?: boolean;\n prefix?: Slottable;\n suffix?: Slottable;\n svgOnly?: boolean;\n loading?: boolean;\n children?: ReactNode;\n className?: string;\n}\n\nexport interface EffectButtonProps\n extends\n EffectButtonBaseProps,\n Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n keyof EffectButtonBaseProps | MotionConflicts\n > {\n ref?: Ref<HTMLButtonElement>;\n}\n\nexport interface EffectButtonLinkProps\n extends\n EffectButtonBaseProps,\n Omit<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n keyof EffectButtonBaseProps | MotionConflicts\n > {\n href: string;\n disabled?: boolean;\n}\n\n/**\n * @deprecated Prefer `<Button variant=\"effect\">`. Thin alias that forwards to\n * Button with the sheen surface (no icon reveal).\n */\nexport function EffectButton({\n size = \"md\",\n fullWidth,\n animated,\n iconReveal,\n className,\n ...props\n}: EffectButtonProps) {\n return (\n <Button\n variant=\"effect\"\n size={size}\n iconReveal={iconReveal ?? animated ?? true}\n className={cn(fullWidth && \"w-full\", className)}\n {...props}\n />\n );\n}\n\nEffectButton.displayName = \"EffectButton\";\n\n/**\n * @deprecated Prefer `<ButtonLink variant=\"effect\">`.\n */\nexport function EffectButtonLink({\n size = \"md\",\n fullWidth,\n animated,\n iconReveal,\n className,\n ...props\n}: EffectButtonLinkProps) {\n return (\n <ButtonLink\n variant=\"effect\"\n size={size}\n iconReveal={iconReveal ?? animated ?? true}\n className={cn(fullWidth && \"w-full\", className)}\n {...props}\n />\n );\n}\n\nEffectButtonLink.displayName = \"EffectButtonLink\";\n"],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as r } from "./cn-DTiB6ek_.js";
|
|
3
|
+
import { t as n } from "./resolve-variant-CcD8iG5l.js";
|
|
4
|
+
import { t as a } from "./IconX-pZ9vrtSr.js";
|
|
5
|
+
import "react";
|
|
6
|
+
import { jsx as e } from "react/jsx-runtime";
|
|
7
|
+
var l = {
|
|
8
|
+
sm: { classes: "size-9 rounded-base *:size-5" },
|
|
9
|
+
md: { classes: "size-10 rounded-base *:size-5" },
|
|
10
|
+
lg: { classes: "size-11 rounded-base *:size-6" }
|
|
11
|
+
};
|
|
12
|
+
function u({ size: s = "sm", label: o, className: t, ...i }) {
|
|
13
|
+
return /* @__PURE__ */ e("button", {
|
|
14
|
+
type: "button",
|
|
15
|
+
"aria-label": o || "Close",
|
|
16
|
+
...i,
|
|
17
|
+
className: r("squircle text-pho-secondary outline-pho-brand hover:bg-pho-ghost-hover hover:text-pho-secondary-hover inline-flex cursor-pointer items-center justify-center p-2 transition duration-100 ease-linear focus-visible:outline-2 focus-visible:outline-offset-2", n(l, s), t),
|
|
18
|
+
children: /* @__PURE__ */ e(a, {
|
|
19
|
+
"aria-hidden": "true",
|
|
20
|
+
className: "transition-inherit-all shrink-0"
|
|
21
|
+
})
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
u.displayName = "CloseButton";
|
|
25
|
+
export {
|
|
26
|
+
u as t
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=close-button-xadxp0j8.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"close-button-xadxp0j8.js","names":[],"sources":["../../src/components/button/close-button.tsx"],"sourcesContent":["import { type ButtonHTMLAttributes } from \"react\";\nimport { IconX } from \"@tabler/icons-react\";\nimport { cn } from \"../../utils/cn\";\nimport { resolveVariant, type VariantMap } from \"../../utils/resolve-variant\";\n\n// `rounded-base` (12px) at every size; base classes already apply squircle.\nconst CLOSE_SIZES = {\n sm: { classes: \"size-9 rounded-base *:size-5\" },\n md: { classes: \"size-10 rounded-base *:size-5\" },\n lg: { classes: \"size-11 rounded-base *:size-6\" },\n} satisfies VariantMap;\n\nexport interface CloseButtonProps extends Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n \"color\"\n> {\n /** Size variant. @default \"sm\" */\n size?: keyof typeof CLOSE_SIZES;\n /** Accessible label. @default \"Close\" */\n label?: string;\n}\n\n/**\n * Icon-only dismiss control — a squircle chip that fills on hover. Adapts to\n * light/dark automatically via semantic tokens. Used by Dialog and dismissible\n * surfaces.\n */\nexport function CloseButton({\n size = \"sm\",\n label,\n className,\n ...props\n}: CloseButtonProps) {\n return (\n <button\n type=\"button\"\n aria-label={label || \"Close\"}\n {...props}\n className={cn(\n \"squircle text-pho-secondary outline-pho-brand hover:bg-pho-ghost-hover hover:text-pho-secondary-hover inline-flex cursor-pointer items-center justify-center p-2 transition duration-100 ease-linear focus-visible:outline-2 focus-visible:outline-offset-2\",\n resolveVariant(CLOSE_SIZES, size),\n className,\n )}\n >\n <IconX aria-hidden=\"true\" className=\"transition-inherit-all shrink-0\" />\n </button>\n );\n}\n\nCloseButton.displayName = \"CloseButton\";\n"],"mappings":";;;;;;AAMA,IAAM,IAAc;AAAA,EAClB,IAAI,EAAE,SAAS,+BAA+B;AAAA,EAC9C,IAAI,EAAE,SAAS,gCAAgC;AAAA,EAC/C,IAAI,EAAE,SAAS,gCAAgC;AACjD;AAiBA,SAAgB,EAAY,EAC1B,MAAA,IAAO,MACP,OAAA,GACA,WAAA,GACA,GAAG,EAAA,GACgB;AACnB,SACE,gBAAA,EAAC,UAAD;AAAA,IACE,MAAK;AAAA,IACL,cAAY,KAAS;AAAA,IACrB,GAAI;AAAA,IACJ,WAAW,EACT,+PACA,EAAe,GAAa,CAAI,GAChC,CACF;AAAA,cAEA,gBAAA,EAAC,GAAD;AAAA,MAAO,eAAY;AAAA,MAAO,WAAU;AAAA,IAAmC,CAAA;AAAA,EACjE,CAAA;AAEZ;AAEA,EAAY,cAAc"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as o } from "./cn-DTiB6ek_.js";
|
|
3
|
+
import "react";
|
|
4
|
+
import { jsx as n } from "react/jsx-runtime";
|
|
5
|
+
import { Combobox as r } from "@base-ui/react/combobox";
|
|
6
|
+
var i = r.Root, s = r.Value, p = r.Portal, c = r.Group, l = r.Collection;
|
|
7
|
+
function h({ className: e, ...t }) {
|
|
8
|
+
return /* @__PURE__ */ n(r.InputGroup, {
|
|
9
|
+
className: o("relative flex items-center", e),
|
|
10
|
+
...t
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function u({ className: e, ...t }) {
|
|
14
|
+
return /* @__PURE__ */ n(r.Input, {
|
|
15
|
+
className: o("bg-pho-primary ring-pho-primary text-pho-primary placeholder:text-pho-placeholder focus-visible:ring-pho-brand text-md rounded-base w-full px-3 py-2 ring-1 transition-shadow duration-100 ease-linear outline-none ring-inset focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-base", e),
|
|
16
|
+
...t
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function d({ className: e, ...t }) {
|
|
20
|
+
return /* @__PURE__ */ n(r.Clear, {
|
|
21
|
+
className: o("combobox-clear text-pho-secondary hover:text-pho-secondary-hover absolute right-2.5 flex cursor-pointer items-center [&>svg]:size-4", e),
|
|
22
|
+
...t
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function m({ className: e, ...t }) {
|
|
26
|
+
return /* @__PURE__ */ n(r.Trigger, {
|
|
27
|
+
className: o("text-pho-secondary hover:text-pho-secondary-hover absolute right-2.5 flex cursor-pointer items-center [&>svg]:size-4", e),
|
|
28
|
+
...t
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function g({ className: e, sideOffset: t = 6, ...a }) {
|
|
32
|
+
return /* @__PURE__ */ n(r.Positioner, {
|
|
33
|
+
sideOffset: t,
|
|
34
|
+
className: o("z-50 outline-none", e),
|
|
35
|
+
...a
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function x({ className: e, ...t }) {
|
|
39
|
+
return /* @__PURE__ */ n(r.Popup, {
|
|
40
|
+
className: o("bg-pho-primary text-pho-primary shadow-pho-lg ring-pho-secondary rounded-base w-[var(--anchor-width)] max-w-[var(--available-width)] origin-[var(--transform-origin)] p-1 ring-1 transition-[transform,opacity] duration-150 ease-out outline-none ring-inset", "data-[starting-style]:scale-95 data-[starting-style]:opacity-0", "data-[ending-style]:scale-95 data-[ending-style]:opacity-0", e),
|
|
41
|
+
...t
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function y({ className: e, ...t }) {
|
|
45
|
+
return /* @__PURE__ */ n(r.List, {
|
|
46
|
+
className: o("max-h-[min(20rem,var(--available-height))] overflow-y-auto overscroll-contain", e),
|
|
47
|
+
...t
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function f({ className: e, ...t }) {
|
|
51
|
+
return /* @__PURE__ */ n(r.Empty, {
|
|
52
|
+
className: o("text-pho-description px-2.5 py-6 text-center text-base empty:m-0 empty:p-0", e),
|
|
53
|
+
...t
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function v({ className: e, ...t }) {
|
|
57
|
+
return /* @__PURE__ */ n(r.Item, {
|
|
58
|
+
className: o("text-pho-secondary grid cursor-pointer grid-cols-[1rem_1fr] items-center gap-2 rounded-[calc(var(--radius-base)-4px)] py-1.5 pr-2.5 pl-2 text-base outline-none select-none", "data-[highlighted]:bg-pho-ghost-hover data-[highlighted]:text-pho-primary", e),
|
|
59
|
+
...t
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function b({ className: e, ...t }) {
|
|
63
|
+
return /* @__PURE__ */ n(r.ItemIndicator, {
|
|
64
|
+
className: o("text-pho-brand col-start-1 flex items-center [&>svg]:size-4", e),
|
|
65
|
+
...t
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function N({ className: e, ...t }) {
|
|
69
|
+
return /* @__PURE__ */ n(r.GroupLabel, {
|
|
70
|
+
className: o("text-pho-secondary px-2.5 py-1.5 text-xs font-medium", e),
|
|
71
|
+
...t
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function w({ className: e, ...t }) {
|
|
75
|
+
return /* @__PURE__ */ n(r.Chips, {
|
|
76
|
+
className: o("bg-pho-primary ring-pho-primary focus-within:ring-pho-brand rounded-base flex flex-wrap items-center gap-1.5 p-1.5 ring-1 ring-inset focus-within:ring-2", e),
|
|
77
|
+
...t
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function C({ className: e, ...t }) {
|
|
81
|
+
return /* @__PURE__ */ n(r.Chip, {
|
|
82
|
+
className: o("bg-pho-secondary text-pho-secondary data-[highlighted]:bg-pho-inverse data-[highlighted]:text-pho-inverse flex items-center gap-1 rounded-sm py-0.5 pr-1 pl-2 text-base", e),
|
|
83
|
+
...t
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function I({ className: e, ...t }) {
|
|
87
|
+
return /* @__PURE__ */ n(r.ChipRemove, {
|
|
88
|
+
className: o("text-pho-secondary hover:text-pho-secondary-hover in-data-[highlighted]:text-pho-inverse flex cursor-pointer items-center rounded-sm [&>svg]:size-3.5", e),
|
|
89
|
+
...t
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
var R = {
|
|
93
|
+
Root: i,
|
|
94
|
+
Value: s,
|
|
95
|
+
InputGroup: h,
|
|
96
|
+
Input: u,
|
|
97
|
+
Trigger: m,
|
|
98
|
+
Clear: d,
|
|
99
|
+
Portal: p,
|
|
100
|
+
Positioner: g,
|
|
101
|
+
Popup: x,
|
|
102
|
+
List: y,
|
|
103
|
+
Collection: l,
|
|
104
|
+
Empty: f,
|
|
105
|
+
Item: v,
|
|
106
|
+
ItemIndicator: b,
|
|
107
|
+
Group: c,
|
|
108
|
+
GroupLabel: N,
|
|
109
|
+
Chips: w,
|
|
110
|
+
Chip: C,
|
|
111
|
+
ChipRemove: I
|
|
112
|
+
};
|
|
113
|
+
export {
|
|
114
|
+
R as t
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
//# sourceMappingURL=combobox-rLdS6fl-.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combobox-rLdS6fl-.js","names":[],"sources":["../../src/components/combobox/combobox.tsx"],"sourcesContent":["import { type ComponentProps, type ElementType } from \"react\";\nimport { Combobox as BaseCombobox } from \"@base-ui/react/combobox\";\nimport { cn } from \"../../utils/cn\";\n\n/** Override Base UI's `string | (state) => string` className with plain string. */\ntype StyledProps<T extends ElementType> = Omit<\n ComponentProps<T>,\n \"className\"\n> & {\n className?: string;\n};\n\nconst Root = BaseCombobox.Root;\nconst Value = BaseCombobox.Value;\nconst Portal = BaseCombobox.Portal;\nconst Group = BaseCombobox.Group;\nconst Collection = BaseCombobox.Collection;\n\nfunction InputGroup({\n className,\n ...props\n}: StyledProps<typeof BaseCombobox.InputGroup>) {\n return (\n <BaseCombobox.InputGroup\n className={cn(\"relative flex items-center\", className)}\n {...props}\n />\n );\n}\n\nfunction Input({\n className,\n ...props\n}: StyledProps<typeof BaseCombobox.Input>) {\n return (\n <BaseCombobox.Input\n className={cn(\n // text-md on small viewports — iOS zooms into fields under 16px.\n \"bg-pho-primary ring-pho-primary text-pho-primary placeholder:text-pho-placeholder focus-visible:ring-pho-brand text-md rounded-base w-full px-3 py-2 ring-1 transition-shadow duration-100 ease-linear outline-none ring-inset focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-base\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Clear({\n className,\n ...props\n}: StyledProps<typeof BaseCombobox.Clear>) {\n return (\n <BaseCombobox.Clear\n className={cn(\n \"combobox-clear text-pho-secondary hover:text-pho-secondary-hover absolute right-2.5 flex cursor-pointer items-center [&>svg]:size-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Trigger({\n className,\n ...props\n}: StyledProps<typeof BaseCombobox.Trigger>) {\n return (\n <BaseCombobox.Trigger\n className={cn(\n \"text-pho-secondary hover:text-pho-secondary-hover absolute right-2.5 flex cursor-pointer items-center [&>svg]:size-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Positioner({\n className,\n sideOffset = 6,\n ...props\n}: StyledProps<typeof BaseCombobox.Positioner>) {\n return (\n <BaseCombobox.Positioner\n sideOffset={sideOffset}\n className={cn(\"z-50 outline-none\", className)}\n {...props}\n />\n );\n}\n\nfunction Popup({\n className,\n ...props\n}: StyledProps<typeof BaseCombobox.Popup>) {\n return (\n <BaseCombobox.Popup\n className={cn(\n \"bg-pho-primary text-pho-primary shadow-pho-lg ring-pho-secondary rounded-base w-[var(--anchor-width)] max-w-[var(--available-width)] origin-[var(--transform-origin)] p-1 ring-1 transition-[transform,opacity] duration-150 ease-out outline-none ring-inset\",\n \"data-[starting-style]:scale-95 data-[starting-style]:opacity-0\",\n \"data-[ending-style]:scale-95 data-[ending-style]:opacity-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction List({ className, ...props }: StyledProps<typeof BaseCombobox.List>) {\n return (\n <BaseCombobox.List\n className={cn(\n \"max-h-[min(20rem,var(--available-height))] overflow-y-auto overscroll-contain\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Empty({\n className,\n ...props\n}: StyledProps<typeof BaseCombobox.Empty>) {\n return (\n <BaseCombobox.Empty\n className={cn(\n \"text-pho-description px-2.5 py-6 text-center text-base empty:m-0 empty:p-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Item({ className, ...props }: StyledProps<typeof BaseCombobox.Item>) {\n return (\n <BaseCombobox.Item\n className={cn(\n \"text-pho-secondary grid cursor-pointer grid-cols-[1rem_1fr] items-center gap-2 rounded-[calc(var(--radius-base)-4px)] py-1.5 pr-2.5 pl-2 text-base outline-none select-none\",\n \"data-[highlighted]:bg-pho-ghost-hover data-[highlighted]:text-pho-primary\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ItemIndicator({\n className,\n ...props\n}: StyledProps<typeof BaseCombobox.ItemIndicator>) {\n return (\n <BaseCombobox.ItemIndicator\n className={cn(\n \"text-pho-brand col-start-1 flex items-center [&>svg]:size-4\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction GroupLabel({\n className,\n ...props\n}: StyledProps<typeof BaseCombobox.GroupLabel>) {\n return (\n <BaseCombobox.GroupLabel\n className={cn(\n \"text-pho-secondary px-2.5 py-1.5 text-xs font-medium\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Chips({\n className,\n ...props\n}: StyledProps<typeof BaseCombobox.Chips>) {\n return (\n <BaseCombobox.Chips\n className={cn(\n \"bg-pho-primary ring-pho-primary focus-within:ring-pho-brand rounded-base flex flex-wrap items-center gap-1.5 p-1.5 ring-1 ring-inset focus-within:ring-2\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Chip({ className, ...props }: StyledProps<typeof BaseCombobox.Chip>) {\n return (\n <BaseCombobox.Chip\n className={cn(\n // Keyboard-highlighted chip flips to the inverse chip surface.\n \"bg-pho-secondary text-pho-secondary data-[highlighted]:bg-pho-inverse data-[highlighted]:text-pho-inverse flex items-center gap-1 rounded-sm py-0.5 pr-1 pl-2 text-base\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ChipRemove({\n className,\n ...props\n}: StyledProps<typeof BaseCombobox.ChipRemove>) {\n return (\n <BaseCombobox.ChipRemove\n className={cn(\n \"text-pho-secondary hover:text-pho-secondary-hover in-data-[highlighted]:text-pho-inverse flex cursor-pointer items-center rounded-sm [&>svg]:size-3.5\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Combobox built on Base UI `Combobox` — a text input that filters a list as\n * you type and commits to a value from it. Pass `items` to `Combobox.Root`;\n * `Combobox.List` takes a render function mapping each (filtered) item to a\n * `Combobox.Item`. Add `Combobox.Chips` for multi-select. For free-form text\n * with suggestions, use `Autocomplete`; for a small fixed set, use `Select`.\n */\nexport const Combobox = {\n Root,\n Value,\n InputGroup,\n Input,\n Trigger,\n Clear,\n Portal,\n Positioner,\n Popup,\n List,\n Collection,\n Empty,\n Item,\n ItemIndicator,\n Group,\n GroupLabel,\n Chips,\n Chip,\n ChipRemove,\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as h } from "./cn-DTiB6ek_.js";
|
|
3
|
+
import { a as I } from "./button-X5wsWvRa.js";
|
|
4
|
+
import { t as C } from "./close-button-xadxp0j8.js";
|
|
5
|
+
import { t as _ } from "./animated-height-DhNSac85.js";
|
|
6
|
+
import { createContext as F, useCallback as O, useContext as B, useEffect as k, useMemo as V, useRef as b, useState as D } from "react";
|
|
7
|
+
import { jsx as e, jsxs as c } from "react/jsx-runtime";
|
|
8
|
+
import { Dialog as p } from "@base-ui/react/dialog";
|
|
9
|
+
var P = F(null);
|
|
10
|
+
function ee() {
|
|
11
|
+
return B(P)?.pending ?? !1;
|
|
12
|
+
}
|
|
13
|
+
function M({ onOpenChange: t, actionsRef: n, ...l }) {
|
|
14
|
+
const [r, a] = D(!1), s = b(!1), o = b(null);
|
|
15
|
+
k(() => {
|
|
16
|
+
if (n)
|
|
17
|
+
return n.current = o.current, () => {
|
|
18
|
+
n.current = null;
|
|
19
|
+
};
|
|
20
|
+
}, [n]);
|
|
21
|
+
const i = O((u, f) => {
|
|
22
|
+
if (!u && s.current) {
|
|
23
|
+
f.cancel();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
t?.(u, f);
|
|
27
|
+
}, [t]), d = V(() => ({
|
|
28
|
+
pending: r,
|
|
29
|
+
beginPending: () => {
|
|
30
|
+
s.current = !0, a(!0);
|
|
31
|
+
},
|
|
32
|
+
endPending: () => {
|
|
33
|
+
s.current = !1, a(!1);
|
|
34
|
+
},
|
|
35
|
+
close: () => o.current?.close()
|
|
36
|
+
}), [r]);
|
|
37
|
+
return /* @__PURE__ */ e(P.Provider, {
|
|
38
|
+
value: d,
|
|
39
|
+
children: /* @__PURE__ */ e(p.Root, {
|
|
40
|
+
actionsRef: o,
|
|
41
|
+
onOpenChange: i,
|
|
42
|
+
...l
|
|
43
|
+
})
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
var S = p.Trigger, y = p.Portal, x = p.Close;
|
|
47
|
+
function $(t) {
|
|
48
|
+
return t != null && typeof t.then == "function";
|
|
49
|
+
}
|
|
50
|
+
function G({ onClick: t, loading: n, disabled: l, ...r }) {
|
|
51
|
+
const a = B(P), [s, o] = D(!1), i = b(!0);
|
|
52
|
+
k(() => (i.current = !0, () => {
|
|
53
|
+
i.current = !1;
|
|
54
|
+
}), []);
|
|
55
|
+
function d(f) {
|
|
56
|
+
if (s || n) return;
|
|
57
|
+
const m = t?.(f);
|
|
58
|
+
if (!$(m)) {
|
|
59
|
+
a?.close();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
o(!0), a?.beginPending(), m.then(() => {
|
|
63
|
+
a?.endPending(), i.current && o(!1), a?.close();
|
|
64
|
+
}, (g) => {
|
|
65
|
+
a?.endPending(), i.current && o(!1), typeof process < "u" && process.env.NODE_ENV !== "production" && console.error("Dialog.Action: async onClick rejected —", g);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
const u = s || n;
|
|
69
|
+
return /* @__PURE__ */ e(I, {
|
|
70
|
+
...r,
|
|
71
|
+
disabled: l || u,
|
|
72
|
+
loading: u,
|
|
73
|
+
onClick: d
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function w({ className: t, ...n }) {
|
|
77
|
+
return /* @__PURE__ */ e(p.Backdrop, {
|
|
78
|
+
className: h("bg-pho-overlay fixed inset-0 z-50 transition-opacity duration-200 ease-out", "data-[ending-style]:opacity-0 data-[ending-style]:duration-150 data-[starting-style]:opacity-0", t),
|
|
79
|
+
...n
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function j({ className: t, ...n }) {
|
|
83
|
+
return /* @__PURE__ */ e(p.Popup, {
|
|
84
|
+
className: h("border-pho-secondary bg-pho-primary shadow-pho-xl fixed top-1/2 left-1/2 z-50 w-[calc(100%-2rem)] max-w-lg -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg border outline-none", "transition-[opacity,scale] duration-200 ease-out", "data-[starting-style]:scale-95 data-[starting-style]:opacity-0", "data-[ending-style]:scale-95 data-[ending-style]:opacity-0 data-[ending-style]:duration-150", t),
|
|
85
|
+
...n
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
function v({ className: t, ...n }) {
|
|
89
|
+
return /* @__PURE__ */ e(p.Title, {
|
|
90
|
+
className: h("text-pho-primary font-display text-display-sm font-medium text-balance", t),
|
|
91
|
+
...n
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
function N({ className: t, ...n }) {
|
|
95
|
+
return /* @__PURE__ */ e(p.Description, {
|
|
96
|
+
className: h("text-pho-description text-display-xs font-normal", t),
|
|
97
|
+
...n
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function z({ children: t, size: n = "md" }) {
|
|
101
|
+
return /* @__PURE__ */ e("span", {
|
|
102
|
+
"aria-hidden": !0,
|
|
103
|
+
className: h("text-pho-secondary mb-1", n === "lg" ? "[&>svg]:size-12" : "[&>svg]:size-8"),
|
|
104
|
+
children: t
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function J({ icon: t, title: n, description: l, consequences: r, warning: a, actions: s, showClose: o = !0, children: i, className: d, ...u }) {
|
|
108
|
+
const f = s == null && o, m = !!(t || n || l || f), g = r != null && r.length > 0, A = g || a != null || i != null || s != null;
|
|
109
|
+
return /* @__PURE__ */ c(y, { children: [/* @__PURE__ */ e(w, {}), /* @__PURE__ */ c(j, {
|
|
110
|
+
className: d,
|
|
111
|
+
...u,
|
|
112
|
+
children: [m && /* @__PURE__ */ c("div", {
|
|
113
|
+
className: "flex flex-col gap-1 px-6 pt-6",
|
|
114
|
+
children: [
|
|
115
|
+
t && /* @__PURE__ */ e(z, { children: t }),
|
|
116
|
+
(n || f) && /* @__PURE__ */ c("div", {
|
|
117
|
+
className: "relative",
|
|
118
|
+
children: [n ? /* @__PURE__ */ e(v, {
|
|
119
|
+
className: f ? "pr-12" : void 0,
|
|
120
|
+
children: n
|
|
121
|
+
}) : /* @__PURE__ */ e("div", {
|
|
122
|
+
className: "h-[1.625rem]",
|
|
123
|
+
"aria-hidden": "true"
|
|
124
|
+
}), f && /* @__PURE__ */ e(x, { render: /* @__PURE__ */ e(C, { className: "absolute top-1/2 right-0 z-10 -translate-y-1/2" }) })]
|
|
125
|
+
}),
|
|
126
|
+
l && /* @__PURE__ */ e(N, { children: l })
|
|
127
|
+
]
|
|
128
|
+
}), A && /* @__PURE__ */ c("div", {
|
|
129
|
+
className: "flex flex-col gap-5 px-6 py-5",
|
|
130
|
+
children: [
|
|
131
|
+
g && /* @__PURE__ */ e("ul", {
|
|
132
|
+
className: "text-pho-description text-md [&_strong]:text-pho-secondary space-y-1 [&_strong]:font-medium",
|
|
133
|
+
children: r.map((R, E) => /* @__PURE__ */ e("li", {
|
|
134
|
+
className: "relative pl-4 before:absolute before:top-2.5 before:left-1 before:size-1 before:rounded-full before:bg-current",
|
|
135
|
+
children: R
|
|
136
|
+
}, E))
|
|
137
|
+
}),
|
|
138
|
+
a != null && /* @__PURE__ */ e("p", {
|
|
139
|
+
className: "text-pho-error text-display-xs font-medium",
|
|
140
|
+
children: a
|
|
141
|
+
}),
|
|
142
|
+
i,
|
|
143
|
+
s != null && /* @__PURE__ */ e("div", {
|
|
144
|
+
className: "flex items-center justify-end gap-2",
|
|
145
|
+
children: s
|
|
146
|
+
})
|
|
147
|
+
]
|
|
148
|
+
})]
|
|
149
|
+
})] });
|
|
150
|
+
}
|
|
151
|
+
function H({ className: t, ...n }) {
|
|
152
|
+
return /* @__PURE__ */ e(p.Popup, {
|
|
153
|
+
className: h("border-pho-secondary bg-pho-primary shadow-pho-xl fixed inset-4 z-50 flex flex-col overflow-hidden rounded-lg border outline-none sm:inset-8", "transition-[opacity,scale] duration-200 ease-out", "data-[starting-style]:scale-[0.98] data-[starting-style]:opacity-0", "data-[ending-style]:scale-[0.98] data-[ending-style]:opacity-0 data-[ending-style]:duration-150", t),
|
|
154
|
+
...n
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
function K({ icon: t, title: n, description: l, actions: r, showClose: a = !0, children: s, className: o, ...i }) {
|
|
158
|
+
const d = r == null && a;
|
|
159
|
+
return /* @__PURE__ */ c(y, { children: [/* @__PURE__ */ e(w, {}), /* @__PURE__ */ c(H, {
|
|
160
|
+
className: o,
|
|
161
|
+
...i,
|
|
162
|
+
children: [
|
|
163
|
+
!!(t || n || l || d) && /* @__PURE__ */ c("div", {
|
|
164
|
+
className: "flex shrink-0 flex-col gap-1 px-6 pt-6",
|
|
165
|
+
children: [
|
|
166
|
+
t && /* @__PURE__ */ e(z, { children: t }),
|
|
167
|
+
(n || d) && /* @__PURE__ */ c("div", {
|
|
168
|
+
className: "relative",
|
|
169
|
+
children: [n ? /* @__PURE__ */ e(v, {
|
|
170
|
+
className: d ? "pr-12" : void 0,
|
|
171
|
+
children: n
|
|
172
|
+
}) : /* @__PURE__ */ e("div", {
|
|
173
|
+
className: "h-[1.625rem]",
|
|
174
|
+
"aria-hidden": "true"
|
|
175
|
+
}), d && /* @__PURE__ */ e(x, { render: /* @__PURE__ */ e(C, { className: "absolute top-1/2 right-0 z-10 -translate-y-1/2" }) })]
|
|
176
|
+
}),
|
|
177
|
+
l && /* @__PURE__ */ e(N, { children: l })
|
|
178
|
+
]
|
|
179
|
+
}),
|
|
180
|
+
/* @__PURE__ */ e("div", {
|
|
181
|
+
className: "min-h-0 flex-1 overflow-y-auto overscroll-contain px-6 py-5",
|
|
182
|
+
children: s
|
|
183
|
+
}),
|
|
184
|
+
r != null && /* @__PURE__ */ e("div", {
|
|
185
|
+
className: "flex shrink-0 items-center justify-end gap-2 px-6 pb-5",
|
|
186
|
+
children: r
|
|
187
|
+
})
|
|
188
|
+
]
|
|
189
|
+
})] });
|
|
190
|
+
}
|
|
191
|
+
function T({ className: t, ...n }) {
|
|
192
|
+
return /* @__PURE__ */ e(p.Popup, {
|
|
193
|
+
className: h("bg-pho-page fixed inset-0 z-50 overflow-y-auto outline-none", "transition-opacity duration-200 ease-out", "data-[ending-style]:opacity-0 data-[ending-style]:duration-150 data-[starting-style]:opacity-0", t),
|
|
194
|
+
...n
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
function L({ icon: t, title: n, description: l, actions: r, showClose: a = !0, frameClassName: s, children: o, className: i, ...d }) {
|
|
198
|
+
const u = r == null && a;
|
|
199
|
+
return /* @__PURE__ */ e(y, { children: /* @__PURE__ */ c(T, {
|
|
200
|
+
className: i,
|
|
201
|
+
...d,
|
|
202
|
+
children: [u && /* @__PURE__ */ e(x, { render: /* @__PURE__ */ e(C, { className: "fixed top-4 right-4 z-10" }) }), /* @__PURE__ */ e("div", {
|
|
203
|
+
className: h("flex min-h-full items-center justify-center px-6 pt-6 pb-20", s),
|
|
204
|
+
children: /* @__PURE__ */ e("div", {
|
|
205
|
+
className: "w-full max-w-md",
|
|
206
|
+
children: /* @__PURE__ */ c(_, {
|
|
207
|
+
className: "flex flex-col gap-5",
|
|
208
|
+
children: [
|
|
209
|
+
(t || n || l) && /* @__PURE__ */ c("div", {
|
|
210
|
+
className: "flex flex-col gap-1",
|
|
211
|
+
children: [
|
|
212
|
+
t && /* @__PURE__ */ e(z, {
|
|
213
|
+
size: "lg",
|
|
214
|
+
children: t
|
|
215
|
+
}),
|
|
216
|
+
n && /* @__PURE__ */ e(v, { children: n }),
|
|
217
|
+
l && /* @__PURE__ */ e(N, { children: l })
|
|
218
|
+
]
|
|
219
|
+
}),
|
|
220
|
+
o,
|
|
221
|
+
r != null && /* @__PURE__ */ e("div", {
|
|
222
|
+
className: "flex items-center justify-end gap-2",
|
|
223
|
+
children: r
|
|
224
|
+
})
|
|
225
|
+
]
|
|
226
|
+
})
|
|
227
|
+
})
|
|
228
|
+
})]
|
|
229
|
+
}) });
|
|
230
|
+
}
|
|
231
|
+
var ne = {
|
|
232
|
+
Root: M,
|
|
233
|
+
Trigger: S,
|
|
234
|
+
Portal: y,
|
|
235
|
+
Backdrop: w,
|
|
236
|
+
Popup: j,
|
|
237
|
+
InsetPopup: H,
|
|
238
|
+
FullscreenPopup: T,
|
|
239
|
+
Title: v,
|
|
240
|
+
Description: N,
|
|
241
|
+
Close: x,
|
|
242
|
+
Action: G,
|
|
243
|
+
Content: J,
|
|
244
|
+
InsetContent: K,
|
|
245
|
+
FullscreenContent: L
|
|
246
|
+
};
|
|
247
|
+
export {
|
|
248
|
+
ee as n,
|
|
249
|
+
ne as t
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
//# sourceMappingURL=dialog-Caze1vkf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialog-Caze1vkf.js","names":[],"sources":["../../src/components/dialog/dialog.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentProps,\n type ElementType,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n} from \"react\";\nimport { Dialog as BaseDialog } from \"@base-ui/react/dialog\";\nimport { AnimatedHeight } from \"../../utils/animated-height\";\nimport { cn } from \"../../utils/cn\";\nimport { Button, type ButtonProps } from \"../button/button\";\nimport { CloseButton } from \"../button/close-button\";\n\n/** Override Base UI's `string | (state) => string` className with plain string. */\ntype StyledProps<T extends ElementType> = Omit<\n ComponentProps<T>,\n \"className\"\n> & {\n className?: string;\n};\n\n/* ========================== Async pending context ========================== */\n\n/** Imperative actions exposed by Base UI's `actionsRef`. */\ninterface RootActions {\n unmount: () => void;\n close: () => void;\n}\n\ninterface DialogPendingContextValue {\n /** True while a `Dialog.Action` promise is in flight. */\n pending: boolean;\n beginPending: () => void;\n endPending: () => void;\n /** Close the dialog imperatively (used by `Dialog.Action` on resolve). */\n close: () => void;\n}\n\nconst DialogPendingContext = createContext<DialogPendingContextValue | null>(\n null,\n);\n\n/**\n * Whether the surrounding dialog has a `Dialog.Action` promise in flight —\n * use it to disable secondary actions (Cancel etc.) while work is pending.\n * Returns `false` outside a `Dialog.Root`.\n */\nexport function useDialogPending(): boolean {\n return useContext(DialogPendingContext)?.pending ?? false;\n}\n\ntype RootProps = ComponentProps<typeof BaseDialog.Root>;\n\n/**\n * `Dialog.Root` with async awareness: while a `Dialog.Action` promise is\n * pending, every close request (outside press, Escape, `Dialog.Close`) is\n * cancelled so the dialog stays open until the work settles. Props pass\n * through to Base UI's `Dialog.Root` unchanged.\n */\nfunction Root({ onOpenChange, actionsRef, ...props }: RootProps) {\n const [pending, setPending] = useState(false);\n // Guard reads a ref so a resolve → close() in the same tick isn't blocked\n // by a not-yet-flushed state update.\n const pendingRef = useRef(false);\n const internalActionsRef = useRef<RootActions | null>(null);\n\n // Keep a caller-supplied actionsRef working alongside our internal one.\n useEffect(() => {\n if (!actionsRef) return;\n actionsRef.current = internalActionsRef.current;\n return () => {\n actionsRef.current = null;\n };\n }, [actionsRef]);\n\n const handleOpenChange = useCallback<NonNullable<RootProps[\"onOpenChange\"]>>(\n (open, eventDetails) => {\n if (!open && pendingRef.current) {\n eventDetails.cancel();\n return;\n }\n onOpenChange?.(open, eventDetails);\n },\n [onOpenChange],\n );\n\n const contextValue = useMemo<DialogPendingContextValue>(\n () => ({\n pending,\n beginPending: () => {\n pendingRef.current = true;\n setPending(true);\n },\n endPending: () => {\n pendingRef.current = false;\n setPending(false);\n },\n close: () => internalActionsRef.current?.close(),\n }),\n [pending],\n );\n\n return (\n <DialogPendingContext.Provider value={contextValue}>\n <BaseDialog.Root\n actionsRef={internalActionsRef}\n onOpenChange={handleOpenChange}\n {...props}\n />\n </DialogPendingContext.Provider>\n );\n}\n\nconst Trigger = BaseDialog.Trigger;\nconst Portal = BaseDialog.Portal;\nconst Close = BaseDialog.Close;\n\n/* ============================== Dialog.Action ============================== */\n\nexport interface DialogActionProps extends Omit<ButtonProps, \"onClick\"> {\n /**\n * Confirm handler. Return a promise to keep the dialog open while it runs:\n * the button shows `loading`, all dismissal is locked, and the dialog\n * closes when the promise resolves. On rejection the dialog stays open —\n * surface errors inside the handler. A non-promise return closes\n * immediately, like `Dialog.Close`.\n */\n onClick?: (\n event: ReactMouseEvent<HTMLButtonElement>,\n ) => void | Promise<unknown>;\n}\n\nfunction isThenable(value: unknown): value is Promise<unknown> {\n return (\n value != null && typeof (value as { then?: unknown }).then === \"function\"\n );\n}\n\n/**\n * The confirm button of an action row, with native promise support — a\n * `Button` that runs its (possibly async) `onClick` and closes the dialog\n * when the work settles successfully.\n */\nfunction Action({ onClick, loading, disabled, ...props }: DialogActionProps) {\n const pendingContext = useContext(DialogPendingContext);\n const [busy, setBusy] = useState(false);\n const mountedRef = useRef(true);\n\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n function handleClick(event: ReactMouseEvent<HTMLButtonElement>) {\n if (busy || loading) return;\n const result = onClick?.(event);\n if (!isThenable(result)) {\n pendingContext?.close();\n return;\n }\n setBusy(true);\n pendingContext?.beginPending();\n result.then(\n () => {\n pendingContext?.endPending();\n if (mountedRef.current) setBusy(false);\n pendingContext?.close();\n },\n (error: unknown) => {\n pendingContext?.endPending();\n if (mountedRef.current) setBusy(false);\n if (\n typeof process !== \"undefined\" &&\n process.env?.NODE_ENV !== \"production\"\n ) {\n console.error(\"Dialog.Action: async onClick rejected —\", error);\n }\n },\n );\n }\n\n const inert = busy || loading;\n return (\n <Button\n {...props}\n disabled={disabled || inert}\n loading={inert}\n onClick={handleClick}\n />\n );\n}\n\nfunction Backdrop({\n className,\n ...props\n}: StyledProps<typeof BaseDialog.Backdrop>) {\n return (\n <BaseDialog.Backdrop\n className={cn(\n \"bg-pho-overlay fixed inset-0 z-50 transition-opacity duration-200 ease-out\",\n \"data-[ending-style]:opacity-0 data-[ending-style]:duration-150 data-[starting-style]:opacity-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Popup({ className, ...props }: StyledProps<typeof BaseDialog.Popup>) {\n return (\n <BaseDialog.Popup\n className={cn(\n // Floating layer: bg-pho-primary + border-pho-secondary hairline, elevation kept.\n \"border-pho-secondary bg-pho-primary shadow-pho-xl fixed top-1/2 left-1/2 z-50 w-[calc(100%-2rem)] max-w-lg -translate-x-1/2 -translate-y-1/2 overflow-hidden rounded-lg border outline-none\",\n // Opacity + scale only — leave translate centering alone (no transition-all).\n \"transition-[opacity,scale] duration-200 ease-out\",\n \"data-[starting-style]:scale-95 data-[starting-style]:opacity-0\",\n \"data-[ending-style]:scale-95 data-[ending-style]:opacity-0 data-[ending-style]:duration-150\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Title({ className, ...props }: StyledProps<typeof BaseDialog.Title>) {\n return (\n <BaseDialog.Title\n className={cn(\n \"text-pho-primary font-display text-display-sm font-medium text-balance\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction Description({\n className,\n ...props\n}: StyledProps<typeof BaseDialog.Description>) {\n return (\n <BaseDialog.Description\n className={cn(\n \"text-pho-description text-display-xs font-normal\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/**\n * Header icon chrome: secondary ink, a hair of extra air before the title.\n * Panel dialogs use 32px (`size-8`); fullscreen gates step up to 48px\n * (`size-12`) so the glyph reads at viewport scale.\n */\nfunction DialogHeaderIcon({\n children,\n size = \"md\",\n}: {\n children: ReactNode;\n size?: \"md\" | \"lg\";\n}) {\n return (\n <span\n aria-hidden\n className={cn(\n \"text-pho-secondary mb-1\",\n size === \"lg\" ? \"[&>svg]:size-12\" : \"[&>svg]:size-8\",\n )}\n >\n {children}\n </span>\n );\n}\n\ninterface ContentProps extends Omit<\n StyledProps<typeof BaseDialog.Popup>,\n \"title\"\n> {\n /**\n * Decorative icon above the title — typically a Tabler outline icon.\n * Rendered aria-hidden in secondary ink at 32px (`[&>svg]:size-8`). Pass a\n * styled node to override the ink; the size is owned by the slot.\n */\n icon?: ReactNode;\n /** Heading rendered in the panel header. */\n title?: ReactNode;\n /** Supporting text under the title. */\n description?: ReactNode;\n /**\n * Consequence bullets rendered as a list at the top of the body — one item\n * per outcome (what is deleted, what survives, who loses access). Use on\n * destructive confirms where the one-line description undersells the\n * impact; keep each item to a single short sentence. Wrap the load-bearing\n * figure in `<strong>` (\"<strong>3 members</strong> lose access\") — the\n * list styles it (secondary ink, medium weight); no classes needed.\n */\n consequences?: ReactNode[];\n /**\n * Final cautionary line under `consequences` — error ink at description\n * size (e.g. \"It cannot be undone. Please be certain.\"). Reserve it for\n * irreversible actions; keep it short.\n */\n warning?: ReactNode;\n /**\n * Footer action row (Cancel / Confirm, etc.). Iron rule: when `actions` is\n * set, the header close button is never shown — dismiss via the actions.\n */\n actions?: ReactNode;\n /**\n * Header close control. Only applies when `actions` is absent.\n * @default true\n */\n showClose?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Convenience panel: renders the portal, backdrop, and styled popup with an\n * optional header (title/description + close) and optional action row. For\n * full control, compose the parts directly (`Dialog.Portal` /\n * `Dialog.Backdrop` / `Dialog.Popup`).\n */\nfunction Content({\n icon,\n title,\n description,\n consequences,\n warning,\n actions,\n showClose = true,\n children,\n className,\n ...props\n}: ContentProps) {\n // Iron rule: action dialogs dismiss via their actions — never a header X.\n const showCloseButton = actions == null && showClose;\n const hasHeader = Boolean(icon || title || description || showCloseButton);\n const hasConsequences = consequences != null && consequences.length > 0;\n const hasBody =\n hasConsequences || warning != null || children != null || actions != null;\n\n return (\n <Portal>\n <Backdrop />\n <Popup className={className} {...props}>\n {hasHeader && (\n <div className=\"flex flex-col gap-1 px-6 pt-6\">\n {icon && <DialogHeaderIcon>{icon}</DialogHeaderIcon>}\n {(title || showCloseButton) && (\n // Title row height = title only. Close is out of flow, centered\n // on the row, and may paint outside it (no clip, no stretch).\n <div className=\"relative\">\n {title ? (\n <Title className={showCloseButton ? \"pr-12\" : undefined}>\n {title}\n </Title>\n ) : (\n <div className=\"h-[1.625rem]\" aria-hidden=\"true\" />\n )}\n {showCloseButton && (\n <Close\n render={\n <CloseButton className=\"absolute top-1/2 right-0 z-10 -translate-y-1/2\" />\n }\n />\n )}\n </div>\n )}\n {description && <Description>{description}</Description>}\n </div>\n )}\n {hasBody && (\n <div className=\"flex flex-col gap-5 px-6 py-5\">\n {hasConsequences && (\n <ul className=\"text-pho-description text-md [&_strong]:text-pho-secondary space-y-1 [&_strong]:font-medium\">\n {consequences.map((item, index) => (\n // Hand-drawn marker: a 4px dot on the first line's center —\n // quieter than the browser disc, ink tracks the text.\n <li\n key={index}\n className=\"relative pl-4 before:absolute before:top-2.5 before:left-1 before:size-1 before:rounded-full before:bg-current\"\n >\n {item}\n </li>\n ))}\n </ul>\n )}\n {warning != null && (\n <p className=\"text-pho-error text-display-xs font-medium\">\n {warning}\n </p>\n )}\n {children}\n {actions != null && (\n <div className=\"flex items-center justify-end gap-2\">\n {actions}\n </div>\n )}\n </div>\n )}\n </Popup>\n </Portal>\n );\n}\n\n/* =========================== Dialog.InsetContent =========================== */\n\n/**\n * Near-fullscreen popup — the viewport minus a breathing ring, floating over\n * a backdrop (the page stays visible through the gap, so it dims like any\n * floating layer). Still a card: border, elevation, rounded corners; the\n * scale gesture stays but shrinks to 98% — at this size 95% reads like a jump.\n */\nfunction InsetPopup({\n className,\n ...props\n}: StyledProps<typeof BaseDialog.Popup>) {\n return (\n <BaseDialog.Popup\n className={cn(\n \"border-pho-secondary bg-pho-primary shadow-pho-xl fixed inset-4 z-50 flex flex-col overflow-hidden rounded-lg border outline-none sm:inset-8\",\n \"transition-[opacity,scale] duration-200 ease-out\",\n \"data-[starting-style]:scale-[0.98] data-[starting-style]:opacity-0\",\n \"data-[ending-style]:scale-[0.98] data-[ending-style]:opacity-0 data-[ending-style]:duration-150\",\n className,\n )}\n {...props}\n />\n );\n}\n\ninterface InsetContentProps extends Omit<\n StyledProps<typeof BaseDialog.Popup>,\n \"title\"\n> {\n /** Decorative icon above the title — same treatment as `Content`. */\n icon?: ReactNode;\n /** Heading rendered in the panel header. */\n title?: ReactNode;\n /** Supporting text under the title. */\n description?: ReactNode;\n /**\n * Bottom action row. Iron rule as `Content`: when `actions` is set, the\n * header close button is never shown — dismiss via the actions.\n */\n actions?: ReactNode;\n /**\n * Header close control. Only applies when `actions` is absent.\n * @default true\n */\n showClose?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Convenience near-fullscreen panel: header pinned on top, body filling and\n * scrolling on its own, optional action row pinned at the bottom. Sits\n * between `Content` (a focused card) and `FullscreenContent` (a page\n * takeover): use it for roomy working surfaces — pickers, editors, previews —\n * that still want the page peeking through an edge.\n */\nfunction InsetContent({\n icon,\n title,\n description,\n actions,\n showClose = true,\n children,\n className,\n ...props\n}: InsetContentProps) {\n // Iron rule: action dialogs dismiss via their actions — never a header X.\n const showCloseButton = actions == null && showClose;\n const hasHeader = Boolean(icon || title || description || showCloseButton);\n\n return (\n <Portal>\n <Backdrop />\n <InsetPopup className={className} {...props}>\n {hasHeader && (\n <div className=\"flex shrink-0 flex-col gap-1 px-6 pt-6\">\n {icon && <DialogHeaderIcon>{icon}</DialogHeaderIcon>}\n {(title || showCloseButton) && (\n <div className=\"relative\">\n {title ? (\n <Title className={showCloseButton ? \"pr-12\" : undefined}>\n {title}\n </Title>\n ) : (\n <div className=\"h-[1.625rem]\" aria-hidden=\"true\" />\n )}\n {showCloseButton && (\n <Close\n render={\n <CloseButton className=\"absolute top-1/2 right-0 z-10 -translate-y-1/2\" />\n }\n />\n )}\n </div>\n )}\n {description && <Description>{description}</Description>}\n </div>\n )}\n <div className=\"min-h-0 flex-1 overflow-y-auto overscroll-contain px-6 py-5\">\n {children}\n </div>\n {actions != null && (\n <div className=\"flex shrink-0 items-center justify-end gap-2 px-6 pb-5\">\n {actions}\n </div>\n )}\n </InsetPopup>\n </Portal>\n );\n}\n\n/* ========================= Dialog.FullscreenContent ======================== */\n\n/**\n * Full-viewport popup — a page-surface takeover instead of a floating card.\n * No backdrop: the popup itself is the layer. Fade only; scale is a floating-\n * card gesture and reads wrong at viewport size.\n */\nfunction FullscreenPopup({\n className,\n ...props\n}: StyledProps<typeof BaseDialog.Popup>) {\n return (\n <BaseDialog.Popup\n className={cn(\n \"bg-pho-page fixed inset-0 z-50 overflow-y-auto outline-none\",\n \"transition-opacity duration-200 ease-out\",\n \"data-[ending-style]:opacity-0 data-[ending-style]:duration-150 data-[starting-style]:opacity-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\ninterface FullscreenContentProps extends Omit<\n StyledProps<typeof BaseDialog.Popup>,\n \"title\"\n> {\n /**\n * Decorative icon above the title — same chrome as `Content`, but 48px\n * (`size-12`) for viewport-scale gates.\n */\n icon?: ReactNode;\n /** Heading of the takeover. */\n title?: ReactNode;\n /** Supporting text under the title. */\n description?: ReactNode;\n /**\n * Action row under the body. Iron rule as `Content`: when `actions` is set,\n * the corner close button is never shown — dismiss via the actions.\n */\n actions?: ReactNode;\n /**\n * Corner close control. Only applies when `actions` is absent.\n * @default true\n */\n showClose?: boolean;\n /**\n * Classes on the viewport-centering frame (the `min-h-full` flex host).\n * Use to drop the default optical `pb-20` when the stack grows (e.g. a\n * captcha) so true center stays put: `frameClassName=\"pb-6\"`.\n */\n frameClassName?: string;\n children?: ReactNode;\n}\n\n/**\n * Convenience full-screen panel: the whole viewport becomes the dialog, with\n * a centered column at the standalone-flow width (28rem — the same measure as\n * onboarding / invite cards). Column height follows its content through\n * `AnimatedHeight` (same spring as the Card shell), so step swaps — phone →\n * OTP → captcha — glide instead of jumping. Use for gates the visitor must\n * deal with before the page behind makes sense (e.g. binding a phone number);\n * prefer `Content` for everything conversational.\n */\nfunction FullscreenContent({\n icon,\n title,\n description,\n actions,\n showClose = true,\n frameClassName,\n children,\n className,\n ...props\n}: FullscreenContentProps) {\n // Iron rule: action dialogs dismiss via their actions — never a corner X.\n const showCloseButton = actions == null && showClose;\n\n return (\n <Portal>\n <FullscreenPopup className={className} {...props}>\n {showCloseButton && (\n <Close\n render={<CloseButton className=\"fixed top-4 right-4 z-10\" />}\n />\n )}\n {/* Default `pb-20` optically lifts the column above true center. */}\n <div\n className={cn(\n \"flex min-h-full items-center justify-center px-6 pt-6 pb-20\",\n frameClassName,\n )}\n >\n {/* Width stays on the outer host; AnimatedHeight measures the\n section stack and springs its own height on content changes. */}\n <div className=\"w-full max-w-md\">\n <AnimatedHeight className=\"flex flex-col gap-5\">\n {(icon || title || description) && (\n <div className=\"flex flex-col gap-1\">\n {icon && (\n <DialogHeaderIcon size=\"lg\">{icon}</DialogHeaderIcon>\n )}\n {title && <Title>{title}</Title>}\n {description && <Description>{description}</Description>}\n </div>\n )}\n {children}\n {actions != null && (\n <div className=\"flex items-center justify-end gap-2\">\n {actions}\n </div>\n )}\n </AnimatedHeight>\n </div>\n </div>\n </FullscreenPopup>\n </Portal>\n );\n}\n\n/**\n * Modal dialog built on Base UI `Dialog`. Controlled or uncontrolled via\n * `Dialog.Root` (`open` / `onOpenChange` / `defaultOpen`). `Dialog.Action`\n * adds native promise support: an async confirm keeps the dialog open and\n * undismissable until the work resolves.\n */\nexport const Dialog = {\n Root,\n Trigger,\n Portal,\n Backdrop,\n Popup,\n InsetPopup,\n FullscreenPopup,\n Title,\n Description,\n Close,\n Action,\n Content,\n InsetContent,\n FullscreenContent,\n};\n"],"mappings":";;;;;;;;AA4CA,IAAM,IAAuB,EAC3B,IACF;AAOA,SAAgB,KAA4B;AAC1C,SAAO,EAAW,CAAoB,GAAG,WAAW;AACtD;AAUA,SAAS,EAAK,EAAE,cAAA,GAAc,YAAA,GAAY,GAAG,EAAA,GAAoB;AAC/D,QAAM,CAAC,GAAS,CAAA,IAAc,EAAS,EAAK,GAGtC,IAAa,EAAO,EAAK,GACzB,IAAqB,EAA2B,IAAI;AAG1D,EAAA,EAAA,MAAgB;AACd,QAAK;AACL,aAAA,EAAW,UAAU,EAAmB,SACxC,MAAa;AACX,QAAA,EAAW,UAAU;AAAA,MACvB;AAAA,EACF,GAAG,CAAC,CAAU,CAAC;AAEf,QAAM,IAAmB,EAAA,CACtB,GAAM,MAAiB;AACtB,QAAI,CAAC,KAAQ,EAAW,SAAS;AAC/B,MAAA,EAAa,OAAO;AACpB;AAAA,IACF;AACA,IAAA,IAAe,GAAM,CAAY;AAAA,EACnC,GACA,CAAC,CAAY,CACf,GAEM,IAAe,EAAA,OACZ;AAAA,IACL,SAAA;AAAA,IACA,cAAA,MAAoB;AAClB,MAAA,EAAW,UAAU,IACrB,EAAW,EAAI;AAAA,IACjB;AAAA,IACA,YAAA,MAAkB;AAChB,MAAA,EAAW,UAAU,IACrB,EAAW,EAAK;AAAA,IAClB;AAAA,IACA,OAAA,MAAa,EAAmB,SAAS,MAAM;AAAA,EACjD,IACA,CAAC,CAAO,CACV;AAEA,SACE,gBAAA,EAAC,EAAqB,UAAtB;AAAA,IAA+B,OAAO;AAAA,cACpC,gBAAA,EAAC,EAAW,MAAZ;AAAA,MACE,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,GAAI;AAAA,IACL,CAAA;AAAA,EAC4B,CAAA;AAEnC;AAEA,IAAM,IAAU,EAAW,SACrB,IAAS,EAAW,QACpB,IAAQ,EAAW;AAiBzB,SAAS,EAAW,GAA2C;AAC7D,SACE,KAAS,QAAQ,OAAQ,EAA6B,QAAS;AAEnE;AAOA,SAAS,EAAO,EAAE,SAAA,GAAS,SAAA,GAAS,UAAA,GAAU,GAAG,EAAA,GAA4B;AAC3E,QAAM,IAAiB,EAAW,CAAoB,GAChD,CAAC,GAAM,CAAA,IAAW,EAAS,EAAK,GAChC,IAAa,EAAO,EAAI;AAE9B,EAAA,EAAA,OACE,EAAW,UAAU,IACrB,MAAa;AACX,IAAA,EAAW,UAAU;AAAA,EACvB,IACC,CAAC,CAAC;AAEL,WAAS,EAAY,GAA2C;AAC9D,QAAI,KAAQ,EAAS;AACrB,UAAM,IAAS,IAAU,CAAK;AAC9B,QAAI,CAAC,EAAW,CAAM,GAAG;AACvB,MAAA,GAAgB,MAAM;AACtB;AAAA,IACF;AACA,IAAA,EAAQ,EAAI,GACZ,GAAgB,aAAa,GAC7B,EAAO,KAAA,MACC;AACJ,MAAA,GAAgB,WAAW,GACvB,EAAW,WAAS,EAAQ,EAAK,GACrC,GAAgB,MAAM;AAAA,IACxB,GAAA,CACC,MAAmB;AAClB,MAAA,GAAgB,WAAW,GACvB,EAAW,WAAS,EAAQ,EAAK,GAEnC,OAAO,UAAY,OAAA,QAAA,IAAA,aACO,gBAE1B,QAAQ,MAAM,2CAA2C,CAAK;AAAA,IAElE,CACF;AAAA,EACF;AAEA,QAAM,IAAQ,KAAQ;AACtB,SACE,gBAAA,EAAC,GAAD;AAAA,IACE,GAAI;AAAA,IACJ,UAAU,KAAY;AAAA,IACtB,SAAS;AAAA,IACT,SAAS;AAAA,EACV,CAAA;AAEL;AAEA,SAAS,EAAS,EAChB,WAAA,GACA,GAAG,EAAA,GACuC;AAC1C,SACE,gBAAA,EAAC,EAAW,UAAZ;AAAA,IACE,WAAW,EACT,8EACA,kGACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAEA,SAAS,EAAM,EAAE,WAAA,GAAW,GAAG,EAAA,GAA+C;AAC5E,SACE,gBAAA,EAAC,EAAW,OAAZ;AAAA,IACE,WAAW,EAET,+LAEA,oDACA,kEACA,+FACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAEA,SAAS,EAAM,EAAE,WAAA,GAAW,GAAG,EAAA,GAA+C;AAC5E,SACE,gBAAA,EAAC,EAAW,OAAZ;AAAA,IACE,WAAW,EACT,0EACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAEA,SAAS,EAAY,EACnB,WAAA,GACA,GAAG,EAAA,GAC0C;AAC7C,SACE,gBAAA,EAAC,EAAW,aAAZ;AAAA,IACE,WAAW,EACT,oDACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAOA,SAAS,EAAiB,EACxB,UAAA,GACA,MAAA,IAAO,KAAA,GAIN;AACD,SACE,gBAAA,EAAC,QAAD;AAAA,IACE,eAAA;AAAA,IACA,WAAW,EACT,2BACA,MAAS,OAAO,oBAAoB,gBACtC;AAAA,IAEC,UAAA;AAAA,EACG,CAAA;AAEV;AAkDA,SAAS,EAAQ,EACf,MAAA,GACA,OAAA,GACA,aAAA,GACA,cAAA,GACA,SAAA,GACA,SAAA,GACA,WAAA,IAAY,IACZ,UAAA,GACA,WAAA,GACA,GAAG,EAAA,GACY;AAEf,QAAM,IAAkB,KAAW,QAAQ,GACrC,IAAY,GAAQ,KAAQ,KAAS,KAAe,IACpD,IAAkB,KAAgB,QAAQ,EAAa,SAAS,GAChE,IACJ,KAAmB,KAAW,QAAQ,KAAY,QAAQ,KAAW;AAEvE,SACE,gBAAA,EAAC,GAAD,EAAA,UAAA,CACE,gBAAA,EAAC,GAAD,CAAW,CAAA,GACX,gBAAA,EAAC,GAAD;AAAA,IAAkB,WAAA;AAAA,IAAW,GAAI;AAAA,cAAjC,CACG,KACC,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,gBAAf;AAAA,QACG,KAAQ,gBAAA,EAAC,GAAD,EAAA,UAAmB,EAAuB,CAAA;AAAA,SACjD,KAAS,MAGT,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,oBAAf,CACG,IACC,gBAAA,EAAC,GAAD;AAAA,YAAO,WAAW,IAAkB,UAAU;AAAA,sBAC3C;AAAA,UACI,CAAA,IAEP,gBAAA,EAAC,OAAD;AAAA,YAAK,WAAU;AAAA,YAAe,eAAY;AAAA,UAAQ,CAAA,GAEnD,KACC,gBAAA,EAAC,GAAD,EACE,QACE,gBAAA,EAAC,GAAD,EAAa,WAAU,iDAAkD,CAAA,EAE5E,CAAA,CAEA;AAAA;QAEN,KAAe,gBAAA,EAAC,GAAD,EAAA,UAAc,EAAyB,CAAA;AAAA,MACpD;AAAA,QAEN,KACC,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,gBAAf;AAAA,QACG,KACC,gBAAA,EAAC,MAAD;AAAA,UAAI,WAAU;AAAA,oBACX,EAAa,IAAA,CAAK,GAAM,MAGvB,gBAAA,EAAC,MAAD;AAAA,YAEE,WAAU;AAAA,sBAET;AAAA,UACC,GAJG,CAIH,CACL;AAAA,QACC,CAAA;AAAA,QAEL,KAAW,QACV,gBAAA,EAAC,KAAD;AAAA,UAAG,WAAU;AAAA,oBACV;AAAA,QACA,CAAA;AAAA,QAEJ;AAAA,QACA,KAAW,QACV,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,oBACZ;AAAA,QACE,CAAA;AAAA,MAEJ;AAAA,MAEF;AAAA,IACD,EAAA,CAAA;AAEZ;AAUA,SAAS,EAAW,EAClB,WAAA,GACA,GAAG,EAAA,GACoC;AACvC,SACE,gBAAA,EAAC,EAAW,OAAZ;AAAA,IACE,WAAW,EACT,gJACA,oDACA,sEACA,mGACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AAgCA,SAAS,EAAa,EACpB,MAAA,GACA,OAAA,GACA,aAAA,GACA,SAAA,GACA,WAAA,IAAY,IACZ,UAAA,GACA,WAAA,GACA,GAAG,EAAA,GACiB;AAEpB,QAAM,IAAkB,KAAW,QAAQ;AAG3C,SACE,gBAAA,EAAC,GAAD,EAAA,UAAA,CACE,gBAAA,EAAC,GAAD,CAAW,CAAA,GACX,gBAAA,EAAC,GAAD;AAAA,IAAuB,WAAA;AAAA,IAAW,GAAI;AAAA,cAAtC;AAAA,MALc,GAAQ,KAAQ,KAAS,KAAe,MAOlD,gBAAA,EAAC,OAAD;AAAA,QAAK,WAAU;AAAA,kBAAf;AAAA,UACG,KAAQ,gBAAA,EAAC,GAAD,EAAA,UAAmB,EAAuB,CAAA;AAAA,WACjD,KAAS,MACT,gBAAA,EAAC,OAAD;AAAA,YAAK,WAAU;AAAA,sBAAf,CACG,IACC,gBAAA,EAAC,GAAD;AAAA,cAAO,WAAW,IAAkB,UAAU;AAAA,wBAC3C;AAAA,YACI,CAAA,IAEP,gBAAA,EAAC,OAAD;AAAA,cAAK,WAAU;AAAA,cAAe,eAAY;AAAA,YAAQ,CAAA,GAEnD,KACC,gBAAA,EAAC,GAAD,EACE,QACE,gBAAA,EAAC,GAAD,EAAa,WAAU,iDAAkD,CAAA,EAE5E,CAAA,CAEA;AAAA;UAEN,KAAe,gBAAA,EAAC,GAAD,EAAA,UAAc,EAAyB,CAAA;AAAA,QACpD;AAAA;MAEP,gBAAA,EAAC,OAAD;AAAA,QAAK,WAAU;AAAA,QACZ,UAAA;AAAA,MACE,CAAA;AAAA,MACJ,KAAW,QACV,gBAAA,EAAC,OAAD;AAAA,QAAK,WAAU;AAAA,kBACZ;AAAA,MACE,CAAA;AAAA,IAEG;AAAA,IACN,EAAA,CAAA;AAEZ;AASA,SAAS,EAAgB,EACvB,WAAA,GACA,GAAG,EAAA,GACoC;AACvC,SACE,gBAAA,EAAC,EAAW,OAAZ;AAAA,IACE,WAAW,EACT,+DACA,4CACA,kGACA,CACF;AAAA,IACA,GAAI;AAAA,EACL,CAAA;AAEL;AA2CA,SAAS,EAAkB,EACzB,MAAA,GACA,OAAA,GACA,aAAA,GACA,SAAA,GACA,WAAA,IAAY,IACZ,gBAAA,GACA,UAAA,GACA,WAAA,GACA,GAAG,EAAA,GACsB;AAEzB,QAAM,IAAkB,KAAW,QAAQ;AAE3C,SACE,gBAAA,EAAC,GAAD,EAAA,UACE,gBAAA,EAAC,GAAD;AAAA,IAA4B,WAAA;AAAA,IAAW,GAAI;AAAA,cAA3C,CACG,KACC,gBAAA,EAAC,GAAD,EACE,QAAQ,gBAAA,EAAC,GAAD,EAAa,WAAU,2BAA4B,CAAA,EAC5D,CAAA,GAGH,gBAAA,EAAC,OAAD;AAAA,MACE,WAAW,EACT,+DACA,CACF;AAAA,gBAIA,gBAAA,EAAC,OAAD;AAAA,QAAK,WAAU;AAAA,kBACb,gBAAA,EAAC,GAAD;AAAA,UAAgB,WAAU;AAAA,oBAA1B;AAAA,aACI,KAAQ,KAAS,MACjB,gBAAA,EAAC,OAAD;AAAA,cAAK,WAAU;AAAA,wBAAf;AAAA,gBACG,KACC,gBAAA,EAAC,GAAD;AAAA,kBAAkB,MAAK;AAAA,4BAAM;AAAA,gBAAuB,CAAA;AAAA,gBAErD,KAAS,gBAAA,EAAC,GAAD,EAAA,UAAQ,EAAa,CAAA;AAAA,gBAC9B,KAAe,gBAAA,EAAC,GAAD,EAAA,UAAc,EAAyB,CAAA;AAAA,cACpD;AAAA;YAEN;AAAA,YACA,KAAW,QACV,gBAAA,EAAC,OAAD;AAAA,cAAK,WAAU;AAAA,wBACZ;AAAA,YACE,CAAA;AAAA,UAEO;AAAA;MACb,CAAA;AAAA,IACF,CAAA,CACU;AAAA,KACX,CAAA;AAEZ;AAQA,IAAa,KAAS;AAAA,EACpB,MAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA,YAAA;AAAA,EACA,iBAAA;AAAA,EACA,OAAA;AAAA,EACA,aAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,cAAA;AAAA,EACA,mBAAA;AACF"}
|