@krizaka/ui 3.46.0 → 3.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/account-menu.d.ts +2 -111
- package/dist/account-menu.js +39 -118
- package/dist/account-menu.js.map +1 -1
- package/dist/account-settings.d.ts +163 -0
- package/dist/account-settings.js +354 -0
- package/dist/account-settings.js.map +1 -0
- package/dist/agenda.d.ts +136 -0
- package/dist/agenda.js +90 -0
- package/dist/agenda.js.map +1 -0
- package/dist/avatar-iajODANU.d.ts +114 -0
- package/dist/chunk-3D2YI63L.js +27 -0
- package/dist/chunk-3D2YI63L.js.map +1 -0
- package/dist/chunk-3RVFD3UX.js +85 -0
- package/dist/chunk-3RVFD3UX.js.map +1 -0
- package/dist/{chunk-P4TTKYC4.js → chunk-4LYKBSOG.js} +4 -1
- package/dist/chunk-4LYKBSOG.js.map +1 -0
- package/dist/chunk-S6NYGOJT.js +22 -0
- package/dist/chunk-S6NYGOJT.js.map +1 -0
- package/dist/docs-layout.js +13 -32
- package/dist/docs-layout.js.map +1 -1
- package/dist/docs-nav.js +1 -1
- package/dist/drop-overlay.d.ts +31 -0
- package/dist/drop-overlay.js +86 -0
- package/dist/drop-overlay.js.map +1 -0
- package/dist/motion.css +27 -0
- package/dist/nav-bar.d.ts +1 -1
- package/dist/nav-bar.js +1 -1
- package/dist/settings-layout.d.ts +112 -8
- package/dist/settings-layout.js +274 -28
- package/dist/settings-layout.js.map +1 -1
- package/dist/site-footer.d.ts +1 -1
- package/dist/site-footer.js +1 -1
- package/dist/{sites-inztN_Bv.d.ts → sites-DlR8jicc.d.ts} +1 -1
- package/dist/sites.d.ts +1 -1
- package/dist/sites.js +3 -0
- package/dist/sites.js.map +1 -1
- package/dist/upload-queue.d.ts +67 -0
- package/dist/upload-queue.js +76 -0
- package/dist/upload-queue.js.map +1 -0
- package/package.json +33 -7
- package/registry/account-menu.json +2 -2
- package/registry/account-settings.json +721 -0
- package/registry/achievement.json +1 -1
- package/registry/action-bar.json +1 -1
- package/registry/activity-feed.json +1 -1
- package/registry/agenda.json +293 -0
- package/registry/alert.json +1 -1
- package/registry/anatomy-plate.json +1 -1
- package/registry/app-header.json +1 -1
- package/registry/app-shell.json +1 -1
- package/registry/argument-card.json +1 -1
- package/registry/audio-player.json +1 -1
- package/registry/auth-layout.json +1 -1
- package/registry/avatar.json +1 -1
- package/registry/badge.json +1 -1
- package/registry/bird-plate.json +1 -1
- package/registry/button.json +1 -1
- package/registry/captcha.json +1 -1
- package/registry/card-grid.json +1 -1
- package/registry/card.json +1 -1
- package/registry/catalogue-page.json +1 -1
- package/registry/changelog-page.json +1 -1
- package/registry/chat.json +3 -3
- package/registry/checkbox.json +1 -1
- package/registry/chip-link.json +1 -1
- package/registry/chip-row.json +1 -1
- package/registry/chip.json +1 -1
- package/registry/choice-grid.json +1 -1
- package/registry/code-block.json +1 -1
- package/registry/combobox.json +1 -1
- package/registry/command.json +1 -1
- package/registry/comparison-table.json +1 -1
- package/registry/component-page.json +1 -1
- package/registry/confirm-button.json +1 -1
- package/registry/contact-page.json +1 -1
- package/registry/continue-prompt.json +1 -1
- package/registry/countdown.json +1 -1
- package/registry/cover-hero.json +1 -1
- package/registry/cta-panel.json +1 -1
- package/registry/dashboard-layout.json +1 -1
- package/registry/data-table.json +3 -3
- package/registry/date-picker.json +1 -1
- package/registry/decision-list.json +1 -1
- package/registry/description-list.json +1 -1
- package/registry/detail-layout.json +1 -1
- package/registry/dialog.json +1 -1
- package/registry/docs-article-page.json +1 -1
- package/registry/docs-hub-page.json +1 -1
- package/registry/docs-layout.json +1 -1
- package/registry/docs-nav.json +1 -1
- package/registry/document-viewer.json +1 -1
- package/registry/drop-overlay.json +182 -0
- package/registry/dropdown-menu.json +1 -1
- package/registry/elephant.json +2 -2
- package/registry/empty-state.json +1 -1
- package/registry/engine-flow.json +1 -1
- package/registry/error-page.json +1 -1
- package/registry/examples/account-settings/avatar-picker.d.ts +4 -0
- package/registry/examples/account-settings/avatar-picker.js +15 -0
- package/registry/examples/account-settings/avatar-picker.tsx +15 -0
- package/registry/examples/account-settings/choice-cards.d.ts +4 -0
- package/registry/examples/account-settings/choice-cards.js +24 -0
- package/registry/examples/account-settings/choice-cards.tsx +20 -0
- package/registry/examples/account-settings/language-picker.d.ts +4 -0
- package/registry/examples/account-settings/language-picker.js +25 -0
- package/registry/examples/account-settings/language-picker.tsx +21 -0
- package/registry/examples/account-settings/patterns.d.ts +4 -0
- package/registry/examples/account-settings/patterns.js +29 -0
- package/registry/examples/account-settings/patterns.tsx +39 -0
- package/registry/examples/account-settings/profile.d.ts +4 -0
- package/registry/examples/account-settings/profile.js +70 -0
- package/registry/examples/account-settings/profile.tsx +80 -0
- package/registry/examples/agenda/day.d.ts +4 -0
- package/registry/examples/agenda/day.js +43 -0
- package/registry/examples/agenda/day.tsx +35 -0
- package/registry/examples/drop-overlay/default.d.ts +4 -0
- package/registry/examples/drop-overlay/default.js +20 -0
- package/registry/examples/drop-overlay/default.tsx +18 -0
- package/registry/examples/settings-layout/grouped.d.ts +4 -0
- package/registry/examples/settings-layout/grouped.js +64 -0
- package/registry/examples/settings-layout/grouped.tsx +66 -0
- package/registry/examples/upload-queue/default.d.ts +4 -0
- package/registry/examples/upload-queue/default.js +22 -0
- package/registry/examples/upload-queue/default.tsx +20 -0
- package/registry/examples/upload-queue/tray.d.ts +4 -0
- package/registry/examples/upload-queue/tray.js +21 -0
- package/registry/examples/upload-queue/tray.tsx +19 -0
- package/registry/field.json +1 -1
- package/registry/file-upload.json +1 -1
- package/registry/filter-bar.json +1 -1
- package/registry/flock.json +1 -1
- package/registry/footnote.json +1 -1
- package/registry/force-update-screen.json +1 -1
- package/registry/form.json +3 -3
- package/registry/gallery-page.json +1 -1
- package/registry/genui.json +1 -1
- package/registry/glow-card.json +1 -1
- package/registry/goal-gauge.json +1 -1
- package/registry/how-it-works-page.json +1 -1
- package/registry/image-cropper.json +1 -1
- package/registry/index.json +159 -10
- package/registry/iso.json +1 -1
- package/registry/kanban.json +1 -1
- package/registry/kbd.json +1 -1
- package/registry/landing-page.json +1 -1
- package/registry/landscape.json +1 -1
- package/registry/language-switch.json +1 -1
- package/registry/legal-page.json +1 -1
- package/registry/link-card.json +1 -1
- package/registry/list.json +3 -3
- package/registry/loader.json +1 -1
- package/registry/longform-page.json +1 -1
- package/registry/maintenance-screen.json +1 -1
- package/registry/map.json +2 -2
- package/registry/markdown.json +1 -1
- package/registry/marketing-layout.json +1 -1
- package/registry/marquee.json +1 -1
- package/registry/mascot-quote.json +3 -3
- package/registry/mascot-state.json +3 -3
- package/registry/mascots.json +3 -3
- package/registry/match-dialog.json +1 -1
- package/registry/media-capture.json +1 -1
- package/registry/media-gallery.json +1 -1
- package/registry/media-grid.json +1 -1
- package/registry/meta-row.json +1 -1
- package/registry/meter.json +1 -1
- package/registry/nav-bar.json +2 -2
- package/registry/number-ticker.json +1 -1
- package/registry/opening-hours.json +1 -1
- package/registry/page-header.json +1 -1
- package/registry/page-hero.json +1 -1
- package/registry/page-index.json +1 -1
- package/registry/page.json +1 -1
- package/registry/pagination.json +1 -1
- package/registry/photo-grid.json +1 -1
- package/registry/pointer-light.json +1 -1
- package/registry/popover.json +1 -1
- package/registry/pricing-page.json +1 -1
- package/registry/product-page.json +1 -1
- package/registry/profile-card.json +1 -1
- package/registry/progress.json +1 -1
- package/registry/promise-card.json +1 -1
- package/registry/radio-group.json +93 -5
- package/registry/rail-nav.json +2 -2
- package/registry/recipes.json +1 -1
- package/registry/router.json +1 -1
- package/registry/scroll-stage.json +1 -1
- package/registry/search-field.json +1 -1
- package/registry/section-backdrop.json +1 -1
- package/registry/separator.json +1 -1
- package/registry/service-card.json +1 -1
- package/registry/settings-layout.json +79 -13
- package/registry/showcase.json +1 -1
- package/registry/site-footer.json +2 -2
- package/registry/sites.json +2 -2
- package/registry/skeleton.json +1 -1
- package/registry/skip-link.json +1 -1
- package/registry/slider.json +1 -1
- package/registry/slot-picker.json +1 -1
- package/registry/slot.json +1 -1
- package/registry/specimen-tag.json +1 -1
- package/registry/spinner.json +1 -1
- package/registry/split-view.json +1 -1
- package/registry/stage-banner.json +1 -1
- package/registry/stat.json +1 -1
- package/registry/status-page.json +1 -1
- package/registry/step-progress.json +1 -1
- package/registry/step-showcase.json +1 -1
- package/registry/stepper.json +1 -1
- package/registry/sticky-action.json +1 -1
- package/registry/swipe-deck.json +1 -1
- package/registry/switch.json +1 -1
- package/registry/tabs.json +1 -1
- package/registry/tag-input.json +3 -3
- package/registry/tag-selector.json +1 -1
- package/registry/terminal-replay.json +1 -1
- package/registry/theme.json +1 -1
- package/registry/toast.json +1 -1
- package/registry/toc.json +1 -1
- package/registry/tooltip.json +1 -1
- package/registry/tree-view.json +1 -1
- package/registry/update-prompt.json +1 -1
- package/registry/upload-queue.json +243 -0
- package/registry/verified-badge.json +1 -1
- package/registry/vertical-video.json +1 -1
- package/registry/video-player.json +1 -1
- package/registry/video-trimmer.json +1 -1
- package/registry/virtual.json +1 -1
- package/registry/waveform.json +1 -1
- package/dist/chunk-P4TTKYC4.js.map +0 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
/** True while the drag carries files (not text or a link): the only drag that should raise the overlay. */
|
|
4
|
+
declare function dragHasFiles(transfer: {
|
|
5
|
+
types?: readonly string[] | DOMStringList;
|
|
6
|
+
} | null | undefined): boolean;
|
|
7
|
+
/** One accepted kind: a MIME type (`application/pdf`), a family (`image/*`) or an extension (`.pdf`). */
|
|
8
|
+
type AcceptRule = string;
|
|
9
|
+
interface DropSplit<F> {
|
|
10
|
+
accepted: F[];
|
|
11
|
+
rejected: F[];
|
|
12
|
+
}
|
|
13
|
+
/** Splits dropped files by `accept` (no rule: everything is accepted). */
|
|
14
|
+
declare function splitDropped<F extends Pick<File, "name" | "type">>(files: readonly F[], accept?: readonly AcceptRule[]): DropSplit<F>;
|
|
15
|
+
|
|
16
|
+
type DropOverlayProps = Omit<React.ComponentProps<"div">, "children" | "onDrop"> & {
|
|
17
|
+
/** What the overlay says (“Drop to check”) — passed translated. */
|
|
18
|
+
label: string;
|
|
19
|
+
/** One line under it (“PDF or text”). */
|
|
20
|
+
hint?: string;
|
|
21
|
+
/** The files dropped: the accepted ones, then the ones `accept` refused. */
|
|
22
|
+
onFiles: (accepted: File[], rejected: File[]) => void;
|
|
23
|
+
/** What is accepted: MIME types, families (`image/*`) or extensions (`.pdf`). */
|
|
24
|
+
accept?: readonly AcceptRule[];
|
|
25
|
+
/** Turns the window back into a plain page (while a modal is open, signed out). */
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
};
|
|
28
|
+
/** Drag a file anywhere on the page: a full-window overlay accepts it. */
|
|
29
|
+
declare function DropOverlay({ label, hint, onFiles, accept, disabled, className, ...props }: DropOverlayProps): React.JSX.Element | null;
|
|
30
|
+
|
|
31
|
+
export { type AcceptRule, DropOverlay, type DropOverlayProps, type DropSplit, dragHasFiles, splitDropped };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-S6NYGOJT.js";
|
|
4
|
+
|
|
5
|
+
// src/drop-overlay/drop-overlay.tsx
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
|
|
8
|
+
// src/drop-overlay/files.ts
|
|
9
|
+
function dragHasFiles(transfer) {
|
|
10
|
+
return Array.from(transfer?.types ?? []).includes("Files");
|
|
11
|
+
}
|
|
12
|
+
function matches(file, rule) {
|
|
13
|
+
const wanted = rule.trim().toLowerCase();
|
|
14
|
+
if (wanted.startsWith(".")) return file.name.toLowerCase().endsWith(wanted);
|
|
15
|
+
if (wanted.endsWith("/*")) return file.type.toLowerCase().startsWith(wanted.slice(0, -1));
|
|
16
|
+
return file.type.toLowerCase() === wanted;
|
|
17
|
+
}
|
|
18
|
+
function splitDropped(files, accept) {
|
|
19
|
+
if (!accept || accept.length === 0) return { accepted: [...files], rejected: [] };
|
|
20
|
+
const accepted = [];
|
|
21
|
+
const rejected = [];
|
|
22
|
+
for (const file of files) (accept.some((rule) => matches(file, rule)) ? accepted : rejected).push(file);
|
|
23
|
+
return { accepted, rejected };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/drop-overlay/drop-overlay.tsx
|
|
27
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
28
|
+
function DropOverlay({ label, hint, onFiles, accept, disabled, className, ...props }) {
|
|
29
|
+
const [active, setActive] = React.useState(false);
|
|
30
|
+
const depth = React.useRef(0);
|
|
31
|
+
const latest = React.useRef({ onFiles, accept });
|
|
32
|
+
React.useEffect(() => {
|
|
33
|
+
latest.current = { onFiles, accept };
|
|
34
|
+
});
|
|
35
|
+
React.useEffect(() => {
|
|
36
|
+
if (disabled) return;
|
|
37
|
+
const reset = () => {
|
|
38
|
+
depth.current = 0;
|
|
39
|
+
setActive(false);
|
|
40
|
+
};
|
|
41
|
+
const carrying = (event) => dragHasFiles(event.dataTransfer);
|
|
42
|
+
const enter = (event) => {
|
|
43
|
+
if (!carrying(event)) return;
|
|
44
|
+
depth.current += 1;
|
|
45
|
+
setActive(true);
|
|
46
|
+
};
|
|
47
|
+
const over = (event) => {
|
|
48
|
+
if (carrying(event)) event.preventDefault();
|
|
49
|
+
};
|
|
50
|
+
const leave = (event) => {
|
|
51
|
+
if (!carrying(event)) return;
|
|
52
|
+
depth.current = Math.max(0, depth.current - 1);
|
|
53
|
+
if (depth.current === 0) setActive(false);
|
|
54
|
+
};
|
|
55
|
+
const drop = (event) => {
|
|
56
|
+
if (!carrying(event)) return;
|
|
57
|
+
event.preventDefault();
|
|
58
|
+
const files = Array.from(event.dataTransfer?.files ?? []);
|
|
59
|
+
reset();
|
|
60
|
+
const { accepted, rejected } = splitDropped(files, latest.current.accept);
|
|
61
|
+
latest.current.onFiles(accepted, rejected);
|
|
62
|
+
};
|
|
63
|
+
window.addEventListener("dragenter", enter);
|
|
64
|
+
window.addEventListener("dragover", over);
|
|
65
|
+
window.addEventListener("dragleave", leave);
|
|
66
|
+
window.addEventListener("drop", drop);
|
|
67
|
+
return () => {
|
|
68
|
+
window.removeEventListener("dragenter", enter);
|
|
69
|
+
window.removeEventListener("dragover", over);
|
|
70
|
+
window.removeEventListener("dragleave", leave);
|
|
71
|
+
window.removeEventListener("drop", drop);
|
|
72
|
+
reset();
|
|
73
|
+
};
|
|
74
|
+
}, [disabled]);
|
|
75
|
+
if (!active) return null;
|
|
76
|
+
return /* @__PURE__ */ jsx("div", { role: "status", "data-state": "open", className: cn("kz-drop-overlay", className), ...props, children: /* @__PURE__ */ jsxs("div", { className: "kz-drop-overlay-card", children: [
|
|
77
|
+
/* @__PURE__ */ jsx("span", { className: "text-lg font-semibold text-fg", children: label }),
|
|
78
|
+
hint ? /* @__PURE__ */ jsx("span", { className: "text-sm text-fg-secondary", children: hint }) : null
|
|
79
|
+
] }) });
|
|
80
|
+
}
|
|
81
|
+
export {
|
|
82
|
+
DropOverlay,
|
|
83
|
+
dragHasFiles,
|
|
84
|
+
splitDropped
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=drop-overlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/drop-overlay/drop-overlay.tsx","../src/drop-overlay/files.ts"],"sourcesContent":["// Client (window listeners). The whole window is the drop target: while files are dragged over the page a full-window overlay\n// says so, and the dropped files go to `onFiles` (accepted, rejected). No dashed box in the page; the product keeps a real\n// file input behind its primary action for the keyboard and for phones. Motion: motion.css (« DROP OVERLAY »).\nimport * as React from \"react\";\n\nimport { cn } from \"../cn\";\nimport { type AcceptRule, dragHasFiles, splitDropped } from \"./files\";\n\nexport type DropOverlayProps = Omit<React.ComponentProps<\"div\">, \"children\" | \"onDrop\"> & {\n /** What the overlay says (“Drop to check”) — passed translated. */\n label: string;\n /** One line under it (“PDF or text”). */\n hint?: string;\n /** The files dropped: the accepted ones, then the ones `accept` refused. */\n onFiles: (accepted: File[], rejected: File[]) => void;\n /** What is accepted: MIME types, families (`image/*`) or extensions (`.pdf`). */\n accept?: readonly AcceptRule[];\n /** Turns the window back into a plain page (while a modal is open, signed out). */\n disabled?: boolean;\n};\n\n/** Drag a file anywhere on the page: a full-window overlay accepts it. */\nexport function DropOverlay({ label, hint, onFiles, accept, disabled, className, ...props }: DropOverlayProps) {\n const [active, setActive] = React.useState(false);\n const depth = React.useRef(0);\n const latest = React.useRef({ onFiles, accept });\n React.useEffect(() => {\n latest.current = { onFiles, accept };\n });\n\n React.useEffect(() => {\n if (disabled) return;\n const reset = () => {\n depth.current = 0;\n setActive(false);\n };\n const carrying = (event: Event) => dragHasFiles((event as DragEvent).dataTransfer);\n const enter = (event: Event) => {\n if (!carrying(event)) return;\n depth.current += 1;\n setActive(true);\n };\n const over = (event: Event) => {\n if (carrying(event)) event.preventDefault();\n };\n const leave = (event: Event) => {\n if (!carrying(event)) return;\n depth.current = Math.max(0, depth.current - 1);\n if (depth.current === 0) setActive(false);\n };\n const drop = (event: Event) => {\n if (!carrying(event)) return;\n event.preventDefault();\n const files = Array.from((event as DragEvent).dataTransfer?.files ?? []);\n reset();\n const { accepted, rejected } = splitDropped(files, latest.current.accept);\n latest.current.onFiles(accepted, rejected);\n };\n window.addEventListener(\"dragenter\", enter);\n window.addEventListener(\"dragover\", over);\n window.addEventListener(\"dragleave\", leave);\n window.addEventListener(\"drop\", drop);\n return () => {\n window.removeEventListener(\"dragenter\", enter);\n window.removeEventListener(\"dragover\", over);\n window.removeEventListener(\"dragleave\", leave);\n window.removeEventListener(\"drop\", drop);\n reset();\n };\n }, [disabled]);\n\n if (!active) return null;\n return (\n <div role=\"status\" data-state=\"open\" className={cn(\"kz-drop-overlay\", className)} {...props}>\n <div className=\"kz-drop-overlay-card\">\n <span className=\"text-lg font-semibold text-fg\">{label}</span>\n {hint ? <span className=\"text-sm text-fg-secondary\">{hint}</span> : null}\n </div>\n </div>\n );\n}\n","// Headless: what a drag carries and which of the dropped files a product accepts.\n\n/** True while the drag carries files (not text or a link): the only drag that should raise the overlay. */\nexport function dragHasFiles(transfer: { types?: readonly string[] | DOMStringList } | null | undefined): boolean {\n return Array.from(transfer?.types ?? []).includes(\"Files\");\n}\n\n/** One accepted kind: a MIME type (`application/pdf`), a family (`image/*`) or an extension (`.pdf`). */\nexport type AcceptRule = string;\n\nfunction matches(file: Pick<File, \"name\" | \"type\">, rule: AcceptRule): boolean {\n const wanted = rule.trim().toLowerCase();\n if (wanted.startsWith(\".\")) return file.name.toLowerCase().endsWith(wanted);\n if (wanted.endsWith(\"/*\")) return file.type.toLowerCase().startsWith(wanted.slice(0, -1));\n return file.type.toLowerCase() === wanted;\n}\n\nexport interface DropSplit<F> {\n accepted: F[];\n rejected: F[];\n}\n\n/** Splits dropped files by `accept` (no rule: everything is accepted). */\nexport function splitDropped<F extends Pick<File, \"name\" | \"type\">>(files: readonly F[], accept?: readonly AcceptRule[]): DropSplit<F> {\n if (!accept || accept.length === 0) return { accepted: [...files], rejected: [] };\n const accepted: F[] = [];\n const rejected: F[] = [];\n for (const file of files) (accept.some((rule) => matches(file, rule)) ? accepted : rejected).push(file);\n return { accepted, rejected };\n}\n"],"mappings":"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","names":[]}
|
package/dist/motion.css
CHANGED
|
@@ -768,3 +768,30 @@ svg[data-kz-icon="ExternalIcon"] {
|
|
|
768
768
|
@media (prefers-reduced-motion: reduce) {
|
|
769
769
|
::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
|
|
770
770
|
}
|
|
771
|
+
|
|
772
|
+
/* ── DROP OVERLAY ───────────────────────────────────────────────────────────────────────────────────────────────────
|
|
773
|
+
<DropOverlay> (@krizaka/ui/drop-overlay): while files are dragged over the window, a full-window veil and one centred
|
|
774
|
+
card arrive over the motion tokens. It never takes the pointer (the window keeps receiving the drop). Reduced motion:
|
|
775
|
+
it appears at once. */
|
|
776
|
+
.kz-drop-overlay {
|
|
777
|
+
position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center; pointer-events: none;
|
|
778
|
+
background: color-mix(in srgb, var(--kz-surface-0) 78%, transparent); backdrop-filter: blur(6px);
|
|
779
|
+
animation: kz-drop-in var(--kz-motion-duration-base) var(--kz-motion-ease-out) both;
|
|
780
|
+
}
|
|
781
|
+
.kz-drop-overlay-card {
|
|
782
|
+
display: flex; flex-direction: column; align-items: center; gap: 0.25rem; padding: 2rem 2.5rem; text-align: center;
|
|
783
|
+
border: 2px solid var(--kz-accent); border-radius: 1rem; background: var(--kz-surface-1);
|
|
784
|
+
animation: kz-drop-card var(--kz-motion-duration-base) var(--kz-motion-ease-out) both;
|
|
785
|
+
}
|
|
786
|
+
@keyframes kz-drop-in { from { opacity: 0; } to { opacity: 1; } }
|
|
787
|
+
@keyframes kz-drop-card { from { opacity: 0; transform: translateY(8px) scale(0.98); } to { opacity: 1; transform: none; } }
|
|
788
|
+
@media (prefers-reduced-motion: reduce) { .kz-drop-overlay, .kz-drop-overlay-card { animation: none; } }
|
|
789
|
+
|
|
790
|
+
/* ── WORKING (upload queue, task tray) ──────────────────────────────────────────────────────────────────────────────
|
|
791
|
+
What is working moves, nothing else (.kz-working): a row's progress fill shimmers (text never animates: contrast stays AA). The tray rises in.
|
|
792
|
+
Reduced motion: no shimmer, no rise. */
|
|
793
|
+
.kz-working { background-image: linear-gradient(100deg, transparent 30%, color-mix(in srgb, var(--kz-fg) 22%, transparent) 50%, transparent 70%); background-size: 200% 100%; background-repeat: no-repeat; animation: kz-shimmer 1.6s linear infinite; }
|
|
794
|
+
@keyframes kz-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
|
|
795
|
+
.kz-tray { animation: kz-tray-in var(--kz-motion-duration-base) var(--kz-motion-ease-out) both; }
|
|
796
|
+
@keyframes kz-tray-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
|
|
797
|
+
@media (prefers-reduced-motion: reduce) { .kz-working, .kz-tray { animation: none; background-image: none; } }
|
package/dist/nav-bar.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as tailwind_variants from 'tailwind-variants';
|
|
|
2
2
|
import { NavigationMenu } from 'radix-ui';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { LanguageSwitchProps } from './language-switch.js';
|
|
5
|
-
import { S as SiteId, F as FamilyLabels } from './sites-
|
|
5
|
+
import { S as SiteId, F as FamilyLabels } from './sites-DlR8jicc.js';
|
|
6
6
|
|
|
7
7
|
declare const navBar: tailwind_variants.TVReturnType<{
|
|
8
8
|
floating: {
|
package/dist/nav-bar.js
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
import * as tailwind_variants from 'tailwind-variants';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
|
|
4
|
+
/** Where an inline save is: nothing to say, in flight, done (for a moment), or failed. */
|
|
5
|
+
declare const SaveStatus: {
|
|
6
|
+
readonly Idle: "idle";
|
|
7
|
+
readonly Saving: "saving";
|
|
8
|
+
readonly Saved: "saved";
|
|
9
|
+
readonly Error: "error";
|
|
10
|
+
};
|
|
11
|
+
type SaveStatus = (typeof SaveStatus)[keyof typeof SaveStatus];
|
|
12
|
+
/** How long « Saved » stays before the section goes quiet again. */
|
|
13
|
+
declare const SAVED_VISIBLE_MS = 4000;
|
|
14
|
+
interface SaveTracker {
|
|
15
|
+
status: SaveStatus;
|
|
16
|
+
/** The failure of the last try, for the message beside the button. */
|
|
17
|
+
error: unknown;
|
|
18
|
+
/** Runs a save: `saving`, then `saved` (back to `idle` after a moment) or `error`. Never rejects. */
|
|
19
|
+
track: (save: () => Promise<unknown>) => Promise<boolean>;
|
|
20
|
+
/** Clears the status (the form was edited again, or the save was undone). */
|
|
21
|
+
reset: () => void;
|
|
22
|
+
}
|
|
23
|
+
/** The status of one section's save. Feed it to `SettingsSection`'s `save.status`. */
|
|
24
|
+
declare function useSaveStatus(): SaveTracker;
|
|
25
|
+
|
|
4
26
|
declare const settingsLayout: tailwind_variants.TVReturnType<{
|
|
5
27
|
variant: {
|
|
6
28
|
card: {};
|
|
@@ -21,6 +43,18 @@ declare const settingsLayout: tailwind_variants.TVReturnType<{
|
|
|
21
43
|
nav: string;
|
|
22
44
|
navList: string;
|
|
23
45
|
navLink: string;
|
|
46
|
+
sidebar: string;
|
|
47
|
+
sidebarList: string;
|
|
48
|
+
group: string;
|
|
49
|
+
groupLabel: string;
|
|
50
|
+
groupLink: string;
|
|
51
|
+
groupItems: string;
|
|
52
|
+
menu: string;
|
|
53
|
+
menuSummary: string;
|
|
54
|
+
menuChevron: string;
|
|
55
|
+
menuPanel: string;
|
|
56
|
+
navBadge: string;
|
|
57
|
+
header: string;
|
|
24
58
|
content: string;
|
|
25
59
|
section: string;
|
|
26
60
|
sectionHead: string;
|
|
@@ -54,6 +88,18 @@ declare const settingsLayout: tailwind_variants.TVReturnType<{
|
|
|
54
88
|
nav: string;
|
|
55
89
|
navList: string;
|
|
56
90
|
navLink: string;
|
|
91
|
+
sidebar: string;
|
|
92
|
+
sidebarList: string;
|
|
93
|
+
group: string;
|
|
94
|
+
groupLabel: string;
|
|
95
|
+
groupLink: string;
|
|
96
|
+
groupItems: string;
|
|
97
|
+
menu: string;
|
|
98
|
+
menuSummary: string;
|
|
99
|
+
menuChevron: string;
|
|
100
|
+
menuPanel: string;
|
|
101
|
+
navBadge: string;
|
|
102
|
+
header: string;
|
|
57
103
|
content: string;
|
|
58
104
|
section: string;
|
|
59
105
|
sectionHead: string;
|
|
@@ -87,6 +133,18 @@ declare const settingsLayout: tailwind_variants.TVReturnType<{
|
|
|
87
133
|
nav: string;
|
|
88
134
|
navList: string;
|
|
89
135
|
navLink: string;
|
|
136
|
+
sidebar: string;
|
|
137
|
+
sidebarList: string;
|
|
138
|
+
group: string;
|
|
139
|
+
groupLabel: string;
|
|
140
|
+
groupLink: string;
|
|
141
|
+
groupItems: string;
|
|
142
|
+
menu: string;
|
|
143
|
+
menuSummary: string;
|
|
144
|
+
menuChevron: string;
|
|
145
|
+
menuPanel: string;
|
|
146
|
+
navBadge: string;
|
|
147
|
+
header: string;
|
|
90
148
|
content: string;
|
|
91
149
|
section: string;
|
|
92
150
|
sectionHead: string;
|
|
@@ -112,14 +170,27 @@ interface SettingsNavItem {
|
|
|
112
170
|
icon?: React.ReactNode;
|
|
113
171
|
/** The section shown now: `aria-current`. */
|
|
114
172
|
current?: boolean;
|
|
173
|
+
/** A small count or status after the label (`3`, `New`). */
|
|
174
|
+
badge?: React.ReactNode;
|
|
175
|
+
}
|
|
176
|
+
interface SettingsNavGroup {
|
|
177
|
+
/** Its id. */
|
|
178
|
+
id: string;
|
|
179
|
+
/** The group's title (`Library`, `Money`). */
|
|
180
|
+
label: string;
|
|
181
|
+
items: readonly SettingsNavItem[];
|
|
115
182
|
}
|
|
183
|
+
/** Past this many sections a phone gets one menu instead of a strip of chips (« never more than about 5 items in a horizontal tab bar »). */
|
|
184
|
+
declare const SETTINGS_CHIPS_MAX = 5;
|
|
116
185
|
type SettingsLayoutProps = Omit<React.ComponentProps<"div">, "title"> & {
|
|
117
186
|
/** The screen's title (`Settings`). */
|
|
118
187
|
title?: React.ReactNode;
|
|
119
188
|
/** One sentence under it. */
|
|
120
189
|
description?: React.ReactNode;
|
|
121
|
-
/**
|
|
122
|
-
|
|
190
|
+
/** What the screen is about, above the sections: who the account is, with their actions. Replaces `title` and `description`. */
|
|
191
|
+
header?: React.ReactNode;
|
|
192
|
+
/** The sections, alone or in titled groups. */
|
|
193
|
+
nav: readonly SettingsNavItem[] | readonly SettingsNavGroup[];
|
|
123
194
|
/** The navigation's accessible name (`Settings sections`). */
|
|
124
195
|
navLabel: string;
|
|
125
196
|
/** The app's link component for the sections (Next's `Link`); an `<a>` otherwise. */
|
|
@@ -132,9 +203,42 @@ type SettingsLayoutProps = Omit<React.ComponentProps<"div">, "title"> & {
|
|
|
132
203
|
/** The current section's forms (`SettingsSection`). */
|
|
133
204
|
children: React.ReactNode;
|
|
134
205
|
};
|
|
135
|
-
/** A settings screen: sections on the left (chips on a phone), forms on the right. */
|
|
136
|
-
declare function SettingsLayout({ title, description, nav, navLabel, linkAs: Link, variant, className, children, ...props }: SettingsLayoutProps): React.JSX.Element;
|
|
206
|
+
/** A settings screen: sections on the left (chips on a phone, one menu past five), forms on the right. */
|
|
207
|
+
declare function SettingsLayout({ title, description, header, nav, navLabel, linkAs: Link, variant, className, children, ...props }: SettingsLayoutProps): React.JSX.Element;
|
|
208
|
+
interface SectionSaveLabels {
|
|
209
|
+
/** “Save”. */
|
|
210
|
+
save: string;
|
|
211
|
+
/** “Saving…”. */
|
|
212
|
+
saving: string;
|
|
213
|
+
/** “Saved”. */
|
|
214
|
+
saved: string;
|
|
215
|
+
/** What failed, one sentence (“Could not save. Try again.”). */
|
|
216
|
+
error: string;
|
|
217
|
+
/** “Undo” — only shown after a save, when `onUndo` is given. */
|
|
218
|
+
undo: string;
|
|
219
|
+
/** “Discard changes” — only shown while dirty, when `onDiscard` is given. */
|
|
220
|
+
discard: string;
|
|
221
|
+
}
|
|
222
|
+
/** The one save of a section: its dirty state, its status, its words. */
|
|
223
|
+
interface SectionSave {
|
|
224
|
+
/** Whether a field differs from what is saved: the save is enabled only then. */
|
|
225
|
+
dirty: boolean;
|
|
226
|
+
/** Where the save is (`useSaveStatus().status`). */
|
|
227
|
+
status: SaveStatus;
|
|
228
|
+
/** Saves the section (the form's submit, Enter included). */
|
|
229
|
+
onSave: () => void;
|
|
230
|
+
/** Puts the previous values back after a save, optimistic update included. */
|
|
231
|
+
onUndo?: () => void;
|
|
232
|
+
/** Throws the edits away while dirty. */
|
|
233
|
+
onDiscard?: () => void;
|
|
234
|
+
labels: SectionSaveLabels;
|
|
235
|
+
}
|
|
137
236
|
type SettingsSectionProps = Omit<React.ComponentProps<"section">, "title"> & {
|
|
237
|
+
/**
|
|
238
|
+
* One save for the whole section: the section becomes a form, the foot shows the Save (enabled while dirty), the
|
|
239
|
+
* result in a live region (saved, or the error as an alert) and an undo after a save. Replaces `footer`.
|
|
240
|
+
*/
|
|
241
|
+
save?: SectionSave;
|
|
138
242
|
/** The section's title: it names the region (and is its anchor's target when `id` is set). */
|
|
139
243
|
title: React.ReactNode;
|
|
140
244
|
/** What these settings change, in one sentence. */
|
|
@@ -146,11 +250,11 @@ type SettingsSectionProps = Omit<React.ComponentProps<"section">, "title"> & {
|
|
|
146
250
|
* @default "card"
|
|
147
251
|
*/
|
|
148
252
|
variant?: "card" | "flat";
|
|
149
|
-
/** The fields (or, flat, the `SettingsRow`s). */
|
|
150
|
-
children
|
|
253
|
+
/** The fields (or, flat, the `SettingsRow`s). A section of a title, a sentence and a foot action has none. */
|
|
254
|
+
children?: React.ReactNode;
|
|
151
255
|
};
|
|
152
256
|
/** A group of settings: a titled card with its fields and its own save, or flat rows under a title. */
|
|
153
|
-
declare function SettingsSection({ title, description, footer, variant, id, className, children, ...props }: SettingsSectionProps): React.JSX.Element;
|
|
257
|
+
declare function SettingsSection({ title, description, footer, save, variant, id, className, children, ...props }: SettingsSectionProps): React.JSX.Element;
|
|
154
258
|
type SettingsRowProps = Omit<React.ComponentProps<"div">, "title"> & {
|
|
155
259
|
/** What the setting is (`Username`). */
|
|
156
260
|
label: React.ReactNode;
|
|
@@ -164,4 +268,4 @@ type SettingsRowProps = Omit<React.ComponentProps<"div">, "title"> & {
|
|
|
164
268
|
/** One setting: its label and help on the left, its control or value on the right. Put rows in a flat `SettingsSection`. */
|
|
165
269
|
declare function SettingsRow({ label, description, htmlFor, className, children, ...props }: SettingsRowProps): React.JSX.Element;
|
|
166
270
|
|
|
167
|
-
export { SettingsLayout, type SettingsLayoutProps, type SettingsNavItem, SettingsRow, type SettingsRowProps, SettingsSection, type SettingsSectionProps, settingsLayout };
|
|
271
|
+
export { SAVED_VISIBLE_MS, SETTINGS_CHIPS_MAX, SaveStatus, type SaveTracker, SettingsLayout, type SettingsLayoutProps, type SettingsNavGroup, type SettingsNavItem, SettingsRow, type SettingsRowProps, SettingsSection, type SettingsSectionProps, settingsLayout, useSaveStatus };
|