@krizaka/ui 3.4.0 → 3.6.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/README.md +1 -0
- package/dist/app-shell.d.ts +24 -22
- package/dist/app-shell.js +9 -3
- package/dist/app-shell.js.map +1 -1
- package/dist/argument-card.js +3 -3
- package/dist/chat.d.ts +187 -0
- package/dist/chat.js +132 -0
- package/dist/chat.js.map +1 -0
- package/dist/chunk-3GODX3D6.js +25 -0
- package/dist/chunk-3GODX3D6.js.map +1 -0
- package/dist/chunk-ECSCA3CN.js +128 -0
- package/dist/chunk-ECSCA3CN.js.map +1 -0
- package/dist/chunk-F2GKFIYK.js +47 -0
- package/dist/chunk-F2GKFIYK.js.map +1 -0
- package/dist/{chunk-R6SDS7JM.js → chunk-ND3L5VHT.js} +25 -2
- package/dist/chunk-ND3L5VHT.js.map +1 -0
- package/dist/command.js +1 -1
- package/dist/data-table.js +20 -134
- package/dist/data-table.js.map +1 -1
- package/dist/dialog.js +7 -3
- package/dist/dialog.js.map +1 -1
- package/dist/loader.d.ts +21 -1
- package/dist/loader.js +7 -3
- package/dist/loader.js.map +1 -1
- package/dist/map.js +7 -1
- package/dist/map.js.map +1 -1
- package/dist/marketing-layout.d.ts +3 -9
- package/dist/marketing-layout.js +24 -7
- package/dist/marketing-layout.js.map +1 -1
- package/dist/match-dialog.d.ts +32 -0
- package/dist/match-dialog.js +168 -0
- package/dist/match-dialog.js.map +1 -0
- package/dist/native.d.ts +484 -106
- package/dist/native.js +1967 -1323
- package/dist/native.js.map +1 -1
- package/dist/page-hero.js +3 -3
- package/dist/photo-grid.d.ts +122 -0
- package/dist/photo-grid.js +94 -0
- package/dist/photo-grid.js.map +1 -0
- package/dist/skip-link.d.ts +15 -0
- package/dist/skip-link.js +10 -0
- package/dist/skip-link.js.map +1 -0
- package/dist/step-progress.d.ts +20 -0
- package/dist/step-progress.js +17 -0
- package/dist/step-progress.js.map +1 -0
- package/dist/swipe-deck.d.ts +183 -0
- package/dist/swipe-deck.js +144 -0
- package/dist/swipe-deck.js.map +1 -0
- package/dist/tag-selector.d.ts +26 -0
- package/dist/tag-selector.js +21 -0
- package/dist/tag-selector.js.map +1 -0
- package/dist/tree-view.d.ts +2 -0
- package/dist/tree-view.js.map +1 -1
- package/dist/verified-badge.d.ts +16 -0
- package/dist/verified-badge.js +23 -0
- package/dist/verified-badge.js.map +1 -0
- package/package.json +120 -8
- package/registry/achievement.json +2 -1
- package/registry/action-bar.json +2 -1
- package/registry/action-sheet.json +1 -0
- package/registry/activity-feed.json +2 -1
- package/registry/alert.json +2 -1
- package/registry/app-shell.json +27 -5
- package/registry/argument-card.json +2 -1
- package/registry/audio-player.json +2 -1
- package/registry/auth-layout.json +7 -2
- package/registry/avatar.json +2 -1
- package/registry/badge.json +2 -1
- package/registry/button.json +2 -1
- package/registry/card-grid.json +2 -1
- package/registry/card.json +2 -1
- package/registry/catalogue-page.json +5 -2
- package/registry/changelog-page.json +5 -2
- package/registry/chat.json +918 -0
- package/registry/checkbox.json +2 -1
- package/registry/chip-link.json +2 -1
- package/registry/chip.json +2 -1
- package/registry/choice-grid.json +2 -1
- package/registry/cn.json +1 -0
- package/registry/code-block.json +2 -1
- package/registry/combobox.json +2 -1
- package/registry/command.json +2 -1
- package/registry/component-page.json +5 -2
- package/registry/confirm-button.json +2 -1
- package/registry/contact-page.json +5 -2
- package/registry/continue-prompt.json +2 -1
- package/registry/countdown.json +2 -1
- package/registry/cta-panel.json +2 -1
- package/registry/dashboard-layout.json +5 -2
- package/registry/data-table.json +2 -1
- package/registry/date-picker.json +3 -2
- package/registry/decision-list.json +2 -1
- package/registry/description-list.json +2 -1
- package/registry/detail-layout.json +16 -2
- package/registry/dialog.json +10 -4
- package/registry/docs-article-page.json +16 -2
- package/registry/docs-hub-page.json +5 -2
- package/registry/docs-layout.json +2 -1
- package/registry/dropdown-menu.json +2 -1
- package/registry/empty-state.json +14 -2
- package/registry/error-page.json +5 -2
- package/registry/examples/chat/conversation.d.ts +4 -0
- package/registry/examples/chat/conversation.js +22 -0
- package/registry/examples/chat/conversation.tsx +21 -0
- package/registry/examples/chat/inbox.d.ts +4 -0
- package/registry/examples/chat/inbox.js +15 -0
- package/registry/examples/chat/inbox.tsx +12 -0
- package/registry/examples/chat/native/conversation.d.ts +4 -0
- package/registry/examples/chat/native/conversation.dark.png +0 -0
- package/registry/examples/chat/native/conversation.js +23 -0
- package/registry/examples/chat/native/conversation.light.png +0 -0
- package/registry/examples/chat/native/conversation.tsx +20 -0
- package/registry/examples/chat/native/inbox.d.ts +4 -0
- package/registry/examples/chat/native/inbox.dark.png +0 -0
- package/registry/examples/chat/native/inbox.js +16 -0
- package/registry/examples/chat/native/inbox.light.png +0 -0
- package/registry/examples/chat/native/inbox.tsx +13 -0
- package/registry/examples/detail-layout/checkout.d.ts +4 -0
- package/registry/examples/detail-layout/checkout.js +37 -0
- package/registry/examples/detail-layout/checkout.tsx +44 -0
- package/registry/examples/docs-article-page/faq.d.ts +4 -0
- package/registry/examples/docs-article-page/faq.js +31 -0
- package/registry/examples/docs-article-page/faq.tsx +40 -0
- package/registry/examples/empty-state/library.d.ts +4 -0
- package/registry/examples/empty-state/library.js +25 -0
- package/registry/examples/empty-state/library.tsx +20 -0
- package/registry/examples/loader/branded.d.ts +4 -0
- package/registry/examples/loader/branded.js +12 -0
- package/registry/examples/loader/branded.tsx +7 -0
- package/registry/examples/loader/native/branded.d.ts +4 -0
- package/registry/examples/loader/native/branded.dark.png +0 -0
- package/registry/examples/loader/native/branded.js +12 -0
- package/registry/examples/loader/native/branded.light.png +0 -0
- package/registry/examples/loader/native/branded.tsx +11 -0
- package/registry/examples/longform-page/case-study.d.ts +4 -0
- package/registry/examples/longform-page/case-study.js +41 -0
- package/registry/examples/longform-page/case-study.tsx +40 -0
- package/registry/examples/match-dialog/its-a-match.d.ts +4 -0
- package/registry/examples/match-dialog/its-a-match.js +29 -0
- package/registry/examples/match-dialog/its-a-match.tsx +25 -0
- package/registry/examples/match-dialog/native/its-a-match.d.ts +4 -0
- package/registry/examples/match-dialog/native/its-a-match.dark.png +0 -0
- package/registry/examples/match-dialog/native/its-a-match.js +28 -0
- package/registry/examples/match-dialog/native/its-a-match.light.png +0 -0
- package/registry/examples/match-dialog/native/its-a-match.tsx +22 -0
- package/registry/examples/photo-grid/native/profile-photos.d.ts +4 -0
- package/registry/examples/photo-grid/native/profile-photos.dark.png +0 -0
- package/registry/examples/photo-grid/native/profile-photos.js +27 -0
- package/registry/examples/photo-grid/native/profile-photos.light.png +0 -0
- package/registry/examples/photo-grid/native/profile-photos.tsx +24 -0
- package/registry/examples/photo-grid/profile-photos.d.ts +4 -0
- package/registry/examples/photo-grid/profile-photos.js +28 -0
- package/registry/examples/photo-grid/profile-photos.tsx +25 -0
- package/registry/examples/pull-to-refresh/native/branded.d.ts +4 -0
- package/registry/examples/pull-to-refresh/native/branded.dark.png +0 -0
- package/registry/examples/pull-to-refresh/native/branded.js +14 -0
- package/registry/examples/pull-to-refresh/native/branded.light.png +0 -0
- package/registry/examples/pull-to-refresh/native/branded.tsx +23 -0
- package/registry/examples/screen/native/app-shell.d.ts +4 -0
- package/registry/examples/screen/native/app-shell.dark.png +0 -0
- package/registry/examples/screen/native/app-shell.js +25 -0
- package/registry/examples/screen/native/app-shell.light.png +0 -0
- package/registry/examples/screen/native/app-shell.tsx +33 -0
- package/registry/examples/screen/native/auth.d.ts +4 -0
- package/registry/examples/screen/native/auth.dark.png +0 -0
- package/registry/examples/screen/native/auth.js +24 -0
- package/registry/examples/screen/native/auth.light.png +0 -0
- package/registry/examples/screen/native/auth.tsx +20 -0
- package/registry/examples/screen/native/chat.d.ts +4 -0
- package/registry/examples/screen/native/chat.dark.png +0 -0
- package/registry/examples/screen/native/chat.js +27 -0
- package/registry/examples/screen/native/chat.light.png +0 -0
- package/registry/examples/screen/native/chat.tsx +22 -0
- package/registry/examples/screen/native/feed.d.ts +4 -0
- package/registry/examples/screen/native/feed.dark.png +0 -0
- package/registry/examples/screen/native/feed.js +24 -0
- package/registry/examples/screen/native/feed.light.png +0 -0
- package/registry/examples/screen/native/feed.tsx +34 -0
- package/registry/examples/screen/native/map.d.ts +4 -0
- package/registry/examples/screen/native/map.dark.png +0 -0
- package/registry/examples/screen/native/map.js +26 -0
- package/registry/examples/screen/native/map.light.png +0 -0
- package/registry/examples/screen/native/map.tsx +31 -0
- package/registry/examples/screen/native/notifications.d.ts +4 -0
- package/registry/examples/screen/native/notifications.dark.png +0 -0
- package/registry/examples/screen/native/notifications.js +21 -0
- package/registry/examples/screen/native/notifications.light.png +0 -0
- package/registry/examples/screen/native/notifications.tsx +21 -0
- package/registry/examples/screen/native/profile.d.ts +4 -0
- package/registry/examples/screen/native/profile.dark.png +0 -0
- package/registry/examples/screen/native/profile.js +29 -0
- package/registry/examples/screen/native/profile.light.png +0 -0
- package/registry/examples/screen/native/profile.tsx +27 -0
- package/registry/examples/screen/native/settings.d.ts +4 -0
- package/registry/examples/screen/native/settings.dark.png +0 -0
- package/registry/examples/screen/native/settings.js +20 -0
- package/registry/examples/screen/native/settings.light.png +0 -0
- package/registry/examples/screen/native/settings.tsx +19 -0
- package/registry/examples/skip-link/default.d.ts +4 -0
- package/registry/examples/skip-link/default.js +19 -0
- package/registry/examples/skip-link/default.tsx +12 -0
- package/registry/examples/splash-handoff/native/default.d.ts +4 -0
- package/registry/examples/splash-handoff/native/default.dark.png +0 -0
- package/registry/examples/splash-handoff/native/default.js +12 -0
- package/registry/examples/splash-handoff/native/default.light.png +0 -0
- package/registry/examples/splash-handoff/native/default.tsx +11 -0
- package/registry/examples/split-view/nearby.d.ts +4 -0
- package/registry/examples/split-view/nearby.js +33 -0
- package/registry/examples/split-view/nearby.tsx +45 -0
- package/registry/examples/split-view/notifications.d.ts +4 -0
- package/registry/examples/split-view/notifications.js +33 -0
- package/registry/examples/split-view/notifications.tsx +31 -0
- package/registry/examples/status-page/maintenance.d.ts +4 -0
- package/registry/examples/status-page/maintenance.js +29 -0
- package/registry/examples/status-page/maintenance.tsx +24 -0
- package/registry/examples/step-progress/native/sign-up.d.ts +4 -0
- package/registry/examples/step-progress/native/sign-up.dark.png +0 -0
- package/registry/examples/step-progress/native/sign-up.js +12 -0
- package/registry/examples/step-progress/native/sign-up.light.png +0 -0
- package/registry/examples/step-progress/native/sign-up.tsx +11 -0
- package/registry/examples/step-progress/sign-up.d.ts +4 -0
- package/registry/examples/step-progress/sign-up.js +22 -0
- package/registry/examples/step-progress/sign-up.tsx +16 -0
- package/registry/examples/swipe-deck/discover.d.ts +4 -0
- package/registry/examples/swipe-deck/discover.js +41 -0
- package/registry/examples/swipe-deck/discover.tsx +37 -0
- package/registry/examples/swipe-deck/native/discover.d.ts +4 -0
- package/registry/examples/swipe-deck/native/discover.dark.png +0 -0
- package/registry/examples/swipe-deck/native/discover.js +39 -0
- package/registry/examples/swipe-deck/native/discover.light.png +0 -0
- package/registry/examples/swipe-deck/native/discover.tsx +35 -0
- package/registry/examples/tag-selector/interests.d.ts +4 -0
- package/registry/examples/tag-selector/interests.js +14 -0
- package/registry/examples/tag-selector/interests.tsx +12 -0
- package/registry/examples/tag-selector/native/interests.d.ts +4 -0
- package/registry/examples/tag-selector/native/interests.dark.png +0 -0
- package/registry/examples/tag-selector/native/interests.js +15 -0
- package/registry/examples/tag-selector/native/interests.light.png +0 -0
- package/registry/examples/tag-selector/native/interests.tsx +15 -0
- package/registry/examples/verified-badge/native/verified.d.ts +4 -0
- package/registry/examples/verified-badge/native/verified.dark.png +0 -0
- package/registry/examples/verified-badge/native/verified.js +18 -0
- package/registry/examples/verified-badge/native/verified.light.png +0 -0
- package/registry/examples/verified-badge/native/verified.tsx +15 -0
- package/registry/examples/verified-badge/verified.d.ts +4 -0
- package/registry/examples/verified-badge/verified.js +17 -0
- package/registry/examples/verified-badge/verified.tsx +13 -0
- package/registry/fab.json +1 -0
- package/registry/field.json +2 -1
- package/registry/file-upload.json +3 -2
- package/registry/filter-bar.json +2 -1
- package/registry/form.json +3 -2
- package/registry/gallery-page.json +5 -2
- package/registry/glow-card.json +2 -1
- package/registry/goal-gauge.json +2 -1
- package/registry/header.json +1 -0
- package/registry/how-it-works-page.json +5 -2
- package/registry/image-cropper.json +2 -1
- package/registry/image-viewer.json +1 -0
- package/registry/index.json +608 -19
- package/registry/iso.json +2 -1
- package/registry/kanban.json +2 -1
- package/registry/kbd.json +2 -1
- package/registry/landing-page.json +5 -2
- package/registry/landscape.json +2 -1
- package/registry/legal-page.json +5 -2
- package/registry/link-card.json +2 -1
- package/registry/list.json +2 -1
- package/registry/loader.json +47 -3
- package/registry/longform-page.json +16 -2
- package/registry/map.json +4 -3
- package/registry/marketing-layout.json +13 -4
- package/registry/marquee.json +2 -1
- package/registry/mascot-quote.json +2 -1
- package/registry/mascot-state.json +2 -1
- package/registry/mascots.json +2 -1
- package/registry/match-dialog.json +315 -0
- package/registry/media-capture.json +2 -1
- package/registry/media-picker.json +1 -0
- package/registry/meter.json +2 -1
- package/registry/nav-bar.json +2 -1
- package/registry/number-ticker.json +2 -1
- package/registry/onboarding.json +1 -0
- package/registry/otp-input.json +1 -0
- package/registry/page-header.json +2 -1
- package/registry/page-hero.json +2 -1
- package/registry/page.json +2 -1
- package/registry/pagination.json +2 -1
- package/registry/permission-prompt.json +1 -0
- package/registry/photo-grid.json +303 -0
- package/registry/pointer-light.json +2 -1
- package/registry/popover.json +2 -1
- package/registry/pricing-page.json +5 -2
- package/registry/product-page.json +5 -2
- package/registry/profile-card.json +2 -1
- package/registry/progress.json +2 -1
- package/registry/promise-card.json +2 -1
- package/registry/pull-to-refresh.json +68 -4
- package/registry/radio-group.json +2 -1
- package/registry/screen.json +233 -0
- package/registry/scroll-stage.json +2 -1
- package/registry/search-field.json +2 -1
- package/registry/section-backdrop.json +2 -1
- package/registry/segmented.json +1 -0
- package/registry/separator.json +2 -1
- package/registry/settings-layout.json +5 -2
- package/registry/skeleton.json +2 -1
- package/registry/skip-link.json +122 -0
- package/registry/slider.json +2 -1
- package/registry/slot.json +2 -1
- package/registry/spinner.json +2 -1
- package/registry/splash-handoff.json +138 -0
- package/registry/split-view.json +27 -2
- package/registry/stage-banner.json +2 -1
- package/registry/stat.json +2 -1
- package/registry/status-page.json +18 -2
- package/registry/step-progress.json +256 -0
- package/registry/stepper.json +2 -1
- package/registry/swipe-deck.json +513 -0
- package/registry/swipeable-row.json +1 -0
- package/registry/switch.json +2 -1
- package/registry/tab-bar.json +1 -0
- package/registry/tabs.json +2 -1
- package/registry/tag-input.json +2 -1
- package/registry/tag-selector.json +277 -0
- package/registry/terminal-replay.json +2 -1
- package/registry/theme.json +2 -1
- package/registry/toast.json +2 -1
- package/registry/toc.json +2 -1
- package/registry/tooltip.json +2 -1
- package/registry/tree-view.json +10 -4
- package/registry/txt.json +1 -0
- package/registry/verified-badge.json +203 -0
- package/registry/video-player.json +2 -1
- package/registry/video-trimmer.json +2 -1
- package/registry/virtual.json +2 -1
- package/dist/chunk-R6SDS7JM.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/skip-link/skip-link.tsx"],"sourcesContent":["// Client (it moves focus). WCAG 2.4.1 Bypass Blocks: the first tab stop of a page, a link that skips the navigation and\n// lands on the content. Visually hidden until focused, then a pill above everything in the brand ring. The label is\n// passed translated; the target needs an `id` (and is made focusable, so focus really moves, router or not).\nimport * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const skipLink = tv({\n base:\n \"sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-4 focus:z-[100] focus:rounded-full focus:bg-surface-1 focus:px-4 focus:py-2 \" +\n \"focus:text-sm focus:font-semibold focus:text-fg focus:no-underline focus:shadow-lg focus:outline-hidden focus:ring-2 focus:ring-ring\",\n});\n\nexport type SkipLinkProps = Omit<React.ComponentProps<\"a\">, \"href\"> & {\n /**\n * The content to land on: `#` and its `id`. The element becomes focusable (`tabindex=\"-1\"`) when it is not.\n * @default \"#content\"\n */\n href?: `#${string}`;\n};\n\n/** A \"skip to content\" link: the first tab stop, hidden until focused; Enter moves focus to the target. */\nexport function SkipLink({ href = \"#content\", className, onClick, children, ...props }: SkipLinkProps) {\n const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {\n onClick?.(event);\n if (event.defaultPrevented) return;\n const target = document.getElementById(decodeURIComponent(href.slice(1)));\n if (!target) return;\n if (!target.hasAttribute(\"tabindex\") && !target.matches(\"a[href], button, input, select, textarea, [contenteditable]\")) target.setAttribute(\"tabindex\", \"-1\");\n target.focus();\n };\n return (\n <a href={href} className={skipLink({ className })} onClick={handleClick} {...props}>\n {children}\n </a>\n );\n}\n"],"mappings":";;;AAIA,SAAS,UAAU;AA2Bf;AAzBG,IAAM,WAAW,GAAG;AAAA,EACzB,MACE;AAEJ,CAAC;AAWM,SAAS,SAAS,EAAE,OAAO,YAAY,WAAW,SAAS,UAAU,GAAG,MAAM,GAAkB;AACrG,QAAM,cAAc,CAAC,UAA+C;AAClE,cAAU,KAAK;AACf,QAAI,MAAM,iBAAkB;AAC5B,UAAM,SAAS,SAAS,eAAe,mBAAmB,KAAK,MAAM,CAAC,CAAC,CAAC;AACxE,QAAI,CAAC,OAAQ;AACb,QAAI,CAAC,OAAO,aAAa,UAAU,KAAK,CAAC,OAAO,QAAQ,6DAA6D,EAAG,QAAO,aAAa,YAAY,IAAI;AAC5J,WAAO,MAAM;AAAA,EACf;AACA,SACE,oBAAC,OAAE,MAAY,WAAW,SAAS,EAAE,UAAU,CAAC,GAAG,SAAS,aAAc,GAAG,OAC1E,UACH;AAEJ;","names":[]}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/button/button.tsx
|
|
4
|
+
import { Slot } from "radix-ui";
|
|
5
|
+
import { tv } from "tailwind-variants";
|
|
6
|
+
|
|
7
|
+
// src/spinner/glyph.tsx
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
var HEX = "M12 3 19.79 7.5 19.79 16.5 12 21 4.21 16.5 4.21 7.5Z";
|
|
10
|
+
function LoaderGlyph({ state = "loading", value, ...props }) {
|
|
11
|
+
const known = typeof value === "number" && Number.isFinite(value);
|
|
12
|
+
const fill = state !== "loading" ? 100 : known ? Math.round(Math.min(1, Math.max(0, value)) * 100) : null;
|
|
13
|
+
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", "aria-hidden": true, "data-state": state, "data-progress": fill === null ? void 0 : fill, ...props, children: [
|
|
14
|
+
/* @__PURE__ */ jsx("path", { d: HEX, stroke: "currentColor", strokeOpacity: "0.22", strokeWidth: "2.2", strokeLinejoin: "round" }),
|
|
15
|
+
/* @__PURE__ */ jsx(
|
|
16
|
+
"path",
|
|
17
|
+
{
|
|
18
|
+
d: HEX,
|
|
19
|
+
pathLength: 100,
|
|
20
|
+
stroke: "currentColor",
|
|
21
|
+
strokeWidth: "2.2",
|
|
22
|
+
strokeLinejoin: "round",
|
|
23
|
+
strokeLinecap: "round",
|
|
24
|
+
className: "kz-loader-trace",
|
|
25
|
+
strokeDasharray: fill === null ? void 0 : `${fill} ${100 - fill}`
|
|
26
|
+
}
|
|
27
|
+
),
|
|
28
|
+
state === "loading" && /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "2.6", fill: "currentColor", className: "kz-loader-node" }),
|
|
29
|
+
state === "success" && /* @__PURE__ */ jsx("path", { d: "M8.3 12.3l2.6 2.6 4.9-5.3", pathLength: 20, stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", className: "kz-loader-mark" }),
|
|
30
|
+
state === "error" && /* @__PURE__ */ jsx("path", { d: "M9.4 9.4l5.2 5.2M14.6 9.4l-5.2 5.2", pathLength: 20, stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", className: "kz-loader-mark" })
|
|
31
|
+
] });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/button/button.tsx
|
|
35
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
36
|
+
var buttonVariants = tv({
|
|
37
|
+
base: "inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 disabled:pointer-events-none disabled:opacity-40 data-loading:cursor-progress active:scale-[0.98] [&[data-loading]]:opacity-100",
|
|
38
|
+
variants: {
|
|
39
|
+
variant: {
|
|
40
|
+
primary: "bg-accent text-on-accent shadow-sm hover:bg-accent-hover",
|
|
41
|
+
// The brand's signature: accent → accent-2 (on-accent reads on both stops, tested in @krizaka/tokens).
|
|
42
|
+
gradient: "bg-linear-to-r from-accent to-accent-2 text-on-accent shadow-sm hover:brightness-110",
|
|
43
|
+
secondary: "border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3",
|
|
44
|
+
outline: "border border-border-default bg-transparent text-fg hover:border-accent hover:text-fg-accent",
|
|
45
|
+
ghost: "text-fg-secondary hover:bg-surface-2 hover:text-fg",
|
|
46
|
+
// The border and the tint carry the danger; the label stays the primary text role, legible on the tint at rest
|
|
47
|
+
// and hovered over every surface (`text-fg-danger` is for text set directly on a surface).
|
|
48
|
+
danger: "border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20"
|
|
49
|
+
},
|
|
50
|
+
size: { sm: "h-8 px-3 text-xs", md: "h-10 px-4 text-sm", lg: "h-12 px-6 text-sm", icon: "h-10 w-10" },
|
|
51
|
+
// `cut`: the Krizaka chamfer — 45° corners (CSS corner-shape, where supported; rounded elsewhere). The border, the
|
|
52
|
+
// focus ring and the hover follow the cut, unlike a clip-path.
|
|
53
|
+
shape: { rounded: "rounded-lg", pill: "rounded-full", cut: "rounded-[10px] [corner-shape:bevel]" }
|
|
54
|
+
},
|
|
55
|
+
defaultVariants: { variant: "secondary", size: "md", shape: "rounded" }
|
|
56
|
+
});
|
|
57
|
+
var STATUS_TEXT = { success: "text-fg-success", error: "text-fg-danger" };
|
|
58
|
+
function Button({
|
|
59
|
+
asChild,
|
|
60
|
+
loading,
|
|
61
|
+
progress,
|
|
62
|
+
status,
|
|
63
|
+
announce,
|
|
64
|
+
indicator = true,
|
|
65
|
+
shimmer,
|
|
66
|
+
magnetic,
|
|
67
|
+
variant,
|
|
68
|
+
size,
|
|
69
|
+
shape,
|
|
70
|
+
className,
|
|
71
|
+
disabled,
|
|
72
|
+
children,
|
|
73
|
+
...props
|
|
74
|
+
}) {
|
|
75
|
+
const Comp = asChild ? Slot.Root : "button";
|
|
76
|
+
const known = loading && typeof progress === "number" && Number.isFinite(progress);
|
|
77
|
+
const ratio = known ? Math.min(1, Math.max(0, progress)) : 0;
|
|
78
|
+
const glyph = indicator && !asChild && (loading || status) ? status ?? "loading" : null;
|
|
79
|
+
const filled = variant === "primary" || variant === "gradient";
|
|
80
|
+
const button = /* @__PURE__ */ jsx2(
|
|
81
|
+
Comp,
|
|
82
|
+
{
|
|
83
|
+
type: asChild ? void 0 : "button",
|
|
84
|
+
"aria-busy": loading || void 0,
|
|
85
|
+
"data-loading": loading ? "" : void 0,
|
|
86
|
+
"data-variant": variant ?? "secondary",
|
|
87
|
+
"data-kz-status": status ?? void 0,
|
|
88
|
+
"data-kz-magnetic": magnetic ? "" : void 0,
|
|
89
|
+
disabled: asChild ? void 0 : disabled || loading,
|
|
90
|
+
"aria-disabled": asChild && (disabled || loading) ? true : void 0,
|
|
91
|
+
className: buttonVariants({
|
|
92
|
+
variant,
|
|
93
|
+
size,
|
|
94
|
+
shape,
|
|
95
|
+
className: [known && "relative isolate overflow-hidden", shimmer && "kz-sheen", className].filter(Boolean).join(" ") || void 0
|
|
96
|
+
}),
|
|
97
|
+
...props,
|
|
98
|
+
children: asChild ? children : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
99
|
+
known && /* @__PURE__ */ jsx2("span", { "aria-hidden": true, className: "absolute inset-y-0 left-0 -z-10 bg-current opacity-15 transition-[width] duration-500", style: { width: `${ratio * 100}%` } }),
|
|
100
|
+
glyph && /* @__PURE__ */ jsx2(
|
|
101
|
+
"span",
|
|
102
|
+
{
|
|
103
|
+
"aria-hidden": true,
|
|
104
|
+
"data-slot": "indicator",
|
|
105
|
+
className: "-my-1 grid grid-cols-[1fr] transition-[grid-template-columns,margin,opacity] duration-300 starting:-mr-2 starting:grid-cols-[0fr] starting:opacity-0",
|
|
106
|
+
children: /* @__PURE__ */ jsx2("span", { className: "overflow-hidden", children: /* @__PURE__ */ jsx2(LoaderGlyph, { state: glyph, value: known ? ratio : null, className: ["h-4 w-4", glyph !== "loading" && !filled && STATUS_TEXT[glyph]].filter(Boolean).join(" ") }) })
|
|
107
|
+
}
|
|
108
|
+
),
|
|
109
|
+
children
|
|
110
|
+
] })
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
if (announce === void 0 || asChild) return button;
|
|
114
|
+
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
115
|
+
button,
|
|
116
|
+
/* @__PURE__ */ jsx2("span", { role: "status", className: "sr-only", children: announce })
|
|
117
|
+
] });
|
|
118
|
+
}
|
|
119
|
+
function IconButton({ label, size = "icon", children, ...props }) {
|
|
120
|
+
const swap = props.indicator !== false && !props.asChild && (props.loading || props.status);
|
|
121
|
+
return /* @__PURE__ */ jsx2(Button, { "aria-label": label, title: label, size, ...props, children: swap ? null : children });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export {
|
|
125
|
+
Button,
|
|
126
|
+
IconButton
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=chunk-ECSCA3CN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/button/button.tsx","../src/spinner/glyph.tsx"],"sourcesContent":["// Server-safe: no hook, no context. `buttonVariants` styles a <Link> or a Server Component without the component.\nimport { Slot } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { LoaderGlyph } from \"../spinner/glyph\";\n\nexport const buttonVariants = tv({\n base:\n \"inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-all \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 \" +\n \"disabled:pointer-events-none disabled:opacity-40 data-loading:cursor-progress active:scale-[0.98] \" +\n // Busy is not unavailable: a loading button keeps its colour (it is disabled only so it is not pressed twice).\n \"[&[data-loading]]:opacity-100\",\n variants: {\n variant: {\n primary: \"bg-accent text-on-accent shadow-sm hover:bg-accent-hover\",\n // The brand's signature: accent → accent-2 (on-accent reads on both stops, tested in @krizaka/tokens).\n gradient: \"bg-linear-to-r from-accent to-accent-2 text-on-accent shadow-sm hover:brightness-110\",\n secondary: \"border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3\",\n outline: \"border border-border-default bg-transparent text-fg hover:border-accent hover:text-fg-accent\",\n ghost: \"text-fg-secondary hover:bg-surface-2 hover:text-fg\",\n // The border and the tint carry the danger; the label stays the primary text role, legible on the tint at rest\n // and hovered over every surface (`text-fg-danger` is for text set directly on a surface).\n danger: \"border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20\",\n },\n size: { sm: \"h-8 px-3 text-xs\", md: \"h-10 px-4 text-sm\", lg: \"h-12 px-6 text-sm\", icon: \"h-10 w-10\" },\n // `cut`: the Krizaka chamfer — 45° corners (CSS corner-shape, where supported; rounded elsewhere). The border, the\n // focus ring and the hover follow the cut, unlike a clip-path.\n shape: { rounded: \"rounded-lg\", pill: \"rounded-full\", cut: \"rounded-[10px] [corner-shape:bevel]\" },\n },\n defaultVariants: { variant: \"secondary\", size: \"md\", shape: \"rounded\" },\n});\n\nexport type ButtonVariants = VariantProps<typeof buttonVariants>;\n\nexport type ButtonProps = React.ComponentProps<\"button\"> &\n ButtonVariants & {\n /**\n * The look: `primary` (the accent), `gradient` (accent → accent-2), `secondary` (a raised surface), `outline`,\n * `ghost`, `danger`.\n * @default \"secondary\"\n */\n variant?: ButtonVariants[\"variant\"];\n /**\n * sm · md · lg, or `icon` (a square).\n * @default \"md\"\n */\n size?: ButtonVariants[\"size\"];\n /**\n * rounded · pill · cut (45° corners, the Krizaka chamfer).\n * @default \"rounded\"\n */\n shape?: ButtonVariants[\"shape\"];\n /** Renders the child (e.g. a <Link>) instead of the <button>, with props, classes and ref merged. */\n asChild?: boolean;\n /**\n * Disables and signals the wait (aria-busy, data-loading) and shows the Krizaka loader glyph before the label; the\n * button keeps its colour.\n */\n loading?: boolean;\n /**\n * Between 0 and 1, while `loading`: the glyph's trace and a light fill across the button grow to the value (an\n * upload, an export).\n */\n progress?: number | null;\n /**\n * How the action ended: `success` draws a check, `error` a cross (and the button shakes its head once); a ring of\n * the status colour opens around it. Clear it to return to rest.\n */\n status?: \"success\" | \"error\" | null;\n /** A message announced politely by assistive technology when it changes (“Saved”, “Upload failed”) — passed translated. */\n announce?: string;\n /**\n * Shows the glyph while `loading` / with a `status`. `false`: you draw your own.\n * @default true\n */\n indicator?: boolean;\n /** A sheen of light crosses the button on hover — for the one action a page is about. */\n shimmer?: boolean;\n /** The button leans a few pixels toward a fine pointer (driven by `MotionObserver`; never under reduced motion or on touch). */\n magnetic?: boolean;\n };\n\nconst STATUS_TEXT = { success: \"text-fg-success\", error: \"text-fg-danger\" } as const;\n\nexport function Button({\n asChild,\n loading,\n progress,\n status,\n announce,\n indicator = true,\n shimmer,\n magnetic,\n variant,\n size,\n shape,\n className,\n disabled,\n children,\n ...props\n}: ButtonProps) {\n const Comp = asChild ? Slot.Root : \"button\";\n const known = loading && typeof progress === \"number\" && Number.isFinite(progress);\n const ratio = known ? Math.min(1, Math.max(0, progress)) : 0;\n const glyph = indicator && !asChild && (loading || status) ? (status ?? \"loading\") : null;\n // On a filled variant the glyph stays in the label's colour; on the others it takes the status colour.\n const filled = variant === \"primary\" || variant === \"gradient\";\n const button = (\n <Comp\n type={asChild ? undefined : \"button\"}\n aria-busy={loading || undefined}\n data-loading={loading ? \"\" : undefined}\n data-variant={variant ?? \"secondary\"}\n data-kz-status={status ?? undefined}\n data-kz-magnetic={magnetic ? \"\" : undefined}\n disabled={asChild ? undefined : disabled || loading}\n aria-disabled={asChild && (disabled || loading) ? true : undefined}\n className={buttonVariants({\n variant,\n size,\n shape,\n className: [known && \"relative isolate overflow-hidden\", shimmer && \"kz-sheen\", className].filter(Boolean).join(\" \") || undefined,\n })}\n {...props}\n >\n {asChild ? (\n children\n ) : (\n <>\n {known && (\n <span aria-hidden className=\"absolute inset-y-0 left-0 -z-10 bg-current opacity-15 transition-[width] duration-500\" style={{ width: `${ratio * 100}%` }} />\n )}\n {glyph && (\n <span\n aria-hidden\n data-slot=\"indicator\"\n className=\"-my-1 grid grid-cols-[1fr] transition-[grid-template-columns,margin,opacity] duration-300 starting:-mr-2 starting:grid-cols-[0fr] starting:opacity-0\"\n >\n <span className=\"overflow-hidden\">\n <LoaderGlyph state={glyph} value={known ? ratio : null} className={[\"h-4 w-4\", glyph !== \"loading\" && !filled && STATUS_TEXT[glyph]].filter(Boolean).join(\" \")} />\n </span>\n </span>\n )}\n {children}\n </>\n )}\n </Comp>\n );\n if (announce === undefined || asChild) return button;\n return (\n <>\n {button}\n <span role=\"status\" className=\"sr-only\">\n {announce}\n </span>\n </>\n );\n}\n\nexport type IconButtonProps = Omit<ButtonProps, \"size\"> & {\n /** The accessible name (and tooltip) of the button — required, passed translated. */\n label: string;\n /**\n * sm · md · lg, or `icon` (a square).\n * @default \"icon\"\n */\n size?: ButtonProps[\"size\"];\n};\n\n/** An icon-only button: `label` is required, it is its accessible name. Loading or with a status, the glyph takes the icon's place. */\nexport function IconButton({ label, size = \"icon\", children, ...props }: IconButtonProps) {\n const swap = props.indicator !== false && !props.asChild && (props.loading || props.status);\n return (\n <Button aria-label={label} title={label} size={size} {...props}>\n {swap ? null : children}\n </Button>\n );\n}\n","// The Krizaka loader glyph, server-safe: a hexagon (the marks' shape) traced by a segment of light around a node that\n// breathes; determinate, it fills to its value; done, the trace closes and a check (or a cross) draws itself. Animated by\n// motion.css (`kz-loader-*`); still under prefers-reduced-motion — a segment at rest and the node lit, never blank.\nimport type * as React from \"react\";\n\n/** The hexagon, pointy top, radius 9 around (12, 12). */\nconst HEX = \"M12 3 19.79 7.5 19.79 16.5 12 21 4.21 16.5 4.21 7.5Z\";\n\n/** What the glyph shows: a wait (with an optional value), or how it ended. */\nexport type LoaderGlyphState = \"loading\" | \"success\" | \"error\";\n\nexport interface LoaderGlyphProps extends Omit<React.ComponentProps<\"svg\">, \"children\"> {\n /** loading · success · error. */\n state?: LoaderGlyphState;\n /** Between 0 and 1: a determinate wait, the trace grows to it. Absent: indeterminate. */\n value?: number | null;\n}\n\n/** The glyph alone (decorative): the Spinner, the Loader and the Button's `loading` draw it. */\nexport function LoaderGlyph({ state = \"loading\", value, ...props }: LoaderGlyphProps) {\n const known = typeof value === \"number\" && Number.isFinite(value);\n const fill = state !== \"loading\" ? 100 : known ? Math.round(Math.min(1, Math.max(0, value)) * 100) : null;\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden data-state={state} data-progress={fill === null ? undefined : fill} {...props}>\n <path d={HEX} stroke=\"currentColor\" strokeOpacity=\"0.22\" strokeWidth=\"2.2\" strokeLinejoin=\"round\" />\n <path\n d={HEX}\n pathLength={100}\n stroke=\"currentColor\"\n strokeWidth=\"2.2\"\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n className=\"kz-loader-trace\"\n strokeDasharray={fill === null ? undefined : `${fill} ${100 - fill}`}\n />\n {state === \"loading\" && <circle cx=\"12\" cy=\"12\" r=\"2.6\" fill=\"currentColor\" className=\"kz-loader-node\" />}\n {state === \"success\" && <path d=\"M8.3 12.3l2.6 2.6 4.9-5.3\" pathLength={20} stroke=\"currentColor\" strokeWidth=\"2.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className=\"kz-loader-mark\" />}\n {state === \"error\" && <path d=\"M9.4 9.4l5.2 5.2M14.6 9.4l-5.2 5.2\" pathLength={20} stroke=\"currentColor\" strokeWidth=\"2.2\" strokeLinecap=\"round\" className=\"kz-loader-mark\" />}\n </svg>\n );\n}\n"],"mappings":"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","names":["jsx","jsxs"]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/avatar/avatar.tsx
|
|
4
|
+
import { Avatar as AvatarPrimitive } from "radix-ui";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { tv } from "tailwind-variants";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
var avatar = tv({
|
|
9
|
+
slots: {
|
|
10
|
+
root: "relative inline-flex shrink-0 overflow-hidden rounded-full bg-surface-3 align-middle",
|
|
11
|
+
image: "h-full w-full object-cover",
|
|
12
|
+
fallback: "flex h-full w-full items-center justify-center font-semibold uppercase text-fg-secondary",
|
|
13
|
+
group: "flex items-center -space-x-2 [&>*]:ring-2 [&>*]:ring-surface-0"
|
|
14
|
+
},
|
|
15
|
+
variants: {
|
|
16
|
+
size: {
|
|
17
|
+
xs: { root: "h-5 w-5 text-[9px]" },
|
|
18
|
+
sm: { root: "h-8 w-8 text-xs" },
|
|
19
|
+
md: { root: "h-10 w-10 text-sm" },
|
|
20
|
+
lg: { root: "h-14 w-14 text-base" },
|
|
21
|
+
xl: { root: "h-20 w-20 text-lg" }
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
defaultVariants: { size: "md" }
|
|
25
|
+
});
|
|
26
|
+
function AvatarRoot({ src, alt = "", fallback, size, className, ...props }) {
|
|
27
|
+
const s = avatar({ size });
|
|
28
|
+
return /* @__PURE__ */ jsxs(AvatarPrimitive.Root, { "data-size": size ?? "md", className: s.root({ className }), ...props, children: [
|
|
29
|
+
src && /* @__PURE__ */ jsx(AvatarPrimitive.Image, { src, alt, className: s.image() }),
|
|
30
|
+
/* @__PURE__ */ jsx(AvatarPrimitive.Fallback, { delayMs: src ? 300 : 0, className: s.fallback(), children: fallback })
|
|
31
|
+
] });
|
|
32
|
+
}
|
|
33
|
+
function AvatarGroup({ max, size, className, children, ...props }) {
|
|
34
|
+
const items = React.Children.toArray(children);
|
|
35
|
+
const shown = max === void 0 ? items : items.slice(0, max);
|
|
36
|
+
const rest = items.length - shown.length;
|
|
37
|
+
return /* @__PURE__ */ jsxs("div", { className: avatar().group({ className }), ...props, children: [
|
|
38
|
+
shown,
|
|
39
|
+
rest > 0 && /* @__PURE__ */ jsx(AvatarRoot, { size, fallback: `+${rest}` })
|
|
40
|
+
] });
|
|
41
|
+
}
|
|
42
|
+
var Avatar = Object.assign(AvatarRoot, { Group: AvatarGroup });
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
Avatar
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=chunk-F2GKFIYK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/avatar/avatar.tsx"],"sourcesContent":["// Client: Radix tracks the image's loading state and shows the fallback until it has loaded (or when it fails).\nimport { Avatar as AvatarPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nconst avatar = tv({\n slots: {\n root: \"relative inline-flex shrink-0 overflow-hidden rounded-full bg-surface-3 align-middle\",\n image: \"h-full w-full object-cover\",\n fallback: \"flex h-full w-full items-center justify-center font-semibold uppercase text-fg-secondary\",\n group: \"flex items-center -space-x-2 [&>*]:ring-2 [&>*]:ring-surface-0\",\n },\n variants: {\n size: {\n xs: { root: \"h-5 w-5 text-[9px]\" },\n sm: { root: \"h-8 w-8 text-xs\" },\n md: { root: \"h-10 w-10 text-sm\" },\n lg: { root: \"h-14 w-14 text-base\" },\n xl: { root: \"h-20 w-20 text-lg\" },\n },\n },\n defaultVariants: { size: \"md\" },\n});\n\nexport type AvatarSize = NonNullable<VariantProps<typeof avatar>[\"size\"]>;\n\nexport type AvatarProps = Omit<React.ComponentProps<\"span\">, \"children\"> & {\n /** The image's URL; `null` or nothing shows the `fallback`. */\n src?: string | null;\n /** The image's text alternative (the person's name); empty when a visible name sits next to the avatar. */\n alt?: string;\n /** Shown while the image loads, when it fails or when there is none: initials, an icon. */\n fallback?: React.ReactNode;\n /**\n * xs · sm · md · lg · xl.\n * @default \"md\"\n */\n size?: AvatarSize;\n};\n\nexport function AvatarRoot({ src, alt = \"\", fallback, size, className, ...props }: AvatarProps) {\n const s = avatar({ size });\n return (\n <AvatarPrimitive.Root data-size={size ?? \"md\"} className={s.root({ className })} {...props}>\n {src && <AvatarPrimitive.Image src={src} alt={alt} className={s.image()} />}\n <AvatarPrimitive.Fallback delayMs={src ? 300 : 0} className={s.fallback()}>\n {fallback}\n </AvatarPrimitive.Fallback>\n </AvatarPrimitive.Root>\n );\n}\n\nexport type AvatarGroupProps = React.ComponentProps<\"div\"> & {\n /** How many avatars are shown; the rest becomes a `+n` avatar. */\n max?: number;\n /** The size of the `+n` avatar (match the avatars of the group). */\n size?: AvatarSize;\n};\n\n/** Overlapping avatars; past `max`, a `+n` avatar counts the rest. */\nexport function AvatarGroup({ max, size, className, children, ...props }: AvatarGroupProps) {\n const items = React.Children.toArray(children);\n const shown = max === undefined ? items : items.slice(0, max);\n const rest = items.length - shown.length;\n return (\n <div className={avatar().group({ className })} {...props}>\n {shown}\n {rest > 0 && <AvatarRoot size={size} fallback={`+${rest}`} />}\n </div>\n );\n}\n\n/** `Avatar` (an image with a fallback) and `Avatar.Group`. */\nexport const Avatar = Object.assign(AvatarRoot, { Group: AvatarGroup });\n"],"mappings":";;;AACA,SAAS,UAAU,uBAAuB;AAC1C,YAAY,WAAW;AACvB,SAAS,UAA6B;AAwClC,SACU,KADV;AAtCJ,IAAM,SAAS,GAAG;AAAA,EAChB,OAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO;AAAA,EACT;AAAA,EACA,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,IAAI,EAAE,MAAM,qBAAqB;AAAA,MACjC,IAAI,EAAE,MAAM,kBAAkB;AAAA,MAC9B,IAAI,EAAE,MAAM,oBAAoB;AAAA,MAChC,IAAI,EAAE,MAAM,sBAAsB;AAAA,MAClC,IAAI,EAAE,MAAM,oBAAoB;AAAA,IAClC;AAAA,EACF;AAAA,EACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CAAC;AAkBM,SAAS,WAAW,EAAE,KAAK,MAAM,IAAI,UAAU,MAAM,WAAW,GAAG,MAAM,GAAgB;AAC9F,QAAM,IAAI,OAAO,EAAE,KAAK,CAAC;AACzB,SACE,qBAAC,gBAAgB,MAAhB,EAAqB,aAAW,QAAQ,MAAM,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAClF;AAAA,WAAO,oBAAC,gBAAgB,OAAhB,EAAsB,KAAU,KAAU,WAAW,EAAE,MAAM,GAAG;AAAA,IACzE,oBAAC,gBAAgB,UAAhB,EAAyB,SAAS,MAAM,MAAM,GAAG,WAAW,EAAE,SAAS,GACrE,oBACH;AAAA,KACF;AAEJ;AAUO,SAAS,YAAY,EAAE,KAAK,MAAM,WAAW,UAAU,GAAG,MAAM,GAAqB;AAC1F,QAAM,QAAc,eAAS,QAAQ,QAAQ;AAC7C,QAAM,QAAQ,QAAQ,SAAY,QAAQ,MAAM,MAAM,GAAG,GAAG;AAC5D,QAAM,OAAO,MAAM,SAAS,MAAM;AAClC,SACE,qBAAC,SAAI,WAAW,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,GAAI,GAAG,OAChD;AAAA;AAAA,IACA,OAAO,KAAK,oBAAC,cAAW,MAAY,UAAU,IAAI,IAAI,IAAI;AAAA,KAC7D;AAEJ;AAGO,IAAM,SAAS,OAAO,OAAO,YAAY,EAAE,OAAO,YAAY,CAAC;","names":[]}
|
|
@@ -6,6 +6,25 @@ import {
|
|
|
6
6
|
// src/dialog/dialog.tsx
|
|
7
7
|
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
8
8
|
import { tv } from "tailwind-variants";
|
|
9
|
+
|
|
10
|
+
// src/dialog/return-focus.ts
|
|
11
|
+
import * as React from "react";
|
|
12
|
+
function useReturnFocus(onCloseAutoFocus) {
|
|
13
|
+
const [opener] = React.useState(() => typeof document === "undefined" ? null : document.activeElement);
|
|
14
|
+
return React.useCallback(
|
|
15
|
+
(event) => {
|
|
16
|
+
onCloseAutoFocus?.(event);
|
|
17
|
+
if (event.defaultPrevented) return;
|
|
18
|
+
if (opener instanceof HTMLElement && opener !== document.body && opener.isConnected) {
|
|
19
|
+
event.preventDefault();
|
|
20
|
+
opener.focus();
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
[opener, onCloseAutoFocus]
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/dialog/dialog.tsx
|
|
9
28
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
29
|
var dialog = tv({
|
|
11
30
|
slots: {
|
|
@@ -38,6 +57,9 @@ function CloseIcon() {
|
|
|
38
57
|
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) });
|
|
39
58
|
}
|
|
40
59
|
var prevent = (event) => event.preventDefault();
|
|
60
|
+
function ReturnFocusContent({ onCloseAutoFocus, ...props }) {
|
|
61
|
+
return /* @__PURE__ */ jsx(DialogPrimitive.Content, { onCloseAutoFocus: useReturnFocus(onCloseAutoFocus), ...props });
|
|
62
|
+
}
|
|
41
63
|
function DialogContent({
|
|
42
64
|
placement,
|
|
43
65
|
size,
|
|
@@ -56,7 +78,7 @@ function DialogContent({
|
|
|
56
78
|
return /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { container, children: [
|
|
57
79
|
/* @__PURE__ */ jsx(DialogPrimitive.Overlay, { className: v.overlay() }),
|
|
58
80
|
/* @__PURE__ */ jsxs(
|
|
59
|
-
|
|
81
|
+
ReturnFocusContent,
|
|
60
82
|
{
|
|
61
83
|
"data-placement": placement ?? "center",
|
|
62
84
|
"data-dismissible": dismissible ? void 0 : "false",
|
|
@@ -110,6 +132,7 @@ function Sheet(props) {
|
|
|
110
132
|
}
|
|
111
133
|
|
|
112
134
|
export {
|
|
135
|
+
useReturnFocus,
|
|
113
136
|
dialog,
|
|
114
137
|
DialogContent,
|
|
115
138
|
DialogHeader,
|
|
@@ -120,4 +143,4 @@ export {
|
|
|
120
143
|
Dialog,
|
|
121
144
|
Sheet
|
|
122
145
|
};
|
|
123
|
-
//# sourceMappingURL=chunk-
|
|
146
|
+
//# sourceMappingURL=chunk-ND3L5VHT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dialog/dialog.tsx","../src/dialog/return-focus.ts"],"sourcesContent":["// Client (a portal). Radix does the focus trap, the scroll lock, Escape, the outside click, aria-modal, the\n// aria-labelledby / aria-describedby wiring and the focus return: this file only holds the shape.\nimport { Dialog as DialogPrimitive } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { IconButton } from \"../button/button\";\nimport { useReturnFocus } from \"./return-focus\";\n\nexport const dialog = tv({\n slots: {\n overlay: \"kz-overlay fixed inset-0 z-50 bg-overlay backdrop-blur-xs\",\n content:\n \"kz-dialog fixed z-50 flex flex-col overflow-hidden border border-border-default bg-surface-1 text-fg shadow-lg focus:outline-hidden\",\n close: \"absolute right-3 top-3 h-9 w-9\",\n header: \"flex flex-col gap-1 px-5 pb-2 pr-14 pt-5\",\n title: \"text-base font-bold text-fg\",\n description: \"text-sm text-fg-secondary\",\n body: \"min-h-0 flex-1 overflow-y-auto px-5 pb-5\",\n footer:\n \"flex flex-wrap items-center justify-end gap-2 border-t border-border-subtle px-5 py-4 pb-[max(1rem,env(safe-area-inset-bottom))]\",\n },\n variants: {\n placement: {\n center: { content: \"left-1/2 top-1/2 max-h-[85dvh] w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 rounded-xl\" },\n /* A sheet: anchored at the bottom on a phone, centred from `sm` up. */\n bottom: {\n content:\n \"inset-x-0 bottom-0 max-h-[92dvh] rounded-t-[1.75rem] sm:bottom-auto sm:left-1/2 sm:top-1/2 sm:w-full \" +\n \"sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-[1.75rem]\",\n },\n right: { content: \"inset-y-0 right-0 h-full w-full max-w-md rounded-none border-y-0 border-r-0\" },\n /* A navigation drawer: full height, from the left, clear of the notch. */\n left: { content: \"inset-y-0 left-0 h-full w-full max-w-md rounded-none border-y-0 border-l-0 pl-[env(safe-area-inset-left)]\" },\n },\n size: { sm: { content: \"sm:max-w-sm\" }, md: { content: \"sm:max-w-md\" }, lg: { content: \"sm:max-w-2xl\" } },\n },\n defaultVariants: { placement: \"center\", size: \"md\" },\n});\nconst s = dialog();\n\nexport type DialogVariants = VariantProps<typeof dialog>;\n\nfunction CloseIcon() {\n return (\n <svg viewBox=\"0 0 24 24\" className=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n );\n}\n\ntype CloseButtonProps =\n | {\n /** The accessible name of the close button — passed translated. */\n closeLabel: string;\n /** Leaves the close button out (the content brings its own way out, or none: see `dismissible`). */\n hideClose?: false;\n }\n | { closeLabel?: string; hideClose: true };\n\nexport type DialogContentProps = React.ComponentProps<typeof DialogPrimitive.Content> &\n DialogVariants &\n CloseButtonProps & {\n /**\n * center · bottom (a sheet on a phone, centred from `sm` up) · right (a side panel, full height) · left (a\n * navigation drawer, full height).\n * @default \"center\"\n */\n placement?: DialogVariants[\"placement\"];\n /**\n * sm · md · lg: the width of the dialog.\n * @default \"md\"\n */\n size?: DialogVariants[\"size\"];\n /**\n * `false`: Escape and a click outside do not close it (a gate the user must answer: age, terms). It still closes\n * through `open` / `onOpenChange` and any `Dialog.Close` inside. Default `true`.\n */\n dismissible?: boolean;\n /** The element the portal renders into (default: document.body). */\n container?: HTMLElement | null;\n };\n\nconst prevent = (event: Event) => event.preventDefault();\n\n/** Radix's content, mounted only while open: it remembers the opener then and gives focus back on close (WCAG 2.4.3). */\nfunction ReturnFocusContent({ onCloseAutoFocus, ...props }: React.ComponentProps<typeof DialogPrimitive.Content>) {\n return <DialogPrimitive.Content onCloseAutoFocus={useReturnFocus(onCloseAutoFocus)} {...props} />;\n}\n\n/** The dialog itself, portalled over a dimmed overlay, with a close button. Give it a `Dialog.Title`. */\nexport function DialogContent({\n placement,\n size,\n closeLabel,\n hideClose,\n dismissible = true,\n container,\n className,\n children,\n onEscapeKeyDown,\n onPointerDownOutside,\n onInteractOutside,\n ...props\n}: DialogContentProps) {\n const v = dialog({ placement, size });\n return (\n <DialogPrimitive.Portal container={container}>\n <DialogPrimitive.Overlay className={v.overlay()} />\n <ReturnFocusContent\n data-placement={placement ?? \"center\"}\n data-dismissible={dismissible ? undefined : \"false\"}\n className={v.content({ className })}\n onEscapeKeyDown={dismissible ? onEscapeKeyDown : chain(onEscapeKeyDown, prevent)}\n onPointerDownOutside={dismissible ? onPointerDownOutside : chain(onPointerDownOutside, prevent)}\n onInteractOutside={dismissible ? onInteractOutside : chain(onInteractOutside, prevent)}\n {...props}\n >\n {children}\n {!hideClose && (\n <DialogPrimitive.Close asChild>\n <IconButton label={closeLabel as string} variant=\"ghost\" shape=\"pill\" className={v.close()}>\n <CloseIcon />\n </IconButton>\n </DialogPrimitive.Close>\n )}\n </ReturnFocusContent>\n </DialogPrimitive.Portal>\n );\n}\n\nfunction chain<E extends Event>(handler: ((event: E) => void) | undefined, then: (event: E) => void) {\n return (event: E) => {\n handler?.(event);\n then(event);\n };\n}\n\nexport function DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={s.header({ className })} {...props} />;\n}\n\nexport function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return <DialogPrimitive.Title className={s.title({ className })} {...props} />;\n}\n\nexport function DialogDescription({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return <DialogPrimitive.Description className={s.description({ className })} {...props} />;\n}\n\nexport function DialogBody({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={s.body({ className })} {...props} />;\n}\n\nexport function DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={s.footer({ className })} {...props} />;\n}\n\n/** `Dialog.Root/Trigger/Content/Header/Title/Description/Body/Footer/Close`. `open`/`defaultOpen` + `onOpenChange`. */\nexport const Dialog = {\n Root: DialogPrimitive.Root,\n Trigger: DialogPrimitive.Trigger,\n Close: DialogPrimitive.Close,\n Content: DialogContent,\n Header: DialogHeader,\n Title: DialogTitle,\n Description: DialogDescription,\n Body: DialogBody,\n Footer: DialogFooter,\n};\n\n/** `Omit` that keeps the close-button union (`closeLabel` required unless `hideClose`). */\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\n\nexport type SheetProps = DistributiveOmit<DialogContentProps, \"placement\">;\n\n/** A sheet is a dialog anchored at the bottom (centred from `sm` up): `Dialog.Content placement=\"bottom\"`. */\nexport function Sheet(props: SheetProps) {\n return <DialogContent placement=\"bottom\" {...props} />;\n}\n","// Client. WCAG 2.4.3: when a dialog closes, focus goes back to what opened it. Radix only does it for `Dialog.Trigger`;\n// most app dialogs are controlled (`open` / `onOpenChange`) and opened by a plain button, so on Escape focus fell to\n// <body>. The content remembers the focused element when it mounts (it is still the opener: Radix moves focus in an\n// effect) and gives it back on close, unless the consumer's `onCloseAutoFocus` prevented the default.\nimport * as React from \"react\";\n\n/** The handler for `onCloseAutoFocus`: yours first, then focus back on the opener if it is still on the page. */\nexport function useReturnFocus(onCloseAutoFocus?: (event: Event) => void) {\n const [opener] = React.useState<Element | null>(() => (typeof document === \"undefined\" ? null : document.activeElement));\n return React.useCallback(\n (event: Event) => {\n onCloseAutoFocus?.(event);\n if (event.defaultPrevented) return;\n if (opener instanceof HTMLElement && opener !== document.body && opener.isConnected) {\n event.preventDefault();\n opener.focus();\n }\n },\n [opener, onCloseAutoFocus],\n );\n}\n"],"mappings":"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","names":[]}
|
package/dist/command.js
CHANGED
package/dist/data-table.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import {
|
|
3
|
+
Button
|
|
4
|
+
} from "./chunk-ECSCA3CN.js";
|
|
2
5
|
import {
|
|
3
6
|
Checkbox
|
|
4
7
|
} from "./chunk-7Z4KHPFC.js";
|
|
@@ -766,127 +769,10 @@ function ResizeHandle({
|
|
|
766
769
|
);
|
|
767
770
|
}
|
|
768
771
|
|
|
769
|
-
// src/
|
|
770
|
-
import { Slot } from "radix-ui";
|
|
772
|
+
// src/field/field.tsx
|
|
771
773
|
import { tv as tv3 } from "tailwind-variants";
|
|
772
|
-
|
|
773
|
-
// src/spinner/glyph.tsx
|
|
774
774
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
775
|
-
var
|
|
776
|
-
function LoaderGlyph({ state = "loading", value, ...props }) {
|
|
777
|
-
const known = typeof value === "number" && Number.isFinite(value);
|
|
778
|
-
const fill = state !== "loading" ? 100 : known ? Math.round(Math.min(1, Math.max(0, value)) * 100) : null;
|
|
779
|
-
return /* @__PURE__ */ jsxs3("svg", { viewBox: "0 0 24 24", fill: "none", "aria-hidden": true, "data-state": state, "data-progress": fill === null ? void 0 : fill, ...props, children: [
|
|
780
|
-
/* @__PURE__ */ jsx3("path", { d: HEX, stroke: "currentColor", strokeOpacity: "0.22", strokeWidth: "2.2", strokeLinejoin: "round" }),
|
|
781
|
-
/* @__PURE__ */ jsx3(
|
|
782
|
-
"path",
|
|
783
|
-
{
|
|
784
|
-
d: HEX,
|
|
785
|
-
pathLength: 100,
|
|
786
|
-
stroke: "currentColor",
|
|
787
|
-
strokeWidth: "2.2",
|
|
788
|
-
strokeLinejoin: "round",
|
|
789
|
-
strokeLinecap: "round",
|
|
790
|
-
className: "kz-loader-trace",
|
|
791
|
-
strokeDasharray: fill === null ? void 0 : `${fill} ${100 - fill}`
|
|
792
|
-
}
|
|
793
|
-
),
|
|
794
|
-
state === "loading" && /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "2.6", fill: "currentColor", className: "kz-loader-node" }),
|
|
795
|
-
state === "success" && /* @__PURE__ */ jsx3("path", { d: "M8.3 12.3l2.6 2.6 4.9-5.3", pathLength: 20, stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", className: "kz-loader-mark" }),
|
|
796
|
-
state === "error" && /* @__PURE__ */ jsx3("path", { d: "M9.4 9.4l5.2 5.2M14.6 9.4l-5.2 5.2", pathLength: 20, stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", className: "kz-loader-mark" })
|
|
797
|
-
] });
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
// src/button/button.tsx
|
|
801
|
-
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
802
|
-
var buttonVariants = tv3({
|
|
803
|
-
base: "inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 disabled:pointer-events-none disabled:opacity-40 data-loading:cursor-progress active:scale-[0.98] [&[data-loading]]:opacity-100",
|
|
804
|
-
variants: {
|
|
805
|
-
variant: {
|
|
806
|
-
primary: "bg-accent text-on-accent shadow-sm hover:bg-accent-hover",
|
|
807
|
-
// The brand's signature: accent → accent-2 (on-accent reads on both stops, tested in @krizaka/tokens).
|
|
808
|
-
gradient: "bg-linear-to-r from-accent to-accent-2 text-on-accent shadow-sm hover:brightness-110",
|
|
809
|
-
secondary: "border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3",
|
|
810
|
-
outline: "border border-border-default bg-transparent text-fg hover:border-accent hover:text-fg-accent",
|
|
811
|
-
ghost: "text-fg-secondary hover:bg-surface-2 hover:text-fg",
|
|
812
|
-
// The border and the tint carry the danger; the label stays the primary text role, legible on the tint at rest
|
|
813
|
-
// and hovered over every surface (`text-fg-danger` is for text set directly on a surface).
|
|
814
|
-
danger: "border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20"
|
|
815
|
-
},
|
|
816
|
-
size: { sm: "h-8 px-3 text-xs", md: "h-10 px-4 text-sm", lg: "h-12 px-6 text-sm", icon: "h-10 w-10" },
|
|
817
|
-
// `cut`: the Krizaka chamfer — 45° corners (CSS corner-shape, where supported; rounded elsewhere). The border, the
|
|
818
|
-
// focus ring and the hover follow the cut, unlike a clip-path.
|
|
819
|
-
shape: { rounded: "rounded-lg", pill: "rounded-full", cut: "rounded-[10px] [corner-shape:bevel]" }
|
|
820
|
-
},
|
|
821
|
-
defaultVariants: { variant: "secondary", size: "md", shape: "rounded" }
|
|
822
|
-
});
|
|
823
|
-
var STATUS_TEXT = { success: "text-fg-success", error: "text-fg-danger" };
|
|
824
|
-
function Button({
|
|
825
|
-
asChild,
|
|
826
|
-
loading,
|
|
827
|
-
progress,
|
|
828
|
-
status,
|
|
829
|
-
announce,
|
|
830
|
-
indicator = true,
|
|
831
|
-
shimmer,
|
|
832
|
-
magnetic,
|
|
833
|
-
variant,
|
|
834
|
-
size,
|
|
835
|
-
shape,
|
|
836
|
-
className,
|
|
837
|
-
disabled,
|
|
838
|
-
children,
|
|
839
|
-
...props
|
|
840
|
-
}) {
|
|
841
|
-
const Comp = asChild ? Slot.Root : "button";
|
|
842
|
-
const known = loading && typeof progress === "number" && Number.isFinite(progress);
|
|
843
|
-
const ratio = known ? Math.min(1, Math.max(0, progress)) : 0;
|
|
844
|
-
const glyph = indicator && !asChild && (loading || status) ? status ?? "loading" : null;
|
|
845
|
-
const filled = variant === "primary" || variant === "gradient";
|
|
846
|
-
const button = /* @__PURE__ */ jsx4(
|
|
847
|
-
Comp,
|
|
848
|
-
{
|
|
849
|
-
type: asChild ? void 0 : "button",
|
|
850
|
-
"aria-busy": loading || void 0,
|
|
851
|
-
"data-loading": loading ? "" : void 0,
|
|
852
|
-
"data-variant": variant ?? "secondary",
|
|
853
|
-
"data-kz-status": status ?? void 0,
|
|
854
|
-
"data-kz-magnetic": magnetic ? "" : void 0,
|
|
855
|
-
disabled: asChild ? void 0 : disabled || loading,
|
|
856
|
-
"aria-disabled": asChild && (disabled || loading) ? true : void 0,
|
|
857
|
-
className: buttonVariants({
|
|
858
|
-
variant,
|
|
859
|
-
size,
|
|
860
|
-
shape,
|
|
861
|
-
className: [known && "relative isolate overflow-hidden", shimmer && "kz-sheen", className].filter(Boolean).join(" ") || void 0
|
|
862
|
-
}),
|
|
863
|
-
...props,
|
|
864
|
-
children: asChild ? children : /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
865
|
-
known && /* @__PURE__ */ jsx4("span", { "aria-hidden": true, className: "absolute inset-y-0 left-0 -z-10 bg-current opacity-15 transition-[width] duration-500", style: { width: `${ratio * 100}%` } }),
|
|
866
|
-
glyph && /* @__PURE__ */ jsx4(
|
|
867
|
-
"span",
|
|
868
|
-
{
|
|
869
|
-
"aria-hidden": true,
|
|
870
|
-
"data-slot": "indicator",
|
|
871
|
-
className: "-my-1 grid grid-cols-[1fr] transition-[grid-template-columns,margin,opacity] duration-300 starting:-mr-2 starting:grid-cols-[0fr] starting:opacity-0",
|
|
872
|
-
children: /* @__PURE__ */ jsx4("span", { className: "overflow-hidden", children: /* @__PURE__ */ jsx4(LoaderGlyph, { state: glyph, value: known ? ratio : null, className: ["h-4 w-4", glyph !== "loading" && !filled && STATUS_TEXT[glyph]].filter(Boolean).join(" ") }) })
|
|
873
|
-
}
|
|
874
|
-
),
|
|
875
|
-
children
|
|
876
|
-
] })
|
|
877
|
-
}
|
|
878
|
-
);
|
|
879
|
-
if (announce === void 0 || asChild) return button;
|
|
880
|
-
return /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
881
|
-
button,
|
|
882
|
-
/* @__PURE__ */ jsx4("span", { role: "status", className: "sr-only", children: announce })
|
|
883
|
-
] });
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
// src/field/field.tsx
|
|
887
|
-
import { tv as tv4 } from "tailwind-variants";
|
|
888
|
-
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
889
|
-
var field2 = tv4({
|
|
775
|
+
var field2 = tv3({
|
|
890
776
|
slots: {
|
|
891
777
|
root: "flex flex-col gap-1.5",
|
|
892
778
|
label: "text-xs font-semibold text-fg-secondary",
|
|
@@ -901,11 +787,11 @@ var field2 = tv4({
|
|
|
901
787
|
var s = field2();
|
|
902
788
|
var invalidProps = (invalid) => invalid ? { "aria-invalid": true, "data-invalid": "" } : {};
|
|
903
789
|
function Input({ invalid, className, ...props }) {
|
|
904
|
-
return /* @__PURE__ */
|
|
790
|
+
return /* @__PURE__ */ jsx3("input", { ...invalidProps(invalid), className: s.control({ className }), ...props });
|
|
905
791
|
}
|
|
906
792
|
|
|
907
793
|
// src/data-table/toolbar.tsx
|
|
908
|
-
import { jsx as
|
|
794
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
909
795
|
var asRange = (value) => Array.isArray(value) && value.length === 2 && (typeof value[0] !== "string" || typeof value[1] !== "string") ? [value[0], value[1]] : [null, null];
|
|
910
796
|
var asList = (value) => Array.isArray(value) ? value : [];
|
|
911
797
|
var number = (text) => text.trim() === "" || Number.isNaN(Number(text)) ? null : Number(text);
|
|
@@ -937,7 +823,7 @@ function DataTableFilters({ debounce = 250, children, className }) {
|
|
|
937
823
|
const label = labels.activeFilter(column.header, text);
|
|
938
824
|
return [{ id: column.id, label, onRemove: () => set(column.id, null) }];
|
|
939
825
|
});
|
|
940
|
-
return /* @__PURE__ */
|
|
826
|
+
return /* @__PURE__ */ jsxs4(
|
|
941
827
|
FilterBar,
|
|
942
828
|
{
|
|
943
829
|
label: labels.filters,
|
|
@@ -950,7 +836,7 @@ function DataTableFilters({ debounce = 250, children, className }) {
|
|
|
950
836
|
children: [
|
|
951
837
|
filterable.map((column) => {
|
|
952
838
|
if (column.filter === "text")
|
|
953
|
-
return /* @__PURE__ */
|
|
839
|
+
return /* @__PURE__ */ jsx4(
|
|
954
840
|
SearchField,
|
|
955
841
|
{
|
|
956
842
|
label: labels.search(column.header),
|
|
@@ -966,11 +852,11 @@ function DataTableFilters({ debounce = 250, children, className }) {
|
|
|
966
852
|
column.id
|
|
967
853
|
);
|
|
968
854
|
if (column.filter === "facet")
|
|
969
|
-
return /* @__PURE__ */
|
|
855
|
+
return /* @__PURE__ */ jsx4(FilterMenu, { label: column.header, options: optionsOf(column), value: asList(filters[column.id]), onValueChange: (value) => set(column.id, value) }, column.id);
|
|
970
856
|
const [min, max] = asRange(filters[column.id]);
|
|
971
857
|
const bounds = manualFiltering ? void 0 : table.getColumn(column.id)?.getFacetedMinMaxValues();
|
|
972
|
-
return /* @__PURE__ */
|
|
973
|
-
/* @__PURE__ */
|
|
858
|
+
return /* @__PURE__ */ jsxs4("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
859
|
+
/* @__PURE__ */ jsx4(
|
|
974
860
|
Input,
|
|
975
861
|
{
|
|
976
862
|
type: "number",
|
|
@@ -982,8 +868,8 @@ function DataTableFilters({ debounce = 250, children, className }) {
|
|
|
982
868
|
className: "h-11 w-28"
|
|
983
869
|
}
|
|
984
870
|
),
|
|
985
|
-
/* @__PURE__ */
|
|
986
|
-
/* @__PURE__ */
|
|
871
|
+
/* @__PURE__ */ jsx4("span", { "aria-hidden": true, className: "text-fg-secondary", children: "\u2013" }),
|
|
872
|
+
/* @__PURE__ */ jsx4(
|
|
987
873
|
Input,
|
|
988
874
|
{
|
|
989
875
|
type: "number",
|
|
@@ -1004,14 +890,14 @@ function DataTableFilters({ debounce = 250, children, className }) {
|
|
|
1004
890
|
}
|
|
1005
891
|
function DataTableColumnsMenu({ defaultOpen, className }) {
|
|
1006
892
|
const { table, columns, labels } = useDataTable();
|
|
1007
|
-
return /* @__PURE__ */
|
|
1008
|
-
/* @__PURE__ */
|
|
893
|
+
return /* @__PURE__ */ jsxs4(DropdownMenu.Root, { defaultOpen, modal: false, children: [
|
|
894
|
+
/* @__PURE__ */ jsx4(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs4(Button, { variant: "outline", size: "sm", className, children: [
|
|
1009
895
|
labels.columns,
|
|
1010
|
-
/* @__PURE__ */
|
|
896
|
+
/* @__PURE__ */ jsx4(ChevronGlyph, { className: "h-4 w-4" })
|
|
1011
897
|
] }) }),
|
|
1012
|
-
/* @__PURE__ */
|
|
898
|
+
/* @__PURE__ */ jsx4(DropdownMenu.Content, { align: "end", "aria-label": labels.columns, children: columns.filter((column) => column.hideable !== false).map((column) => {
|
|
1013
899
|
const instance = table.getColumn(column.id);
|
|
1014
|
-
return /* @__PURE__ */
|
|
900
|
+
return /* @__PURE__ */ jsx4(
|
|
1015
901
|
DropdownMenu.CheckboxItem,
|
|
1016
902
|
{
|
|
1017
903
|
checked: instance?.getIsVisible() ?? true,
|
|
@@ -1035,7 +921,7 @@ function DataTableExport({ filename = "export.csv", onExport, className }) {
|
|
|
1035
921
|
link.click();
|
|
1036
922
|
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
1037
923
|
};
|
|
1038
|
-
return /* @__PURE__ */
|
|
924
|
+
return /* @__PURE__ */ jsx4(Button, { variant: "outline", size: "sm", className, onClick: run, children: labels.export });
|
|
1039
925
|
}
|
|
1040
926
|
export {
|
|
1041
927
|
DataTable,
|