@krizaka/ui 1.3.0 → 2.0.0-beta.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 +99 -4
- package/dist/avatar.d.ts +98 -0
- package/dist/avatar.js +48 -0
- package/dist/avatar.js.map +1 -0
- package/dist/badge.d.ts +64 -0
- package/dist/badge.js +31 -0
- package/dist/badge.js.map +1 -0
- package/dist/button.d.ts +76 -0
- package/dist/button.js +46 -0
- package/dist/button.js.map +1 -0
- package/dist/chunk-CPMZS4XA.js +11 -0
- package/dist/chunk-CPMZS4XA.js.map +1 -0
- package/dist/cn.d.ts +10 -0
- package/dist/cn.js +7 -0
- package/dist/cn.js.map +1 -0
- package/dist/countdown.d.ts +46 -0
- package/dist/countdown.js +74 -0
- package/dist/countdown.js.map +1 -0
- package/dist/empty-state.d.ts +63 -0
- package/dist/empty-state.js +26 -0
- package/dist/empty-state.js.map +1 -0
- package/dist/field.d.ts +80 -0
- package/dist/field.js +47 -0
- package/dist/field.js.map +1 -0
- package/dist/index.d.ts +6 -6
- package/dist/skeleton.d.ts +28 -0
- package/dist/skeleton.js +18 -0
- package/dist/skeleton.js.map +1 -0
- package/dist/slot.d.ts +11 -0
- package/dist/slot.js +9 -0
- package/dist/slot.js.map +1 -0
- package/dist/spinner.d.ts +31 -0
- package/dist/spinner.js +31 -0
- package/dist/spinner.js.map +1 -0
- package/dist/theme.d.ts +95 -0
- package/dist/theme.js +140 -0
- package/dist/theme.js.map +1 -0
- package/package.json +176 -7
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/countdown/core.ts
|
|
4
|
+
import { useSyncExternalStore } from "react";
|
|
5
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
6
|
+
var timer = null;
|
|
7
|
+
function subscribe(listener) {
|
|
8
|
+
listeners.add(listener);
|
|
9
|
+
timer ??= setInterval(() => listeners.forEach((l) => l()), 1e3);
|
|
10
|
+
return () => {
|
|
11
|
+
listeners.delete(listener);
|
|
12
|
+
if (listeners.size === 0 && timer) {
|
|
13
|
+
clearInterval(timer);
|
|
14
|
+
timer = null;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
var nowSecond = () => Math.floor(Date.now() / 1e3) * 1e3;
|
|
19
|
+
function useCountdown(target, skewMs = 0) {
|
|
20
|
+
const now = useSyncExternalStore(subscribe, nowSecond, nowSecond);
|
|
21
|
+
return Math.max(0, new Date(target).getTime() - (now + skewMs));
|
|
22
|
+
}
|
|
23
|
+
function splitDuration(ms) {
|
|
24
|
+
const total = Math.max(0, Math.floor(ms / 1e3));
|
|
25
|
+
return { d: Math.floor(total / 86400), h: Math.floor(total % 86400 / 3600), m: Math.floor(total % 3600 / 60), s: total % 60 };
|
|
26
|
+
}
|
|
27
|
+
function countdownParts(ms, units) {
|
|
28
|
+
const { d, h, m, s } = splitDuration(ms);
|
|
29
|
+
return d > 0 ? [[d, units.d], [h, units.h], [m, units.m]] : [[h, units.h], [m, units.m], [s, units.s]];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/countdown/countdown.tsx
|
|
33
|
+
import { tv } from "tailwind-variants";
|
|
34
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
35
|
+
var countdown = tv({
|
|
36
|
+
slots: {
|
|
37
|
+
root: "inline-flex items-baseline gap-1.5 font-display font-black tabular-nums tracking-tight text-fg",
|
|
38
|
+
segment: "inline-flex items-baseline",
|
|
39
|
+
unit: "ml-0.5 text-[0.5em] font-bold uppercase text-fg-secondary"
|
|
40
|
+
},
|
|
41
|
+
variants: {
|
|
42
|
+
size: { sm: { root: "text-sm" }, md: { root: "text-xl" }, lg: { root: "text-3xl sm:text-4xl" } },
|
|
43
|
+
urgent: { true: { root: "text-danger" } }
|
|
44
|
+
},
|
|
45
|
+
defaultVariants: { size: "md" }
|
|
46
|
+
});
|
|
47
|
+
function Countdown({ target, skewMs = 0, units, urgentBelowMs = 6e4, size = "md", label, className }) {
|
|
48
|
+
const ms = useCountdown(target, skewMs);
|
|
49
|
+
const urgent = ms > 0 && ms < urgentBelowMs;
|
|
50
|
+
const parts = countdownParts(ms, units);
|
|
51
|
+
const s = countdown({ size, urgent });
|
|
52
|
+
return /* @__PURE__ */ jsx(
|
|
53
|
+
"span",
|
|
54
|
+
{
|
|
55
|
+
role: "timer",
|
|
56
|
+
"aria-label": label,
|
|
57
|
+
"data-urgent": urgent ? "" : void 0,
|
|
58
|
+
"data-ended": ms === 0 ? "" : void 0,
|
|
59
|
+
suppressHydrationWarning: true,
|
|
60
|
+
className: s.root({ className }),
|
|
61
|
+
children: parts.map(([value, unit], i) => /* @__PURE__ */ jsxs("span", { className: s.segment({ className: urgent && i === parts.length - 1 ? "motion-safe:animate-pulse" : void 0 }), children: [
|
|
62
|
+
String(value).padStart(2, "0"),
|
|
63
|
+
/* @__PURE__ */ jsx("span", { className: s.unit(), children: unit })
|
|
64
|
+
] }, unit))
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
export {
|
|
69
|
+
Countdown,
|
|
70
|
+
countdownParts,
|
|
71
|
+
splitDuration,
|
|
72
|
+
useCountdown
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=countdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/countdown/core.ts","../src/countdown/countdown.tsx"],"sourcesContent":["// The countdown's clock, shared by the web (`@krizaka/ui/countdown`) and native renders: no DOM import.\nimport { useSyncExternalStore } from \"react\";\n\n// One clock for every countdown on the page: it ticks each second while someone listens.\nconst listeners = new Set<() => void>();\nlet timer: ReturnType<typeof setInterval> | null = null;\n\nfunction subscribe(listener: () => void) {\n listeners.add(listener);\n timer ??= setInterval(() => listeners.forEach((l) => l()), 1000);\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0 && timer) {\n clearInterval(timer);\n timer = null;\n }\n };\n}\n\nconst nowSecond = () => Math.floor(Date.now() / 1000) * 1000;\n\n/** Milliseconds left until `target` (never negative), ticking every second. `skewMs` = server clock − this clock. */\nexport function useCountdown(target: Date | string | number, skewMs = 0): number {\n const now = useSyncExternalStore(subscribe, nowSecond, nowSecond);\n return Math.max(0, new Date(target).getTime() - (now + skewMs));\n}\n\n/** Splits a duration into days, hours, minutes and seconds. */\nexport function splitDuration(ms: number): { d: number; h: number; m: number; s: number } {\n const total = Math.max(0, Math.floor(ms / 1000));\n return { d: Math.floor(total / 86400), h: Math.floor((total % 86400) / 3600), m: Math.floor((total % 3600) / 60), s: total % 60 };\n}\n\n/** The short unit labels, passed translated (e.g. `{ d: \"d\", h: \"h\", m: \"m\", s: \"s\" }`). */\nexport type CountdownUnits = { d: string; h: string; m: string; s: string };\n\n/** The three segments shown: days, hours, minutes when there are days; else hours, minutes, seconds. */\nexport function countdownParts(ms: number, units: CountdownUnits): [number, string][] {\n const { d, h, m, s } = splitDuration(ms);\n return d > 0 ? [[d, units.d], [h, units.h], [m, units.m]] : [[h, units.h], [m, units.m], [s, units.s]];\n}\n","// Client: the clock is a hook.\nimport { tv } from \"tailwind-variants\";\n\nimport { countdownParts, type CountdownUnits, useCountdown } from \"./core\";\n\nconst countdown = tv({\n slots: {\n root: \"inline-flex items-baseline gap-1.5 font-display font-black tabular-nums tracking-tight text-fg\",\n segment: \"inline-flex items-baseline\",\n unit: \"ml-0.5 text-[0.5em] font-bold uppercase text-fg-secondary\",\n },\n variants: {\n size: { sm: { root: \"text-sm\" }, md: { root: \"text-xl\" }, lg: { root: \"text-3xl sm:text-4xl\" } },\n urgent: { true: { root: \"text-danger\" } },\n },\n defaultVariants: { size: \"md\" },\n});\n\nexport type CountdownProps = {\n target: Date | string | number;\n /** Server clock − this clock, in milliseconds. */\n skewMs?: number;\n /** The short unit labels, passed translated. */\n units: CountdownUnits;\n /** Below this many milliseconds it turns urgent (`text-danger`, the last segment pulses). Default 60 s. */\n urgentBelowMs?: number;\n size?: \"sm\" | \"md\" | \"lg\";\n /** Accessible name, e.g. \"Ends in\". */\n label: string;\n className?: string;\n};\n\n/**\n * Time left until a moment, as segments (2d 04h 13m 09s — days only when there are some) in tabular figures. Under\n * `urgentBelowMs` it turns to the danger role and its last segment pulses (no motion under prefers-reduced-motion).\n * Words come from the app: `units` are the short unit labels. `role=\"timer\"` without live announcements — the app\n * announces what matters. State: `data-urgent`, `data-ended`.\n *\n * The danger role is large-text safe (≥ 3:1) from `size=\"md\"`; at `size=\"sm\"` an urgent countdown in light mode is\n * under the 4.5:1 of small text.\n */\nexport function Countdown({ target, skewMs = 0, units, urgentBelowMs = 60_000, size = \"md\", label, className }: CountdownProps) {\n const ms = useCountdown(target, skewMs);\n const urgent = ms > 0 && ms < urgentBelowMs;\n const parts = countdownParts(ms, units);\n const s = countdown({ size, urgent });\n return (\n <span\n role=\"timer\"\n aria-label={label}\n data-urgent={urgent ? \"\" : undefined}\n data-ended={ms === 0 ? \"\" : undefined}\n suppressHydrationWarning\n className={s.root({ className })}\n >\n {parts.map(([value, unit], i) => (\n <span key={unit} className={s.segment({ className: urgent && i === parts.length - 1 ? \"motion-safe:animate-pulse\" : undefined })}>\n {String(value).padStart(2, \"0\")}\n <span className={s.unit()}>{unit}</span>\n </span>\n ))}\n </span>\n );\n}\n"],"mappings":";;;AACA,SAAS,4BAA4B;AAGrC,IAAM,YAAY,oBAAI,IAAgB;AACtC,IAAI,QAA+C;AAEnD,SAAS,UAAU,UAAsB;AACvC,YAAU,IAAI,QAAQ;AACtB,YAAU,YAAY,MAAM,UAAU,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,GAAI;AAC/D,SAAO,MAAM;AACX,cAAU,OAAO,QAAQ;AACzB,QAAI,UAAU,SAAS,KAAK,OAAO;AACjC,oBAAc,KAAK;AACnB,cAAQ;AAAA,IACV;AAAA,EACF;AACF;AAEA,IAAM,YAAY,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI;AAGjD,SAAS,aAAa,QAAgC,SAAS,GAAW;AAC/E,QAAM,MAAM,qBAAqB,WAAW,WAAW,SAAS;AAChE,SAAO,KAAK,IAAI,GAAG,IAAI,KAAK,MAAM,EAAE,QAAQ,KAAK,MAAM,OAAO;AAChE;AAGO,SAAS,cAAc,IAA4D;AACxF,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,GAAI,CAAC;AAC/C,SAAO,EAAE,GAAG,KAAK,MAAM,QAAQ,KAAK,GAAG,GAAG,KAAK,MAAO,QAAQ,QAAS,IAAI,GAAG,GAAG,KAAK,MAAO,QAAQ,OAAQ,EAAE,GAAG,GAAG,QAAQ,GAAG;AAClI;AAMO,SAAS,eAAe,IAAY,OAA2C;AACpF,QAAM,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,cAAc,EAAE;AACvC,SAAO,IAAI,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;AACvG;;;ACvCA,SAAS,UAAU;AAuDX,SAEE,KAFF;AAnDR,IAAM,YAAY,GAAG;AAAA,EACnB,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,MAAM;AAAA,EACR;AAAA,EACA,UAAU;AAAA,IACR,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,GAAG,IAAI,EAAE,MAAM,UAAU,GAAG,IAAI,EAAE,MAAM,uBAAuB,EAAE;AAAA,IAC/F,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,EAAE;AAAA,EAC1C;AAAA,EACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CAAC;AAyBM,SAAS,UAAU,EAAE,QAAQ,SAAS,GAAG,OAAO,gBAAgB,KAAQ,OAAO,MAAM,OAAO,UAAU,GAAmB;AAC9H,QAAM,KAAK,aAAa,QAAQ,MAAM;AACtC,QAAM,SAAS,KAAK,KAAK,KAAK;AAC9B,QAAM,QAAQ,eAAe,IAAI,KAAK;AACtC,QAAM,IAAI,UAAU,EAAE,MAAM,OAAO,CAAC;AACpC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,eAAa,SAAS,KAAK;AAAA,MAC3B,cAAY,OAAO,IAAI,KAAK;AAAA,MAC5B,0BAAwB;AAAA,MACxB,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC;AAAA,MAE9B,gBAAM,IAAI,CAAC,CAAC,OAAO,IAAI,GAAG,MACzB,qBAAC,UAAgB,WAAW,EAAE,QAAQ,EAAE,WAAW,UAAU,MAAM,MAAM,SAAS,IAAI,8BAA8B,OAAU,CAAC,GAC5H;AAAA,eAAO,KAAK,EAAE,SAAS,GAAG,GAAG;AAAA,QAC9B,oBAAC,UAAK,WAAW,EAAE,KAAK,GAAI,gBAAK;AAAA,WAFxB,IAGX,CACD;AAAA;AAAA,EACH;AAEJ;","names":[]}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as tailwind_variants from 'tailwind-variants';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
declare const emptyState: tailwind_variants.TVReturnType<{
|
|
5
|
+
[key: string]: {
|
|
6
|
+
[key: string]: tailwind_variants.ClassValue | {
|
|
7
|
+
root?: tailwind_variants.ClassValue;
|
|
8
|
+
icon?: tailwind_variants.ClassValue;
|
|
9
|
+
title?: tailwind_variants.ClassValue;
|
|
10
|
+
description?: tailwind_variants.ClassValue;
|
|
11
|
+
action?: tailwind_variants.ClassValue;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
} | {
|
|
15
|
+
[x: string]: {
|
|
16
|
+
[x: string]: tailwind_variants.ClassValue | {
|
|
17
|
+
root?: tailwind_variants.ClassValue;
|
|
18
|
+
icon?: tailwind_variants.ClassValue;
|
|
19
|
+
title?: tailwind_variants.ClassValue;
|
|
20
|
+
description?: tailwind_variants.ClassValue;
|
|
21
|
+
action?: tailwind_variants.ClassValue;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
} | {}, {
|
|
25
|
+
root: string;
|
|
26
|
+
icon: string;
|
|
27
|
+
title: string;
|
|
28
|
+
description: string;
|
|
29
|
+
action: string;
|
|
30
|
+
}, undefined, {
|
|
31
|
+
[key: string]: {
|
|
32
|
+
[key: string]: tailwind_variants.ClassValue | {
|
|
33
|
+
root?: tailwind_variants.ClassValue;
|
|
34
|
+
icon?: tailwind_variants.ClassValue;
|
|
35
|
+
title?: tailwind_variants.ClassValue;
|
|
36
|
+
description?: tailwind_variants.ClassValue;
|
|
37
|
+
action?: tailwind_variants.ClassValue;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
} | {}, {
|
|
41
|
+
root: string;
|
|
42
|
+
icon: string;
|
|
43
|
+
title: string;
|
|
44
|
+
description: string;
|
|
45
|
+
action: string;
|
|
46
|
+
}, tailwind_variants.TVReturnTypeLike<unknown, {
|
|
47
|
+
root: string;
|
|
48
|
+
icon: string;
|
|
49
|
+
title: string;
|
|
50
|
+
description: string;
|
|
51
|
+
action: string;
|
|
52
|
+
}>>;
|
|
53
|
+
type EmptyStateProps = Omit<React.ComponentProps<"div">, "title"> & {
|
|
54
|
+
/** A decorative icon (hidden from assistive technology). */
|
|
55
|
+
icon?: React.ReactNode;
|
|
56
|
+
title: React.ReactNode;
|
|
57
|
+
description?: React.ReactNode;
|
|
58
|
+
/** What to do next: a Button, a link. */
|
|
59
|
+
action?: React.ReactNode;
|
|
60
|
+
};
|
|
61
|
+
declare function EmptyState({ icon, title, description, action, className, ...props }: EmptyStateProps): React.JSX.Element;
|
|
62
|
+
|
|
63
|
+
export { EmptyState, type EmptyStateProps, emptyState };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// src/empty-state/empty-state.tsx
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
var emptyState = tv({
|
|
5
|
+
slots: {
|
|
6
|
+
root: "flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed border-border-default px-6 py-10 text-center",
|
|
7
|
+
icon: "flex h-12 w-12 items-center justify-center rounded-full bg-surface-2 text-fg-secondary [&>svg]:h-6 [&>svg]:w-6",
|
|
8
|
+
title: "text-sm font-semibold text-fg",
|
|
9
|
+
description: "max-w-sm text-sm text-fg-secondary",
|
|
10
|
+
action: "mt-1 flex flex-wrap items-center justify-center gap-2"
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
var s = emptyState();
|
|
14
|
+
function EmptyState({ icon, title, description, action, className, ...props }) {
|
|
15
|
+
return /* @__PURE__ */ jsxs("div", { role: "status", className: s.root({ className }), ...props, children: [
|
|
16
|
+
icon && /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: s.icon(), children: icon }),
|
|
17
|
+
/* @__PURE__ */ jsx("p", { className: s.title(), children: title }),
|
|
18
|
+
description && /* @__PURE__ */ jsx("p", { className: s.description(), children: description }),
|
|
19
|
+
action && /* @__PURE__ */ jsx("div", { className: s.action(), children: action })
|
|
20
|
+
] });
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
EmptyState,
|
|
24
|
+
emptyState
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=empty-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/empty-state/empty-state.tsx"],"sourcesContent":["// Server-safe. What a list, a search or a panel says when it has nothing to show — every word is a prop.\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nexport const emptyState = tv({\n slots: {\n root: \"flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed border-border-default px-6 py-10 text-center\",\n icon: \"flex h-12 w-12 items-center justify-center rounded-full bg-surface-2 text-fg-secondary [&>svg]:h-6 [&>svg]:w-6\",\n title: \"text-sm font-semibold text-fg\",\n description: \"max-w-sm text-sm text-fg-secondary\",\n action: \"mt-1 flex flex-wrap items-center justify-center gap-2\",\n },\n});\nconst s = emptyState();\n\nexport type EmptyStateProps = Omit<React.ComponentProps<\"div\">, \"title\"> & {\n /** A decorative icon (hidden from assistive technology). */\n icon?: React.ReactNode;\n title: React.ReactNode;\n description?: React.ReactNode;\n /** What to do next: a Button, a link. */\n action?: React.ReactNode;\n};\n\nexport function EmptyState({ icon, title, description, action, className, ...props }: EmptyStateProps) {\n return (\n <div role=\"status\" className={s.root({ className })} {...props}>\n {icon && (\n <div aria-hidden className={s.icon()}>\n {icon}\n </div>\n )}\n <p className={s.title()}>{title}</p>\n {description && <p className={s.description()}>{description}</p>}\n {action && <div className={s.action()}>{action}</div>}\n </div>\n );\n}\n"],"mappings":";AAEA,SAAS,UAAU;AAwBf,SAEI,KAFJ;AAtBG,IAAM,aAAa,GAAG;AAAA,EAC3B,OAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,QAAQ;AAAA,EACV;AACF,CAAC;AACD,IAAM,IAAI,WAAW;AAWd,SAAS,WAAW,EAAE,MAAM,OAAO,aAAa,QAAQ,WAAW,GAAG,MAAM,GAAoB;AACrG,SACE,qBAAC,SAAI,MAAK,UAAS,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OACtD;AAAA,YACC,oBAAC,SAAI,eAAW,MAAC,WAAW,EAAE,KAAK,GAChC,gBACH;AAAA,IAEF,oBAAC,OAAE,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,IAC/B,eAAe,oBAAC,OAAE,WAAW,EAAE,YAAY,GAAI,uBAAY;AAAA,IAC3D,UAAU,oBAAC,SAAI,WAAW,EAAE,OAAO,GAAI,kBAAO;AAAA,KACjD;AAEJ;","names":[]}
|
package/dist/field.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as tailwind_variants from 'tailwind-variants';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
declare const field: tailwind_variants.TVReturnType<{
|
|
5
|
+
[key: string]: {
|
|
6
|
+
[key: string]: tailwind_variants.ClassValue | {
|
|
7
|
+
root?: tailwind_variants.ClassValue;
|
|
8
|
+
label?: tailwind_variants.ClassValue;
|
|
9
|
+
hint?: tailwind_variants.ClassValue;
|
|
10
|
+
error?: tailwind_variants.ClassValue;
|
|
11
|
+
selectWrap?: tailwind_variants.ClassValue;
|
|
12
|
+
chevron?: tailwind_variants.ClassValue;
|
|
13
|
+
control?: tailwind_variants.ClassValue;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
} | {
|
|
17
|
+
[x: string]: {
|
|
18
|
+
[x: string]: tailwind_variants.ClassValue | {
|
|
19
|
+
root?: tailwind_variants.ClassValue;
|
|
20
|
+
label?: tailwind_variants.ClassValue;
|
|
21
|
+
hint?: tailwind_variants.ClassValue;
|
|
22
|
+
error?: tailwind_variants.ClassValue;
|
|
23
|
+
selectWrap?: tailwind_variants.ClassValue;
|
|
24
|
+
chevron?: tailwind_variants.ClassValue;
|
|
25
|
+
control?: tailwind_variants.ClassValue;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
} | {}, {
|
|
29
|
+
root: string;
|
|
30
|
+
label: string;
|
|
31
|
+
control: string;
|
|
32
|
+
hint: string;
|
|
33
|
+
error: string;
|
|
34
|
+
selectWrap: string;
|
|
35
|
+
chevron: string;
|
|
36
|
+
}, undefined, {
|
|
37
|
+
[key: string]: {
|
|
38
|
+
[key: string]: tailwind_variants.ClassValue | {
|
|
39
|
+
root?: tailwind_variants.ClassValue;
|
|
40
|
+
label?: tailwind_variants.ClassValue;
|
|
41
|
+
hint?: tailwind_variants.ClassValue;
|
|
42
|
+
error?: tailwind_variants.ClassValue;
|
|
43
|
+
selectWrap?: tailwind_variants.ClassValue;
|
|
44
|
+
chevron?: tailwind_variants.ClassValue;
|
|
45
|
+
control?: tailwind_variants.ClassValue;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
} | {}, {
|
|
49
|
+
root: string;
|
|
50
|
+
label: string;
|
|
51
|
+
control: string;
|
|
52
|
+
hint: string;
|
|
53
|
+
error: string;
|
|
54
|
+
selectWrap: string;
|
|
55
|
+
chevron: string;
|
|
56
|
+
}, tailwind_variants.TVReturnTypeLike<unknown, {
|
|
57
|
+
root: string;
|
|
58
|
+
label: string;
|
|
59
|
+
control: string;
|
|
60
|
+
hint: string;
|
|
61
|
+
error: string;
|
|
62
|
+
selectWrap: string;
|
|
63
|
+
chevron: string;
|
|
64
|
+
}>>;
|
|
65
|
+
declare const Field: {
|
|
66
|
+
Root: ({ className, ...props }: React.ComponentProps<"div">) => React.JSX.Element;
|
|
67
|
+
Label: ({ className, ...props }: React.ComponentProps<"label">) => React.JSX.Element;
|
|
68
|
+
Hint: ({ className, ...props }: React.ComponentProps<"p">) => React.JSX.Element;
|
|
69
|
+
Error: ({ className, ...props }: React.ComponentProps<"p">) => React.JSX.Element;
|
|
70
|
+
};
|
|
71
|
+
type ControlProps = {
|
|
72
|
+
/** Marks the control invalid: aria-invalid and data-invalid (pair it with a `Field.Error` in aria-describedby). */
|
|
73
|
+
invalid?: boolean;
|
|
74
|
+
};
|
|
75
|
+
declare function Input({ invalid, className, ...props }: React.ComponentProps<"input"> & ControlProps): React.JSX.Element;
|
|
76
|
+
declare function Textarea({ invalid, className, ...props }: React.ComponentProps<"textarea"> & ControlProps): React.JSX.Element;
|
|
77
|
+
/** A native <select>, styled like the other controls (the platform's menu: accessible and right on phones). */
|
|
78
|
+
declare function Select({ invalid, className, ...props }: React.ComponentProps<"select"> & ControlProps): React.JSX.Element;
|
|
79
|
+
|
|
80
|
+
export { Field, Input, Select, Textarea, field };
|
package/dist/field.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-CPMZS4XA.js";
|
|
4
|
+
|
|
5
|
+
// src/field/field.tsx
|
|
6
|
+
import { tv } from "tailwind-variants";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
var field = tv({
|
|
9
|
+
slots: {
|
|
10
|
+
root: "flex flex-col gap-1.5",
|
|
11
|
+
label: "text-xs font-semibold text-fg-secondary",
|
|
12
|
+
control: "flex h-11 w-full rounded-lg border border-border-default bg-surface-2 px-3 text-sm text-fg placeholder:text-fg-muted transition-[border-color,box-shadow] focus-visible:border-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-danger aria-invalid:ring-danger/30",
|
|
13
|
+
hint: "text-xs text-fg-secondary",
|
|
14
|
+
// The danger token is too light for small text on a light surface: the message is a text role, the dot says danger.
|
|
15
|
+
error: "flex items-center gap-1.5 text-xs font-medium text-fg before:h-1.5 before:w-1.5 before:shrink-0 before:rounded-full before:bg-danger",
|
|
16
|
+
selectWrap: "relative flex w-full",
|
|
17
|
+
chevron: "pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-fg-secondary"
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
var s = field();
|
|
21
|
+
var Field = {
|
|
22
|
+
Root: ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: s.root({ className }), ...props }),
|
|
23
|
+
Label: ({ className, ...props }) => /* @__PURE__ */ jsx("label", { className: s.label({ className }), ...props }),
|
|
24
|
+
Hint: ({ className, ...props }) => /* @__PURE__ */ jsx("p", { className: s.hint({ className }), ...props }),
|
|
25
|
+
Error: ({ className, ...props }) => /* @__PURE__ */ jsx("p", { role: "alert", className: s.error({ className }), ...props })
|
|
26
|
+
};
|
|
27
|
+
var invalidProps = (invalid) => invalid ? { "aria-invalid": true, "data-invalid": "" } : {};
|
|
28
|
+
function Input({ invalid, className, ...props }) {
|
|
29
|
+
return /* @__PURE__ */ jsx("input", { ...invalidProps(invalid), className: s.control({ className }), ...props });
|
|
30
|
+
}
|
|
31
|
+
function Textarea({ invalid, className, ...props }) {
|
|
32
|
+
return /* @__PURE__ */ jsx("textarea", { ...invalidProps(invalid), className: s.control({ className: cn("h-auto min-h-24 py-2", className) }), ...props });
|
|
33
|
+
}
|
|
34
|
+
function Select({ invalid, className, ...props }) {
|
|
35
|
+
return /* @__PURE__ */ jsxs("span", { className: s.selectWrap(), children: [
|
|
36
|
+
/* @__PURE__ */ jsx("select", { ...invalidProps(invalid), className: s.control({ className: cn("appearance-none pr-9", className) }), ...props }),
|
|
37
|
+
/* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, className: s.chevron(), children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }) })
|
|
38
|
+
] });
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
Field,
|
|
42
|
+
Input,
|
|
43
|
+
Select,
|
|
44
|
+
Textarea,
|
|
45
|
+
field
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=field.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/field/field.tsx"],"sourcesContent":["// Server-safe. The label ↔ control wiring is HTML (htmlFor / id, aria-describedby): no context.\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\n\nexport const field = tv({\n slots: {\n root: \"flex flex-col gap-1.5\",\n label: \"text-xs font-semibold text-fg-secondary\",\n control:\n \"flex h-11 w-full rounded-lg border border-border-default bg-surface-2 px-3 text-sm text-fg placeholder:text-fg-muted \" +\n \"transition-[border-color,box-shadow] focus-visible:border-accent focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring \" +\n \"disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-danger aria-invalid:ring-danger/30\",\n hint: \"text-xs text-fg-secondary\",\n // The danger token is too light for small text on a light surface: the message is a text role, the dot says danger.\n error: \"flex items-center gap-1.5 text-xs font-medium text-fg before:h-1.5 before:w-1.5 before:shrink-0 before:rounded-full before:bg-danger\",\n selectWrap: \"relative flex w-full\",\n chevron: \"pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-fg-secondary\",\n },\n});\nconst s = field();\n\nexport const Field = {\n Root: ({ className, ...props }: React.ComponentProps<\"div\">) => <div className={s.root({ className })} {...props} />,\n Label: ({ className, ...props }: React.ComponentProps<\"label\">) => <label className={s.label({ className })} {...props} />,\n Hint: ({ className, ...props }: React.ComponentProps<\"p\">) => <p className={s.hint({ className })} {...props} />,\n Error: ({ className, ...props }: React.ComponentProps<\"p\">) => <p role=\"alert\" className={s.error({ className })} {...props} />,\n};\n\ntype ControlProps = {\n /** Marks the control invalid: aria-invalid and data-invalid (pair it with a `Field.Error` in aria-describedby). */\n invalid?: boolean;\n};\n\nconst invalidProps = (invalid?: boolean) => (invalid ? { \"aria-invalid\": true as const, \"data-invalid\": \"\" } : {});\n\nexport function Input({ invalid, className, ...props }: React.ComponentProps<\"input\"> & ControlProps) {\n return <input {...invalidProps(invalid)} className={s.control({ className })} {...props} />;\n}\n\nexport function Textarea({ invalid, className, ...props }: React.ComponentProps<\"textarea\"> & ControlProps) {\n return <textarea {...invalidProps(invalid)} className={s.control({ className: cn(\"h-auto min-h-24 py-2\", className) })} {...props} />;\n}\n\n/** A native <select>, styled like the other controls (the platform's menu: accessible and right on phones). */\nexport function Select({ invalid, className, ...props }: React.ComponentProps<\"select\"> & ControlProps) {\n return (\n <span className={s.selectWrap()}>\n <select {...invalidProps(invalid)} className={s.control({ className: cn(\"appearance-none pr-9\", className) })} {...props} />\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden className={s.chevron()}>\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </span>\n );\n}\n"],"mappings":";;;;;AAEA,SAAS,UAAU;AAsB+C,cAwB9D,YAxB8D;AAlB3D,IAAM,QAAQ,GAAG;AAAA,EACtB,OAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SACE;AAAA,IAGF,MAAM;AAAA;AAAA,IAEN,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,SAAS;AAAA,EACX;AACF,CAAC;AACD,IAAM,IAAI,MAAM;AAET,IAAM,QAAQ;AAAA,EACnB,MAAM,CAAC,EAAE,WAAW,GAAG,MAAM,MAAmC,oBAAC,SAAI,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AAAA,EAClH,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,MAAqC,oBAAC,WAAM,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AAAA,EACxH,MAAM,CAAC,EAAE,WAAW,GAAG,MAAM,MAAiC,oBAAC,OAAE,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AAAA,EAC9G,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,MAAiC,oBAAC,OAAE,MAAK,SAAQ,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AAC/H;AAOA,IAAM,eAAe,CAAC,YAAuB,UAAU,EAAE,gBAAgB,MAAe,gBAAgB,GAAG,IAAI,CAAC;AAEzG,SAAS,MAAM,EAAE,SAAS,WAAW,GAAG,MAAM,GAAiD;AACpG,SAAO,oBAAC,WAAO,GAAG,aAAa,OAAO,GAAG,WAAW,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AAC3F;AAEO,SAAS,SAAS,EAAE,SAAS,WAAW,GAAG,MAAM,GAAoD;AAC1G,SAAO,oBAAC,cAAU,GAAG,aAAa,OAAO,GAAG,WAAW,EAAE,QAAQ,EAAE,WAAW,GAAG,wBAAwB,SAAS,EAAE,CAAC,GAAI,GAAG,OAAO;AACrI;AAGO,SAAS,OAAO,EAAE,SAAS,WAAW,GAAG,MAAM,GAAkD;AACtG,SACE,qBAAC,UAAK,WAAW,EAAE,WAAW,GAC5B;AAAA,wBAAC,YAAQ,GAAG,aAAa,OAAO,GAAG,WAAW,EAAE,QAAQ,EAAE,WAAW,GAAG,wBAAwB,SAAS,EAAE,CAAC,GAAI,GAAG,OAAO;AAAA,IAC1H,oBAAC,SAAI,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ,gBAAe,SAAQ,eAAW,MAAC,WAAW,EAAE,QAAQ,GACvJ,8BAAC,UAAK,GAAE,gBAAe,GACzB;AAAA,KACF;AAEJ;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
|
|
3
3
|
/** Joins class names, skipping the falsy ones. */
|
|
4
4
|
declare function cx(...parts: Array<string | false | null | undefined>): string;
|
|
@@ -14,22 +14,22 @@ interface MarkProps {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/** The Krizaka mark: a hexagonal shield with a neural core, inside slow orbits. Blue accent: `--kz-accent`. */
|
|
17
|
-
declare function KrizakaLogo({ size, animated, title, className }: MarkProps):
|
|
17
|
+
declare function KrizakaLogo({ size, animated, title, className }: MarkProps): React.JSX.Element;
|
|
18
18
|
|
|
19
19
|
/** The Orazaka mark: three shards orbiting slowly around an amber core that breathes. */
|
|
20
|
-
declare function OrazakaLogo({ size, animated, title, className }: MarkProps):
|
|
20
|
+
declare function OrazakaLogo({ size, animated, title, className }: MarkProps): React.JSX.Element;
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* The Orochia mark: the serpent (Orochi) coiled into an "O" around the flame it guards. The orbit turns, scales slide
|
|
24
24
|
* along the body, the eye and the flame breathe. Below 48 px it crops to the serpent: the orbits would be hairlines.
|
|
25
25
|
*/
|
|
26
|
-
declare function OrochiaLogo({ size, animated, title, className }: MarkProps):
|
|
26
|
+
declare function OrochiaLogo({ size, animated, title, className }: MarkProps): React.JSX.Element;
|
|
27
27
|
|
|
28
28
|
type BrandId = "krizaka" | "orazaka" | "orochia";
|
|
29
29
|
/** The mark of a Krizaka brand by id — for navigation, cards and lists driven by data. */
|
|
30
30
|
declare function ProductLogo({ id, ...props }: MarkProps & {
|
|
31
31
|
id: BrandId;
|
|
32
|
-
}):
|
|
32
|
+
}): React.JSX.Element;
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* Mount once at the root of the app. It reveals every `[data-reveal]` element as it enters the viewport — including
|
|
@@ -48,6 +48,6 @@ declare function RotatingWord({ words, interval, className }: {
|
|
|
48
48
|
words: readonly string[];
|
|
49
49
|
interval?: number;
|
|
50
50
|
className?: string;
|
|
51
|
-
}):
|
|
51
|
+
}): React.JSX.Element;
|
|
52
52
|
|
|
53
53
|
export { type BrandId, KrizakaLogo, type MarkProps, MotionObserver, OrazakaLogo, OrochiaLogo, ProductLogo, RotatingWord, cx };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as tailwind_variants from 'tailwind-variants';
|
|
2
|
+
import { VariantProps } from 'tailwind-variants';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
declare const skeletonVariants: tailwind_variants.TVReturnType<{
|
|
6
|
+
shape: {
|
|
7
|
+
text: "h-3 w-full rounded-sm";
|
|
8
|
+
circle: "aspect-square h-10 rounded-full";
|
|
9
|
+
rect: "h-24 w-full rounded-lg";
|
|
10
|
+
};
|
|
11
|
+
}, undefined, "block bg-surface-3 motion-safe:animate-pulse", {
|
|
12
|
+
shape: {
|
|
13
|
+
text: "h-3 w-full rounded-sm";
|
|
14
|
+
circle: "aspect-square h-10 rounded-full";
|
|
15
|
+
rect: "h-24 w-full rounded-lg";
|
|
16
|
+
};
|
|
17
|
+
}, undefined, tailwind_variants.TVReturnTypeLike<{
|
|
18
|
+
shape: {
|
|
19
|
+
text: "h-3 w-full rounded-sm";
|
|
20
|
+
circle: "aspect-square h-10 rounded-full";
|
|
21
|
+
rect: "h-24 w-full rounded-lg";
|
|
22
|
+
};
|
|
23
|
+
}, undefined>>;
|
|
24
|
+
type SkeletonProps = React.ComponentProps<"span"> & VariantProps<typeof skeletonVariants>;
|
|
25
|
+
/** A pulsing shape the size of what is loading. Announce the wait elsewhere (aria-busy on the region, a Spinner). */
|
|
26
|
+
declare function Skeleton({ shape, className, ...props }: SkeletonProps): React.JSX.Element;
|
|
27
|
+
|
|
28
|
+
export { Skeleton, type SkeletonProps, skeletonVariants };
|
package/dist/skeleton.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// src/skeleton/skeleton.tsx
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
var skeletonVariants = tv({
|
|
5
|
+
base: "block bg-surface-3 motion-safe:animate-pulse",
|
|
6
|
+
variants: {
|
|
7
|
+
shape: { text: "h-3 w-full rounded-sm", circle: "aspect-square h-10 rounded-full", rect: "h-24 w-full rounded-lg" }
|
|
8
|
+
},
|
|
9
|
+
defaultVariants: { shape: "text" }
|
|
10
|
+
});
|
|
11
|
+
function Skeleton({ shape, className, ...props }) {
|
|
12
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, "data-shape": shape ?? "text", className: skeletonVariants({ shape, className }), ...props });
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
Skeleton,
|
|
16
|
+
skeletonVariants
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=skeleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/skeleton/skeleton.tsx"],"sourcesContent":["// Server-safe. A placeholder for content on its way: decorative, so hidden from assistive technology.\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const skeletonVariants = tv({\n base: \"block bg-surface-3 motion-safe:animate-pulse\",\n variants: {\n shape: { text: \"h-3 w-full rounded-sm\", circle: \"aspect-square h-10 rounded-full\", rect: \"h-24 w-full rounded-lg\" },\n },\n defaultVariants: { shape: \"text\" },\n});\n\nexport type SkeletonProps = React.ComponentProps<\"span\"> & VariantProps<typeof skeletonVariants>;\n\n/** A pulsing shape the size of what is loading. Announce the wait elsewhere (aria-busy on the region, a Spinner). */\nexport function Skeleton({ shape, className, ...props }: SkeletonProps) {\n return <span aria-hidden data-shape={shape ?? \"text\"} className={skeletonVariants({ shape, className })} {...props} />;\n}\n"],"mappings":";AAEA,SAAS,UAA6B;AAc7B;AAZF,IAAM,mBAAmB,GAAG;AAAA,EACjC,MAAM;AAAA,EACN,UAAU;AAAA,IACR,OAAO,EAAE,MAAM,yBAAyB,QAAQ,mCAAmC,MAAM,yBAAyB;AAAA,EACpH;AAAA,EACA,iBAAiB,EAAE,OAAO,OAAO;AACnC,CAAC;AAKM,SAAS,SAAS,EAAE,OAAO,WAAW,GAAG,MAAM,GAAkB;AACtE,SAAO,oBAAC,UAAK,eAAW,MAAC,cAAY,SAAS,QAAQ,WAAW,iBAAiB,EAAE,OAAO,UAAU,CAAC,GAAI,GAAG,OAAO;AACtH;","names":[]}
|
package/dist/slot.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React$1 from 'react';
|
|
2
|
+
import { VisuallyHidden as VisuallyHidden$1 } from 'radix-ui';
|
|
3
|
+
|
|
4
|
+
/** Merges its props, `className` and `ref` into its only child: the engine of every `asChild`. */
|
|
5
|
+
declare const Slot: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLElement> & {
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
} & React$1.RefAttributes<HTMLElement>>;
|
|
8
|
+
/** Hidden on screen, read by assistive technology. */
|
|
9
|
+
declare const VisuallyHidden: React$1.ForwardRefExoticComponent<VisuallyHidden$1.VisuallyHiddenProps & React$1.RefAttributes<HTMLSpanElement>>;
|
|
10
|
+
|
|
11
|
+
export { Slot, VisuallyHidden };
|
package/dist/slot.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// src/slot/index.ts
|
|
2
|
+
import { Slot as SlotPrimitive, VisuallyHidden as VisuallyHiddenPrimitive } from "radix-ui";
|
|
3
|
+
var Slot = SlotPrimitive.Root;
|
|
4
|
+
var VisuallyHidden = VisuallyHiddenPrimitive.Root;
|
|
5
|
+
export {
|
|
6
|
+
Slot,
|
|
7
|
+
VisuallyHidden
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=slot.js.map
|
package/dist/slot.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/slot/index.ts"],"sourcesContent":["/** @krizaka/ui/slot — `Slot` (what `asChild` renders) and `VisuallyHidden` (a name for assistive technology only), from Radix. */\nimport { Slot as SlotPrimitive, VisuallyHidden as VisuallyHiddenPrimitive } from \"radix-ui\";\n\n/** Merges its props, `className` and `ref` into its only child: the engine of every `asChild`. */\nexport const Slot = SlotPrimitive.Root;\n/** Hidden on screen, read by assistive technology. */\nexport const VisuallyHidden = VisuallyHiddenPrimitive.Root;\n"],"mappings":";AACA,SAAS,QAAQ,eAAe,kBAAkB,+BAA+B;AAG1E,IAAM,OAAO,cAAc;AAE3B,IAAM,iBAAiB,wBAAwB;","names":[]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as tailwind_variants from 'tailwind-variants';
|
|
2
|
+
import { VariantProps } from 'tailwind-variants';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
declare const spinnerVariants: tailwind_variants.TVReturnType<{
|
|
6
|
+
size: {
|
|
7
|
+
sm: "h-4 w-4";
|
|
8
|
+
md: "h-6 w-6";
|
|
9
|
+
lg: "h-10 w-10";
|
|
10
|
+
};
|
|
11
|
+
}, undefined, "shrink-0 text-accent motion-safe:animate-spin", {
|
|
12
|
+
size: {
|
|
13
|
+
sm: "h-4 w-4";
|
|
14
|
+
md: "h-6 w-6";
|
|
15
|
+
lg: "h-10 w-10";
|
|
16
|
+
};
|
|
17
|
+
}, undefined, tailwind_variants.TVReturnTypeLike<{
|
|
18
|
+
size: {
|
|
19
|
+
sm: "h-4 w-4";
|
|
20
|
+
md: "h-6 w-6";
|
|
21
|
+
lg: "h-10 w-10";
|
|
22
|
+
};
|
|
23
|
+
}, undefined>>;
|
|
24
|
+
type SpinnerProps = Omit<React.ComponentProps<"svg">, "children"> & VariantProps<typeof spinnerVariants> & {
|
|
25
|
+
/** The accessible name of the wait, e.g. "Loading" — passed translated. */
|
|
26
|
+
label: string;
|
|
27
|
+
};
|
|
28
|
+
/** A turning ring with `role="status"` (it stops turning under prefers-reduced-motion). */
|
|
29
|
+
declare function Spinner({ label, size, className, ...props }: SpinnerProps): React.JSX.Element;
|
|
30
|
+
|
|
31
|
+
export { Spinner, type SpinnerProps, spinnerVariants };
|
package/dist/spinner.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/spinner/spinner.tsx
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
var spinnerVariants = tv({
|
|
5
|
+
base: "shrink-0 text-accent motion-safe:animate-spin",
|
|
6
|
+
variants: { size: { sm: "h-4 w-4", md: "h-6 w-6", lg: "h-10 w-10" } },
|
|
7
|
+
defaultVariants: { size: "md" }
|
|
8
|
+
});
|
|
9
|
+
function Spinner({ label, size, className, ...props }) {
|
|
10
|
+
return /* @__PURE__ */ jsxs(
|
|
11
|
+
"svg",
|
|
12
|
+
{
|
|
13
|
+
role: "status",
|
|
14
|
+
"aria-label": label,
|
|
15
|
+
viewBox: "0 0 24 24",
|
|
16
|
+
fill: "none",
|
|
17
|
+
"data-size": size ?? "md",
|
|
18
|
+
className: spinnerVariants({ size, className }),
|
|
19
|
+
...props,
|
|
20
|
+
children: [
|
|
21
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeOpacity: "0.2", strokeWidth: "3" }),
|
|
22
|
+
/* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 0 0-9-9", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round" })
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
Spinner,
|
|
29
|
+
spinnerVariants
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=spinner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/spinner/spinner.tsx"],"sourcesContent":["// Server-safe. An indeterminate wait: an SVG ring, announced as a status with its `label`.\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const spinnerVariants = tv({\n base: \"shrink-0 text-accent motion-safe:animate-spin\",\n variants: { size: { sm: \"h-4 w-4\", md: \"h-6 w-6\", lg: \"h-10 w-10\" } },\n defaultVariants: { size: \"md\" },\n});\n\nexport type SpinnerProps = Omit<React.ComponentProps<\"svg\">, \"children\"> &\n VariantProps<typeof spinnerVariants> & {\n /** The accessible name of the wait, e.g. \"Loading\" — passed translated. */\n label: string;\n };\n\n/** A turning ring with `role=\"status\"` (it stops turning under prefers-reduced-motion). */\nexport function Spinner({ label, size, className, ...props }: SpinnerProps) {\n return (\n <svg\n role=\"status\"\n aria-label={label}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n data-size={size ?? \"md\"}\n className={spinnerVariants({ size, className })}\n {...props}\n >\n <circle cx=\"12\" cy=\"12\" r=\"9\" stroke=\"currentColor\" strokeOpacity=\"0.2\" strokeWidth=\"3\" />\n <path d=\"M21 12a9 9 0 0 0-9-9\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" />\n </svg>\n );\n}\n"],"mappings":";AAEA,SAAS,UAA6B;AAiBlC,SASE,KATF;AAfG,IAAM,kBAAkB,GAAG;AAAA,EAChC,MAAM;AAAA,EACN,UAAU,EAAE,MAAM,EAAE,IAAI,WAAW,IAAI,WAAW,IAAI,YAAY,EAAE;AAAA,EACpE,iBAAiB,EAAE,MAAM,KAAK;AAChC,CAAC;AASM,SAAS,QAAQ,EAAE,OAAO,MAAM,WAAW,GAAG,MAAM,GAAiB;AAC1E,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,aAAW,QAAQ;AAAA,MACnB,WAAW,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAAA,MAC7C,GAAG;AAAA,MAEJ;AAAA,4BAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,KAAI,QAAO,gBAAe,eAAc,OAAM,aAAY,KAAI;AAAA,QACxF,oBAAC,UAAK,GAAE,wBAAuB,QAAO,gBAAe,aAAY,KAAI,eAAc,SAAQ;AAAA;AAAA;AAAA,EAC7F;AAEJ;","names":[]}
|
package/dist/theme.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as tailwind_variants from 'tailwind-variants';
|
|
3
|
+
import { VariantProps } from 'tailwind-variants';
|
|
4
|
+
|
|
5
|
+
declare const buttonVariants: tailwind_variants.TVReturnType<{
|
|
6
|
+
variant: {
|
|
7
|
+
primary: "bg-accent text-on-accent shadow-sm hover:bg-accent-hover";
|
|
8
|
+
secondary: "border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3";
|
|
9
|
+
outline: "border border-border-default bg-transparent text-fg hover:border-accent hover:text-accent";
|
|
10
|
+
ghost: "text-fg-secondary hover:bg-surface-2 hover:text-fg";
|
|
11
|
+
danger: "border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20";
|
|
12
|
+
};
|
|
13
|
+
size: {
|
|
14
|
+
sm: "h-8 px-3 text-xs";
|
|
15
|
+
md: "h-10 px-4 text-sm";
|
|
16
|
+
lg: "h-12 px-6 text-sm";
|
|
17
|
+
icon: "h-10 w-10";
|
|
18
|
+
};
|
|
19
|
+
shape: {
|
|
20
|
+
rounded: "rounded-lg";
|
|
21
|
+
pill: "rounded-full";
|
|
22
|
+
};
|
|
23
|
+
}, undefined, string, {
|
|
24
|
+
variant: {
|
|
25
|
+
primary: "bg-accent text-on-accent shadow-sm hover:bg-accent-hover";
|
|
26
|
+
secondary: "border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3";
|
|
27
|
+
outline: "border border-border-default bg-transparent text-fg hover:border-accent hover:text-accent";
|
|
28
|
+
ghost: "text-fg-secondary hover:bg-surface-2 hover:text-fg";
|
|
29
|
+
danger: "border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20";
|
|
30
|
+
};
|
|
31
|
+
size: {
|
|
32
|
+
sm: "h-8 px-3 text-xs";
|
|
33
|
+
md: "h-10 px-4 text-sm";
|
|
34
|
+
lg: "h-12 px-6 text-sm";
|
|
35
|
+
icon: "h-10 w-10";
|
|
36
|
+
};
|
|
37
|
+
shape: {
|
|
38
|
+
rounded: "rounded-lg";
|
|
39
|
+
pill: "rounded-full";
|
|
40
|
+
};
|
|
41
|
+
}, undefined, tailwind_variants.TVReturnTypeLike<{
|
|
42
|
+
variant: {
|
|
43
|
+
primary: "bg-accent text-on-accent shadow-sm hover:bg-accent-hover";
|
|
44
|
+
secondary: "border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3";
|
|
45
|
+
outline: "border border-border-default bg-transparent text-fg hover:border-accent hover:text-accent";
|
|
46
|
+
ghost: "text-fg-secondary hover:bg-surface-2 hover:text-fg";
|
|
47
|
+
danger: "border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20";
|
|
48
|
+
};
|
|
49
|
+
size: {
|
|
50
|
+
sm: "h-8 px-3 text-xs";
|
|
51
|
+
md: "h-10 px-4 text-sm";
|
|
52
|
+
lg: "h-12 px-6 text-sm";
|
|
53
|
+
icon: "h-10 w-10";
|
|
54
|
+
};
|
|
55
|
+
shape: {
|
|
56
|
+
rounded: "rounded-lg";
|
|
57
|
+
pill: "rounded-full";
|
|
58
|
+
};
|
|
59
|
+
}, undefined>>;
|
|
60
|
+
type ButtonVariants = VariantProps<typeof buttonVariants>;
|
|
61
|
+
|
|
62
|
+
type Mode = "dark" | "light" | "system";
|
|
63
|
+
/**
|
|
64
|
+
* In <head>, before anything renders: applies the persisted mode and named theme, so the page never flashes.
|
|
65
|
+
* `nonce` for a strict Content-Security-Policy.
|
|
66
|
+
*/
|
|
67
|
+
declare function ThemeScript({ nonce }: {
|
|
68
|
+
nonce?: string;
|
|
69
|
+
}): React.JSX.Element;
|
|
70
|
+
type ThemeContextValue = {
|
|
71
|
+
/** The chosen mode: dark, light or follow the system. */
|
|
72
|
+
mode: Mode;
|
|
73
|
+
setMode: (mode: Mode) => void;
|
|
74
|
+
/** The named theme (`html.theme-<name>`), or null. */
|
|
75
|
+
theme: string | null;
|
|
76
|
+
setTheme: (theme: string | null) => void;
|
|
77
|
+
};
|
|
78
|
+
type ThemeProviderProps = {
|
|
79
|
+
children: React.ReactNode;
|
|
80
|
+
/** The mode before anything is persisted. */
|
|
81
|
+
defaultMode?: Mode;
|
|
82
|
+
};
|
|
83
|
+
declare function ThemeProvider({ children, defaultMode }: ThemeProviderProps): React.JSX.Element;
|
|
84
|
+
declare function useTheme(): ThemeContextValue;
|
|
85
|
+
type ThemeToggleProps = Omit<React.ComponentProps<"button">, "onClick" | "children"> & Pick<ButtonVariants, "variant" | "shape"> & {
|
|
86
|
+
/** The accessible name — a string, or one per current mode (e.g. `(mode) => t("theme." + mode)`). */
|
|
87
|
+
label: string | ((mode: Mode) => string);
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* An icon button (styled as `IconButton`, without its Slot) that cycles dark → light → system. Needs a
|
|
91
|
+
* <ThemeProvider> above it. State: `data-mode`.
|
|
92
|
+
*/
|
|
93
|
+
declare function ThemeToggle({ label, variant, shape, className, ...props }: ThemeToggleProps): React.JSX.Element;
|
|
94
|
+
|
|
95
|
+
export { type Mode, type ThemeContextValue, ThemeProvider, type ThemeProviderProps, ThemeScript, ThemeToggle, type ThemeToggleProps, useTheme };
|