@suzumiyaaoba/mdxr 0.1.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/LICENSE +21 -0
- package/README.md +56 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +2902 -0
- package/dist/components.d.mts +791 -0
- package/dist/components.mjs +2 -0
- package/dist/config-SI9IyFiC.mjs +184 -0
- package/dist/doc-context-CEqzMYKv.d.mts +568 -0
- package/dist/index.d.mts +20 -0
- package/dist/index.mjs +4 -0
- package/dist/ui-GKFD0mx5.mjs +15986 -0
- package/package.json +131 -0
- package/skill/SKILL.md +49 -0
- package/skill/references/components/charts.md +172 -0
- package/skill/references/components/document.md +98 -0
- package/skill/references/components/forms.md +35 -0
- package/skill/references/components/investigation.md +198 -0
- package/skill/references/components/layout.md +68 -0
- package/skill/references/components/output.md +158 -0
- package/skill/references/components/planning.md +155 -0
- package/skill/references/components/reports.md +252 -0
- package/skill/references/components/shadcn.md +19 -0
- package/skill/references/components.md +186 -0
- package/skill/references/extending.md +48 -0
- package/src/ask-sheet.ts +40 -0
- package/src/assets/css.ts +392 -0
- package/src/assets/scripts.ts +78 -0
- package/src/catalog.ts +287 -0
- package/src/cli.ts +178 -0
- package/src/client/doc-events.ts +1108 -0
- package/src/client/entry.ts +27 -0
- package/src/client-js.ts +47 -0
- package/src/component-map.ts +47 -0
- package/src/components/ui/accordion.tsx +77 -0
- package/src/components/ui/alert-dialog.tsx +185 -0
- package/src/components/ui/alert.tsx +76 -0
- package/src/components/ui/aspect-ratio.tsx +22 -0
- package/src/components/ui/attachment.tsx +208 -0
- package/src/components/ui/avatar.tsx +106 -0
- package/src/components/ui/badge.tsx +52 -0
- package/src/components/ui/breadcrumb.tsx +121 -0
- package/src/components/ui/bubble.tsx +128 -0
- package/src/components/ui/button-group.tsx +88 -0
- package/src/components/ui/button.tsx +58 -0
- package/src/components/ui/calendar.tsx +226 -0
- package/src/components/ui/card.tsx +102 -0
- package/src/components/ui/carousel.tsx +246 -0
- package/src/components/ui/chart.tsx +379 -0
- package/src/components/ui/checkbox.tsx +27 -0
- package/src/components/ui/collapsible.tsx +19 -0
- package/src/components/ui/combobox.tsx +298 -0
- package/src/components/ui/command.tsx +193 -0
- package/src/components/ui/context-menu.tsx +271 -0
- package/src/components/ui/dialog.tsx +159 -0
- package/src/components/ui/direction.tsx +4 -0
- package/src/components/ui/drawer.tsx +227 -0
- package/src/components/ui/dropdown-menu.tsx +269 -0
- package/src/components/ui/empty.tsx +104 -0
- package/src/components/ui/field.tsx +237 -0
- package/src/components/ui/fieldset.tsx +32 -0
- package/src/components/ui/frame.tsx +87 -0
- package/src/components/ui/hover-card.tsx +50 -0
- package/src/components/ui/input-group.tsx +159 -0
- package/src/components/ui/input-otp.tsx +83 -0
- package/src/components/ui/input.tsx +19 -0
- package/src/components/ui/item.tsx +202 -0
- package/src/components/ui/kbd.tsx +26 -0
- package/src/components/ui/label.tsx +19 -0
- package/src/components/ui/marker.tsx +71 -0
- package/src/components/ui/menubar.tsx +284 -0
- package/src/components/ui/message-scroller.tsx +128 -0
- package/src/components/ui/message.tsx +91 -0
- package/src/components/ui/meter.tsx +80 -0
- package/src/components/ui/native-select.tsx +64 -0
- package/src/components/ui/navigation-menu.tsx +170 -0
- package/src/components/ui/pagination.tsx +133 -0
- package/src/components/ui/popover.tsx +87 -0
- package/src/components/ui/progress.tsx +82 -0
- package/src/components/ui/questionnaire.tsx +328 -0
- package/src/components/ui/radio-group.tsx +35 -0
- package/src/components/ui/resizable.tsx +49 -0
- package/src/components/ui/scroll-area.tsx +50 -0
- package/src/components/ui/select.tsx +201 -0
- package/src/components/ui/separator.tsx +22 -0
- package/src/components/ui/sheet.tsx +135 -0
- package/src/components/ui/sidebar.tsx +730 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/slider.tsx +51 -0
- package/src/components/ui/spinner.tsx +16 -0
- package/src/components/ui/switch.tsx +31 -0
- package/src/components/ui/table.tsx +113 -0
- package/src/components/ui/tabs.tsx +82 -0
- package/src/components/ui/textarea.tsx +17 -0
- package/src/components/ui/toast.tsx +229 -0
- package/src/components/ui/toggle-group.tsx +87 -0
- package/src/components/ui/toggle.tsx +43 -0
- package/src/components/ui/tooltip.tsx +65 -0
- package/src/components.ts +78 -0
- package/src/config.ts +56 -0
- package/src/define.ts +122 -0
- package/src/doc-context.ts +20 -0
- package/src/editor.ts +94 -0
- package/src/format-error.ts +78 -0
- package/src/guards.ts +84 -0
- package/src/hooks/use-mobile.ts +21 -0
- package/src/html.ts +91 -0
- package/src/hydrate/export-index.ts +232 -0
- package/src/hydrate/import-scan.ts +169 -0
- package/src/hydrate/plugins.ts +118 -0
- package/src/hydrate/runtime-module.ts +145 -0
- package/src/hydrate-runtime.ts +67 -0
- package/src/hydrate.ts +147 -0
- package/src/index.ts +16 -0
- package/src/init.ts +57 -0
- package/src/langs.ts +148 -0
- package/src/lines.ts +53 -0
- package/src/load-user-module.ts +191 -0
- package/src/mdx.ts +248 -0
- package/src/paths.ts +36 -0
- package/src/rehype/shiki.ts +533 -0
- package/src/remark/alerts.ts +53 -0
- package/src/remark/ast.ts +96 -0
- package/src/remark/callouts.ts +25 -0
- package/src/remark/code-file.ts +85 -0
- package/src/remark/code-meta.ts +21 -0
- package/src/remark/directives.ts +170 -0
- package/src/remark/file-paths.ts +64 -0
- package/src/remark/headings.ts +131 -0
- package/src/remark/no-js.ts +40 -0
- package/src/render.ts +337 -0
- package/src/serve.ts +322 -0
- package/src/styles/globals.css +134 -0
- package/src/styles/shadcn.css +641 -0
- package/src/tailwind.ts +119 -0
- package/src/ui/approvals.tsx +76 -0
- package/src/ui/ask-question.tsx +386 -0
- package/src/ui/ask.tsx +206 -0
- package/src/ui/attrs.ts +51 -0
- package/src/ui/audit.tsx +139 -0
- package/src/ui/bar-chart.tsx +334 -0
- package/src/ui/benchmarks.tsx +143 -0
- package/src/ui/bits.tsx +537 -0
- package/src/ui/board.tsx +173 -0
- package/src/ui/bridge.tsx +207 -0
- package/src/ui/bumps.tsx +178 -0
- package/src/ui/callout.tsx +106 -0
- package/src/ui/changes.tsx +89 -0
- package/src/ui/chart-bits.tsx +52 -0
- package/src/ui/chart.ts +577 -0
- package/src/ui/checks.tsx +203 -0
- package/src/ui/child-index.tsx +44 -0
- package/src/ui/children.ts +43 -0
- package/src/ui/chips.tsx +49 -0
- package/src/ui/cmd.tsx +27 -0
- package/src/ui/columns.tsx +31 -0
- package/src/ui/comments.tsx +544 -0
- package/src/ui/compare.tsx +67 -0
- package/src/ui/decision.tsx +79 -0
- package/src/ui/deps.tsx +78 -0
- package/src/ui/details.tsx +43 -0
- package/src/ui/diff-parse.ts +307 -0
- package/src/ui/diff.tsx +458 -0
- package/src/ui/diffstat.tsx +58 -0
- package/src/ui/due.tsx +65 -0
- package/src/ui/effort.tsx +29 -0
- package/src/ui/endpoints.tsx +118 -0
- package/src/ui/envvars.tsx +96 -0
- package/src/ui/figure.tsx +37 -0
- package/src/ui/file-icon.ts +1020 -0
- package/src/ui/file-link.ts +32 -0
- package/src/ui/file-ref.tsx +39 -0
- package/src/ui/files.tsx +112 -0
- package/src/ui/findings.tsx +85 -0
- package/src/ui/flow.tsx +73 -0
- package/src/ui/funnel.tsx +121 -0
- package/src/ui/gantt.tsx +443 -0
- package/src/ui/gauges.tsx +135 -0
- package/src/ui/glossary.tsx +29 -0
- package/src/ui/graph-layout.ts +149 -0
- package/src/ui/graph-specs.tsx +102 -0
- package/src/ui/graph.tsx +278 -0
- package/src/ui/grid.tsx +119 -0
- package/src/ui/hypothesis.tsx +94 -0
- package/src/ui/icon.tsx +80 -0
- package/src/ui/incident.tsx +130 -0
- package/src/ui/index.ts +342 -0
- package/src/ui/ins-del.tsx +41 -0
- package/src/ui/json.tsx +190 -0
- package/src/ui/layout.ts +9 -0
- package/src/ui/line-chart.tsx +251 -0
- package/src/ui/matrix.tsx +208 -0
- package/src/ui/meta.tsx +73 -0
- package/src/ui/option.tsx +64 -0
- package/src/ui/owner.tsx +40 -0
- package/src/ui/packages.tsx +104 -0
- package/src/ui/pathway.tsx +96 -0
- package/src/ui/phase.tsx +41 -0
- package/src/ui/pie-chart.tsx +170 -0
- package/src/ui/plan.tsx +77 -0
- package/src/ui/pre.tsx +175 -0
- package/src/ui/priority.tsx +51 -0
- package/src/ui/props.tsx +77 -0
- package/src/ui/quadrant.tsx +172 -0
- package/src/ui/radar.tsx +200 -0
- package/src/ui/ref.tsx +160 -0
- package/src/ui/release.tsx +178 -0
- package/src/ui/req.tsx +42 -0
- package/src/ui/review.tsx +133 -0
- package/src/ui/risk.tsx +67 -0
- package/src/ui/sankey.tsx +287 -0
- package/src/ui/scatter.tsx +237 -0
- package/src/ui/schema.tsx +113 -0
- package/src/ui/score.tsx +105 -0
- package/src/ui/search.tsx +120 -0
- package/src/ui/series.tsx +38 -0
- package/src/ui/severity.tsx +69 -0
- package/src/ui/shadcn.tsx +216 -0
- package/src/ui/spark.tsx +86 -0
- package/src/ui/stack.tsx +57 -0
- package/src/ui/stats.tsx +63 -0
- package/src/ui/status-badge.tsx +66 -0
- package/src/ui/statuspage.tsx +238 -0
- package/src/ui/steps.tsx +74 -0
- package/src/ui/summary.tsx +41 -0
- package/src/ui/symbol-ref.tsx +73 -0
- package/src/ui/terminal.tsx +117 -0
- package/src/ui/tests.tsx +218 -0
- package/src/ui/timeline.tsx +63 -0
- package/src/ui/toc.tsx +56 -0
- package/src/ui/tones.ts +187 -0
- package/src/ui/trace.tsx +69 -0
- package/src/ui/tree.tsx +281 -0
- package/src/ui/treemap.tsx +128 -0
- package/src/ui/venn.tsx +258 -0
- package/src/ui/verdict.tsx +78 -0
- package/src/ui/waterfall.tsx +142 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { handleDocEvent, syncBoards } from "./doc-events.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Document entry point — bundled to an IIFE by `client-js.ts` and inlined
|
|
5
|
+
* into every rendered page. Registers the delegated handler, then seeds
|
|
6
|
+
* each Ask output pane (default-checked fields count as answers) by
|
|
7
|
+
* bubbling a synthetic `input` event off the block — the handler's own
|
|
8
|
+
* input branch does the render, so no serialization code is duplicated.
|
|
9
|
+
*/
|
|
10
|
+
for (const type of [
|
|
11
|
+
"click",
|
|
12
|
+
"input",
|
|
13
|
+
"change",
|
|
14
|
+
"keydown",
|
|
15
|
+
"dragstart",
|
|
16
|
+
"dragover",
|
|
17
|
+
"drop",
|
|
18
|
+
"dragend",
|
|
19
|
+
]) {
|
|
20
|
+
document.addEventListener(type, handleDocEvent);
|
|
21
|
+
}
|
|
22
|
+
for (const b of document.querySelectorAll("[data-ask]")) {
|
|
23
|
+
b.dispatchEvent(new Event("input", { bubbles: true }));
|
|
24
|
+
}
|
|
25
|
+
// Move-button `disabled` state depends on each card's lane position —
|
|
26
|
+
// client-side knowledge. Seed it once (and again after every move).
|
|
27
|
+
syncBoards(document);
|
package/src/client-js.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
|
|
3
|
+
import { build } from "esbuild";
|
|
4
|
+
|
|
5
|
+
import { pkgRoot } from "./paths.js";
|
|
6
|
+
|
|
7
|
+
let cache: Promise<string> | undefined;
|
|
8
|
+
|
|
9
|
+
const buildClientJs = async (): Promise<string> => {
|
|
10
|
+
const result = await build({
|
|
11
|
+
absWorkingDir: pkgRoot,
|
|
12
|
+
bundle: true,
|
|
13
|
+
format: "iife",
|
|
14
|
+
logLevel: "silent",
|
|
15
|
+
minify: true,
|
|
16
|
+
platform: "browser",
|
|
17
|
+
stdin: {
|
|
18
|
+
contents: 'import "./client/entry.js";',
|
|
19
|
+
loader: "js",
|
|
20
|
+
resolveDir: path.join(pkgRoot, "src"),
|
|
21
|
+
sourcefile: "mdxr-client.js",
|
|
22
|
+
},
|
|
23
|
+
target: "es2022",
|
|
24
|
+
write: false,
|
|
25
|
+
});
|
|
26
|
+
return result.outputFiles[0]?.text ?? "";
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Vanilla JS inlined into every document (copy/answer/save buttons, the
|
|
31
|
+
* live Markdown answer sheet, the theme toggle). Bundled from
|
|
32
|
+
* `src/client/entry.ts` at render time — real source, so the script is
|
|
33
|
+
* type-checked and unit-testable, and bundler changes can't silently
|
|
34
|
+
* break it the way `fn.toString()` serialization could. Memoized: the
|
|
35
|
+
* bundle is identical for every render in a process.
|
|
36
|
+
*/
|
|
37
|
+
export const clientJs = async (): Promise<string> => {
|
|
38
|
+
cache ??= buildClientJs();
|
|
39
|
+
try {
|
|
40
|
+
return await cache;
|
|
41
|
+
} catch (error) {
|
|
42
|
+
// A rejected bundle promise would otherwise poison every later render
|
|
43
|
+
// in this process (mdxr serve keeps failing on one transient error).
|
|
44
|
+
cache = undefined;
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ComponentMap, MdxrComponent } from "./define.js";
|
|
2
|
+
import { isComponent, isRecord } from "./guards.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `into[k] = v` with `k === "__proto__"` would silently replace the map's
|
|
6
|
+
* prototype instead of registering the component — define it as data.
|
|
7
|
+
*/
|
|
8
|
+
const put = (into: ComponentMap, k: string, v: MdxrComponent): void => {
|
|
9
|
+
Object.defineProperty(into, k, {
|
|
10
|
+
configurable: true,
|
|
11
|
+
enumerable: true,
|
|
12
|
+
value: v,
|
|
13
|
+
writable: true,
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/** A default-exported object is treated as a `{ Name: Component }` map. */
|
|
18
|
+
const mergeDefaultMap = (val: unknown, into: ComponentMap): void => {
|
|
19
|
+
if (!isRecord(val)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
for (const [k, v] of Object.entries(val)) {
|
|
23
|
+
if (isComponent(v)) {
|
|
24
|
+
put(into, k, v);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Merge a user module's exports into a ComponentMap. A default-exported
|
|
31
|
+
* object is treated as a `{ Name: Component }` map; PascalCase named exports
|
|
32
|
+
* that are functions count directly. Shared by the SSR loader (render.ts)
|
|
33
|
+
* and the hydration bundle (hydrate-runtime.ts) — node-free on purpose.
|
|
34
|
+
*/
|
|
35
|
+
export const mergeUserComponents = (
|
|
36
|
+
mod: Record<string, unknown>,
|
|
37
|
+
into: ComponentMap = {}
|
|
38
|
+
): ComponentMap => {
|
|
39
|
+
for (const [key, val] of Object.entries(mod)) {
|
|
40
|
+
if (key === "default") {
|
|
41
|
+
mergeDefaultMap(val, into);
|
|
42
|
+
} else if (isComponent(val) && /^[A-Z]/u.test(key)) {
|
|
43
|
+
put(into, key, val);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return into;
|
|
47
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion";
|
|
2
|
+
import { cn } from "cn";
|
|
3
|
+
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {
|
|
6
|
+
return (
|
|
7
|
+
<AccordionPrimitive.Root
|
|
8
|
+
data-slot="accordion"
|
|
9
|
+
className={cn("flex w-full flex-col", className)}
|
|
10
|
+
{...props}
|
|
11
|
+
/>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {
|
|
16
|
+
return (
|
|
17
|
+
<AccordionPrimitive.Item
|
|
18
|
+
data-slot="accordion-item"
|
|
19
|
+
className={cn("not-last:border-b", className)}
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function AccordionTrigger({
|
|
26
|
+
className,
|
|
27
|
+
children,
|
|
28
|
+
...props
|
|
29
|
+
}: AccordionPrimitive.Trigger.Props) {
|
|
30
|
+
return (
|
|
31
|
+
<AccordionPrimitive.Header className="flex">
|
|
32
|
+
<AccordionPrimitive.Trigger
|
|
33
|
+
data-slot="accordion-trigger"
|
|
34
|
+
className={cn(
|
|
35
|
+
"group/accordion-trigger focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:after:border-ring **:data-[slot=accordion-trigger-icon]:text-muted-foreground relative flex flex-1 items-start justify-between rounded-lg border border-transparent py-2.5 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-3 aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4",
|
|
36
|
+
className
|
|
37
|
+
)}
|
|
38
|
+
{...props}
|
|
39
|
+
>
|
|
40
|
+
{children}
|
|
41
|
+
<ChevronDownIcon
|
|
42
|
+
data-slot="accordion-trigger-icon"
|
|
43
|
+
className="pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden"
|
|
44
|
+
/>
|
|
45
|
+
<ChevronUpIcon
|
|
46
|
+
data-slot="accordion-trigger-icon"
|
|
47
|
+
className="pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline"
|
|
48
|
+
/>
|
|
49
|
+
</AccordionPrimitive.Trigger>
|
|
50
|
+
</AccordionPrimitive.Header>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function AccordionContent({
|
|
55
|
+
className,
|
|
56
|
+
children,
|
|
57
|
+
...props
|
|
58
|
+
}: AccordionPrimitive.Panel.Props) {
|
|
59
|
+
return (
|
|
60
|
+
<AccordionPrimitive.Panel
|
|
61
|
+
data-slot="accordion-content"
|
|
62
|
+
className="data-open:animate-accordion-down data-closed:animate-accordion-up overflow-hidden text-sm"
|
|
63
|
+
{...props}
|
|
64
|
+
>
|
|
65
|
+
<div
|
|
66
|
+
className={cn(
|
|
67
|
+
"[&_a]:hover:text-foreground h-(--accordion-panel-height) pt-0 pb-2.5 data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4",
|
|
68
|
+
className
|
|
69
|
+
)}
|
|
70
|
+
>
|
|
71
|
+
{children}
|
|
72
|
+
</div>
|
|
73
|
+
</AccordionPrimitive.Panel>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog";
|
|
2
|
+
import { cn } from "cn";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
import { Button } from "./button.js";
|
|
6
|
+
|
|
7
|
+
function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) {
|
|
8
|
+
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) {
|
|
12
|
+
return (
|
|
13
|
+
<AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) {
|
|
18
|
+
return (
|
|
19
|
+
<AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function AlertDialogOverlay({
|
|
24
|
+
className,
|
|
25
|
+
...props
|
|
26
|
+
}: AlertDialogPrimitive.Backdrop.Props) {
|
|
27
|
+
return (
|
|
28
|
+
<AlertDialogPrimitive.Backdrop
|
|
29
|
+
data-slot="alert-dialog-overlay"
|
|
30
|
+
className={cn(
|
|
31
|
+
"data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0 fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs",
|
|
32
|
+
className
|
|
33
|
+
)}
|
|
34
|
+
{...props}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function AlertDialogContent({
|
|
40
|
+
className,
|
|
41
|
+
size = "default",
|
|
42
|
+
...props
|
|
43
|
+
}: AlertDialogPrimitive.Popup.Props & {
|
|
44
|
+
size?: "default" | "sm";
|
|
45
|
+
}) {
|
|
46
|
+
return (
|
|
47
|
+
<AlertDialogPortal>
|
|
48
|
+
<AlertDialogOverlay />
|
|
49
|
+
<AlertDialogPrimitive.Popup
|
|
50
|
+
data-slot="alert-dialog-content"
|
|
51
|
+
data-size={size}
|
|
52
|
+
className={cn(
|
|
53
|
+
"group/alert-dialog-content bg-popover text-popover-foreground ring-foreground/10 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl p-4 ring-1 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm",
|
|
54
|
+
className
|
|
55
|
+
)}
|
|
56
|
+
{...props}
|
|
57
|
+
/>
|
|
58
|
+
</AlertDialogPortal>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function AlertDialogHeader({
|
|
63
|
+
className,
|
|
64
|
+
...props
|
|
65
|
+
}: React.ComponentProps<"div">) {
|
|
66
|
+
return (
|
|
67
|
+
<div
|
|
68
|
+
data-slot="alert-dialog-header"
|
|
69
|
+
className={cn(
|
|
70
|
+
"grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",
|
|
71
|
+
className
|
|
72
|
+
)}
|
|
73
|
+
{...props}
|
|
74
|
+
/>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function AlertDialogFooter({
|
|
79
|
+
className,
|
|
80
|
+
...props
|
|
81
|
+
}: React.ComponentProps<"div">) {
|
|
82
|
+
return (
|
|
83
|
+
<div
|
|
84
|
+
data-slot="alert-dialog-footer"
|
|
85
|
+
className={cn(
|
|
86
|
+
"bg-muted/50 -mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
|
|
87
|
+
className
|
|
88
|
+
)}
|
|
89
|
+
{...props}
|
|
90
|
+
/>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function AlertDialogMedia({
|
|
95
|
+
className,
|
|
96
|
+
...props
|
|
97
|
+
}: React.ComponentProps<"div">) {
|
|
98
|
+
return (
|
|
99
|
+
<div
|
|
100
|
+
data-slot="alert-dialog-media"
|
|
101
|
+
className={cn(
|
|
102
|
+
"bg-muted mb-2 inline-flex size-10 items-center justify-center rounded-md sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6",
|
|
103
|
+
className
|
|
104
|
+
)}
|
|
105
|
+
{...props}
|
|
106
|
+
/>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function AlertDialogTitle({
|
|
111
|
+
className,
|
|
112
|
+
...props
|
|
113
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
|
|
114
|
+
return (
|
|
115
|
+
<AlertDialogPrimitive.Title
|
|
116
|
+
data-slot="alert-dialog-title"
|
|
117
|
+
className={cn(
|
|
118
|
+
"font-heading text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",
|
|
119
|
+
className
|
|
120
|
+
)}
|
|
121
|
+
{...props}
|
|
122
|
+
/>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function AlertDialogDescription({
|
|
127
|
+
className,
|
|
128
|
+
...props
|
|
129
|
+
}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
|
|
130
|
+
return (
|
|
131
|
+
<AlertDialogPrimitive.Description
|
|
132
|
+
data-slot="alert-dialog-description"
|
|
133
|
+
className={cn(
|
|
134
|
+
"text-muted-foreground *:[a]:hover:text-foreground text-sm text-balance md:text-pretty *:[a]:underline *:[a]:underline-offset-3",
|
|
135
|
+
className
|
|
136
|
+
)}
|
|
137
|
+
{...props}
|
|
138
|
+
/>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function AlertDialogAction({
|
|
143
|
+
className,
|
|
144
|
+
...props
|
|
145
|
+
}: React.ComponentProps<typeof Button>) {
|
|
146
|
+
return (
|
|
147
|
+
<Button
|
|
148
|
+
data-slot="alert-dialog-action"
|
|
149
|
+
className={cn(className)}
|
|
150
|
+
{...props}
|
|
151
|
+
/>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function AlertDialogCancel({
|
|
156
|
+
className,
|
|
157
|
+
variant = "outline",
|
|
158
|
+
size = "default",
|
|
159
|
+
...props
|
|
160
|
+
}: AlertDialogPrimitive.Close.Props &
|
|
161
|
+
Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
|
|
162
|
+
return (
|
|
163
|
+
<AlertDialogPrimitive.Close
|
|
164
|
+
data-slot="alert-dialog-cancel"
|
|
165
|
+
className={cn(className)}
|
|
166
|
+
render={<Button variant={variant} size={size} />}
|
|
167
|
+
{...props}
|
|
168
|
+
/>
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export {
|
|
173
|
+
AlertDialog,
|
|
174
|
+
AlertDialogAction,
|
|
175
|
+
AlertDialogCancel,
|
|
176
|
+
AlertDialogContent,
|
|
177
|
+
AlertDialogDescription,
|
|
178
|
+
AlertDialogFooter,
|
|
179
|
+
AlertDialogHeader,
|
|
180
|
+
AlertDialogMedia,
|
|
181
|
+
AlertDialogOverlay,
|
|
182
|
+
AlertDialogPortal,
|
|
183
|
+
AlertDialogTitle,
|
|
184
|
+
AlertDialogTrigger,
|
|
185
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { cva } from "class-variance-authority";
|
|
2
|
+
import type { VariantProps } from "class-variance-authority";
|
|
3
|
+
import { cn } from "cn";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
|
|
6
|
+
const alertVariants = cva(
|
|
7
|
+
"group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4",
|
|
8
|
+
{
|
|
9
|
+
defaultVariants: {
|
|
10
|
+
variant: "default",
|
|
11
|
+
},
|
|
12
|
+
variants: {
|
|
13
|
+
variant: {
|
|
14
|
+
default: "bg-card text-card-foreground",
|
|
15
|
+
destructive:
|
|
16
|
+
"bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
function Alert({
|
|
23
|
+
className,
|
|
24
|
+
variant,
|
|
25
|
+
...props
|
|
26
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
data-slot="alert"
|
|
30
|
+
role="alert"
|
|
31
|
+
className={cn(alertVariants({ variant }), className)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
38
|
+
return (
|
|
39
|
+
<div
|
|
40
|
+
data-slot="alert-title"
|
|
41
|
+
className={cn(
|
|
42
|
+
"[&_a]:hover:text-foreground font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3",
|
|
43
|
+
className
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function AlertDescription({
|
|
51
|
+
className,
|
|
52
|
+
...props
|
|
53
|
+
}: React.ComponentProps<"div">) {
|
|
54
|
+
return (
|
|
55
|
+
<div
|
|
56
|
+
data-slot="alert-description"
|
|
57
|
+
className={cn(
|
|
58
|
+
"text-muted-foreground [&_a]:hover:text-foreground text-sm text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_p:not(:last-child)]:mb-4",
|
|
59
|
+
className
|
|
60
|
+
)}
|
|
61
|
+
{...props}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
67
|
+
return (
|
|
68
|
+
<div
|
|
69
|
+
data-slot="alert-action"
|
|
70
|
+
className={cn("absolute top-2 right-2", className)}
|
|
71
|
+
{...props}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { Alert, AlertTitle, AlertDescription, AlertAction };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { cn } from "cn";
|
|
2
|
+
|
|
3
|
+
function AspectRatio({
|
|
4
|
+
ratio,
|
|
5
|
+
className,
|
|
6
|
+
...props
|
|
7
|
+
}: React.ComponentProps<"div"> & { ratio: number }) {
|
|
8
|
+
return (
|
|
9
|
+
<div
|
|
10
|
+
data-slot="aspect-ratio"
|
|
11
|
+
style={
|
|
12
|
+
{
|
|
13
|
+
"--ratio": ratio,
|
|
14
|
+
} as React.CSSProperties
|
|
15
|
+
}
|
|
16
|
+
className={cn("relative aspect-(--ratio)", className)}
|
|
17
|
+
{...props}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { AspectRatio };
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { mergeProps } from "@base-ui/react/merge-props";
|
|
2
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
3
|
+
import { cva } from "class-variance-authority";
|
|
4
|
+
import type { VariantProps } from "class-variance-authority";
|
|
5
|
+
import { cn } from "cn";
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
|
|
8
|
+
import { Button } from "./button.js";
|
|
9
|
+
|
|
10
|
+
const attachmentVariants = cva(
|
|
11
|
+
"group/attachment bg-card text-card-foreground focus-within:ring-ring/50 has-[>a,>button]:hover:bg-muted/50 data-[state=error]:border-destructive/30 relative flex w-fit max-w-full min-w-0 shrink-0 flex-wrap rounded-xl border transition-colors focus-within:ring-1 data-[state=idle]:border-dashed",
|
|
12
|
+
{
|
|
13
|
+
variants: {
|
|
14
|
+
orientation: {
|
|
15
|
+
horizontal: "min-w-40 items-center",
|
|
16
|
+
vertical: "w-24 flex-col has-data-[slot=attachment-content]:w-30",
|
|
17
|
+
},
|
|
18
|
+
size: {
|
|
19
|
+
default:
|
|
20
|
+
"gap-2 text-sm has-data-[slot=attachment-content]:px-2.5 has-data-[slot=attachment-content]:py-2 has-data-[slot=attachment-media]:p-2",
|
|
21
|
+
sm: "gap-2.5 text-xs has-data-[slot=attachment-content]:px-2 has-data-[slot=attachment-content]:py-1.5 has-data-[slot=attachment-media]:p-1.5",
|
|
22
|
+
xs: "gap-1.5 rounded-lg text-xs has-data-[slot=attachment-content]:px-1.5 has-data-[slot=attachment-content]:py-1 has-data-[slot=attachment-media]:p-1",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
function Attachment({
|
|
29
|
+
className,
|
|
30
|
+
state = "done",
|
|
31
|
+
size = "default",
|
|
32
|
+
orientation = "horizontal",
|
|
33
|
+
...props
|
|
34
|
+
}: React.ComponentProps<"div"> &
|
|
35
|
+
VariantProps<typeof attachmentVariants> & {
|
|
36
|
+
state?: "idle" | "uploading" | "processing" | "error" | "done";
|
|
37
|
+
}) {
|
|
38
|
+
return (
|
|
39
|
+
<div
|
|
40
|
+
data-slot="attachment"
|
|
41
|
+
data-state={state}
|
|
42
|
+
data-size={size}
|
|
43
|
+
data-orientation={orientation}
|
|
44
|
+
className={cn(attachmentVariants({ orientation, size }), className)}
|
|
45
|
+
{...props}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const attachmentMediaVariants = cva(
|
|
51
|
+
"bg-muted text-foreground group-data-[state=error]/attachment:bg-destructive/10 group-data-[state=error]/attachment:text-destructive relative flex aspect-square w-10 shrink-0 items-center justify-center overflow-hidden rounded-lg group-data-[orientation=vertical]/attachment:w-full group-data-[size=sm]/attachment:w-8 group-data-[size=xs]/attachment:w-7 group-data-[size=xs]/attachment:rounded-md group-data-[orientation=vertical]/attachment:*:data-[slot=spinner]:size-6! [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 group-data-[orientation=vertical]/attachment:[&_svg:not([class*='size-'])]:size-6 group-data-[size=xs]/attachment:[&_svg:not([class*='size-'])]:size-3.5",
|
|
52
|
+
{
|
|
53
|
+
defaultVariants: {
|
|
54
|
+
variant: "icon",
|
|
55
|
+
},
|
|
56
|
+
variants: {
|
|
57
|
+
variant: {
|
|
58
|
+
icon: "",
|
|
59
|
+
image:
|
|
60
|
+
"opacity-60 group-data-[state=done]/attachment:opacity-100 group-data-[state=idle]/attachment:opacity-100 *:[img]:aspect-square *:[img]:w-full *:[img]:object-cover",
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
function AttachmentMedia({
|
|
67
|
+
className,
|
|
68
|
+
variant = "icon",
|
|
69
|
+
...props
|
|
70
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof attachmentMediaVariants>) {
|
|
71
|
+
return (
|
|
72
|
+
<div
|
|
73
|
+
data-slot="attachment-media"
|
|
74
|
+
data-variant={variant}
|
|
75
|
+
className={cn(attachmentMediaVariants({ variant }), className)}
|
|
76
|
+
{...props}
|
|
77
|
+
/>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function AttachmentContent({
|
|
82
|
+
className,
|
|
83
|
+
...props
|
|
84
|
+
}: React.ComponentProps<"div">) {
|
|
85
|
+
return (
|
|
86
|
+
<div
|
|
87
|
+
data-slot="attachment-content"
|
|
88
|
+
className={cn(
|
|
89
|
+
"max-w-full min-w-0 flex-1 leading-tight group-data-[orientation=vertical]/attachment:px-1",
|
|
90
|
+
className
|
|
91
|
+
)}
|
|
92
|
+
{...props}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function AttachmentTitle({
|
|
98
|
+
className,
|
|
99
|
+
...props
|
|
100
|
+
}: React.ComponentProps<"span">) {
|
|
101
|
+
return (
|
|
102
|
+
<span
|
|
103
|
+
data-slot="attachment-title"
|
|
104
|
+
className={cn(
|
|
105
|
+
"group-data-[state=processing]/attachment:shimmer group-data-[state=uploading]/attachment:shimmer block max-w-full min-w-0 truncate font-medium",
|
|
106
|
+
className
|
|
107
|
+
)}
|
|
108
|
+
{...props}
|
|
109
|
+
/>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function AttachmentDescription({
|
|
114
|
+
className,
|
|
115
|
+
...props
|
|
116
|
+
}: React.ComponentProps<"span">) {
|
|
117
|
+
return (
|
|
118
|
+
<span
|
|
119
|
+
data-slot="attachment-description"
|
|
120
|
+
className={cn(
|
|
121
|
+
"text-muted-foreground group-data-[state=error]/attachment:text-destructive/80 mt-0.5 block min-w-0 truncate text-xs",
|
|
122
|
+
"max-w-full",
|
|
123
|
+
className
|
|
124
|
+
)}
|
|
125
|
+
{...props}
|
|
126
|
+
/>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function AttachmentActions({
|
|
131
|
+
className,
|
|
132
|
+
...props
|
|
133
|
+
}: React.ComponentProps<"div">) {
|
|
134
|
+
return (
|
|
135
|
+
<div
|
|
136
|
+
data-slot="attachment-actions"
|
|
137
|
+
className={cn(
|
|
138
|
+
"relative z-20 flex shrink-0 items-center group-data-[orientation=vertical]/attachment:absolute group-data-[orientation=vertical]/attachment:top-3 group-data-[orientation=vertical]/attachment:right-3 group-data-[orientation=vertical]/attachment:gap-1",
|
|
139
|
+
className
|
|
140
|
+
)}
|
|
141
|
+
{...props}
|
|
142
|
+
/>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function AttachmentAction({
|
|
147
|
+
className,
|
|
148
|
+
variant,
|
|
149
|
+
size = "icon-xs",
|
|
150
|
+
...props
|
|
151
|
+
}: React.ComponentProps<typeof Button>) {
|
|
152
|
+
return (
|
|
153
|
+
<Button
|
|
154
|
+
data-slot="attachment-action"
|
|
155
|
+
variant={variant ?? "ghost"}
|
|
156
|
+
size={size}
|
|
157
|
+
className={cn(className)}
|
|
158
|
+
{...props}
|
|
159
|
+
/>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function AttachmentTrigger({
|
|
164
|
+
className,
|
|
165
|
+
render,
|
|
166
|
+
type,
|
|
167
|
+
...props
|
|
168
|
+
}: useRender.ComponentProps<"button">) {
|
|
169
|
+
return useRender({
|
|
170
|
+
defaultTagName: "button",
|
|
171
|
+
props: mergeProps<"button">(
|
|
172
|
+
{
|
|
173
|
+
className: cn("absolute inset-0 z-10 outline-none", className),
|
|
174
|
+
type: render ? type : (type ?? "button"),
|
|
175
|
+
},
|
|
176
|
+
props
|
|
177
|
+
),
|
|
178
|
+
render,
|
|
179
|
+
state: {
|
|
180
|
+
slot: "attachment-trigger",
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function AttachmentGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
186
|
+
return (
|
|
187
|
+
<div
|
|
188
|
+
data-slot="attachment-group"
|
|
189
|
+
className={cn(
|
|
190
|
+
"scroll-fade-x no-scrollbar flex min-w-0 snap-x snap-mandatory scroll-px-1 gap-3 overflow-x-auto overscroll-x-contain py-1 *:data-[slot=attachment]:flex-none *:data-[slot=attachment]:snap-start",
|
|
191
|
+
className
|
|
192
|
+
)}
|
|
193
|
+
{...props}
|
|
194
|
+
/>
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export {
|
|
199
|
+
Attachment,
|
|
200
|
+
AttachmentGroup,
|
|
201
|
+
AttachmentMedia,
|
|
202
|
+
AttachmentContent,
|
|
203
|
+
AttachmentTitle,
|
|
204
|
+
AttachmentDescription,
|
|
205
|
+
AttachmentActions,
|
|
206
|
+
AttachmentAction,
|
|
207
|
+
AttachmentTrigger,
|
|
208
|
+
};
|