@cloudflare/kumo 2.3.0 → 2.4.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/CHANGELOG.md +80 -0
- package/ai/component-registry.json +166 -123
- package/ai/component-registry.md +349 -215
- package/ai/schemas.ts +7 -2
- package/dist/.build-complete +1 -1
- package/dist/ai/schemas.d.ts +46 -34
- package/dist/ai/schemas.d.ts.map +1 -1
- package/dist/ai/schemas.js +12 -4
- package/dist/ai/schemas.js.map +1 -1
- package/dist/chunks/SankeyChart-npoyr1j06svoxsfe.js +770 -0
- package/dist/chunks/SankeyChart-npoyr1j06svoxsfe.js.map +1 -0
- package/dist/chunks/{autocomplete-h39m8kzoq0csjh9l.js → autocomplete-cvp5fsdt6gh0p3vu.js} +32 -28
- package/dist/chunks/autocomplete-cvp5fsdt6gh0p3vu.js.map +1 -0
- package/dist/chunks/{badge-e9w8qrjmeu9nocf6.js → badge-c1th6h6ahz7eu49q.js} +2 -2
- package/dist/chunks/badge-c1th6h6ahz7eu49q.js.map +1 -0
- package/dist/chunks/banner-es5iwuk4pf25e29e.js +120 -0
- package/dist/chunks/banner-es5iwuk4pf25e29e.js.map +1 -0
- package/dist/chunks/{breadcrumbs-g4pyoikibpoxsgw4.js → breadcrumbs-j214mimk5zj4ffp4.js} +8 -6
- package/dist/chunks/breadcrumbs-j214mimk5zj4ffp4.js.map +1 -0
- package/dist/chunks/{button-fxdpoacmq5rv1adk.js → button-mnrxu6dud2x5js5b.js} +19 -17
- package/dist/chunks/{button-fxdpoacmq5rv1adk.js.map → button-mnrxu6dud2x5js5b.js.map} +1 -1
- package/dist/chunks/{checkbox-dtoq56ieijj9m6vr.js → checkbox-dqih8tzzt3vhp870.js} +25 -19
- package/dist/chunks/checkbox-dqih8tzzt3vhp870.js.map +1 -0
- package/dist/chunks/{clipboard-text-nvdsloomefwgcxat.js → clipboard-text-mrut8z3dt1w0efxz.js} +4 -4
- package/dist/chunks/{clipboard-text-nvdsloomefwgcxat.js.map → clipboard-text-mrut8z3dt1w0efxz.js.map} +1 -1
- package/dist/chunks/{collapsible-cnsxmp7dko87pgx0.js → collapsible-nzqcf9zwnjkxqzr6.js} +21 -17
- package/dist/chunks/collapsible-nzqcf9zwnjkxqzr6.js.map +1 -0
- package/dist/chunks/{combobox-jcqn64ixr4557a0s.js → combobox-dpptfpcmqfrso1xa.js} +115 -103
- package/dist/chunks/combobox-dpptfpcmqfrso1xa.js.map +1 -0
- package/dist/chunks/{command-palette-jrq7p16tff6n46nj.js → command-palette-fqhyacp33fhyf696.js} +5 -5
- package/dist/chunks/{command-palette-jrq7p16tff6n46nj.js.map → command-palette-fqhyacp33fhyf696.js.map} +1 -1
- package/dist/chunks/{dialog-gndju3sqg1lmpb3f.js → dialog-my9fioafdstq50mi.js} +49 -33
- package/dist/chunks/{dialog-gndju3sqg1lmpb3f.js.map → dialog-my9fioafdstq50mi.js.map} +1 -1
- package/dist/chunks/{dropdown-k6orz4j043xybf54.js → dropdown-g4sb4cw9ffqaw5gx.js} +54 -44
- package/dist/chunks/dropdown-g4sb4cw9ffqaw5gx.js.map +1 -0
- package/dist/chunks/{empty-ni12ufom1kkakbuc.js → empty-n17inn1z67bpohkw.js} +2 -2
- package/dist/chunks/{empty-ni12ufom1kkakbuc.js.map → empty-n17inn1z67bpohkw.js.map} +1 -1
- package/dist/chunks/{field-n16udu32tpyq5udz.js → field-c8o7h3rlam4c9pcx.js} +3 -3
- package/dist/chunks/{field-n16udu32tpyq5udz.js.map → field-c8o7h3rlam4c9pcx.js.map} +1 -1
- package/dist/chunks/{input-area-hhhpgg0ev8bowtrk.js → input-area-eurk3seud30ricwn.js} +4 -4
- package/dist/chunks/{input-area-hhhpgg0ev8bowtrk.js.map → input-area-eurk3seud30ricwn.js.map} +1 -1
- package/dist/chunks/{input-mv7giprcc6hfkpq3.js → input-en8hhb14mmt3tfwn.js} +3 -3
- package/dist/chunks/{input-mv7giprcc6hfkpq3.js.map → input-en8hhb14mmt3tfwn.js.map} +1 -1
- package/dist/chunks/{input-group-kkw5j7rwzhj66h10.js → input-group-d09ocmjcbdai0gze.js} +5 -5
- package/dist/chunks/{input-group-kkw5j7rwzhj66h10.js.map → input-group-d09ocmjcbdai0gze.js.map} +1 -1
- package/dist/chunks/{label-f6yvqca8qhbpvkq8.js → label-c8rz453pti66slki.js} +3 -3
- package/dist/chunks/{label-f6yvqca8qhbpvkq8.js.map → label-c8rz453pti66slki.js.map} +1 -1
- package/dist/chunks/{layer-card-gegkqhkjy65l1ueo.js → layer-card-er4flkcxmzfug8jw.js} +2 -2
- package/dist/chunks/{layer-card-gegkqhkjy65l1ueo.js.map → layer-card-er4flkcxmzfug8jw.js.map} +1 -1
- package/dist/chunks/{link-jjk7qolyol7s1jkk.js → link-i6vnwyjcwvjz5btm.js} +20 -19
- package/dist/chunks/{link-jjk7qolyol7s1jkk.js.map → link-i6vnwyjcwvjz5btm.js.map} +1 -1
- package/dist/chunks/menubar-ng5if56amh1tto4j.js +98 -0
- package/dist/chunks/menubar-ng5if56amh1tto4j.js.map +1 -0
- package/dist/chunks/{meter-kxn34sy6l2mz5dwq.js → meter-d5igshkjqttl1fdj.js} +2 -2
- package/dist/chunks/{meter-kxn34sy6l2mz5dwq.js.map → meter-d5igshkjqttl1fdj.js.map} +1 -1
- package/dist/chunks/{pagination-ixbq8ssuuo0jxaa4.js → pagination-bw7vwca4wrfjm8vb.js} +3 -3
- package/dist/chunks/{pagination-ixbq8ssuuo0jxaa4.js.map → pagination-bw7vwca4wrfjm8vb.js.map} +1 -1
- package/dist/chunks/{popover-js5ds3szd43kspja.js → popover-ozf1j7oi7pxiudyz.js} +4 -2
- package/dist/chunks/popover-ozf1j7oi7pxiudyz.js.map +1 -0
- package/dist/chunks/{radio-nyw89v4eafptepmz.js → radio-gpg6kmzonr2cayq1.js} +54 -46
- package/dist/chunks/radio-gpg6kmzonr2cayq1.js.map +1 -0
- package/dist/chunks/{select-o2i7aovnu8v1zv8t.js → select-dw9iw35ug7yer3o3.js} +101 -91
- package/dist/chunks/select-dw9iw35ug7yer3o3.js.map +1 -0
- package/dist/chunks/{sensitive-input-bjg6m791yz7g6bn3.js → sensitive-input-dgoxjtoxl4zqa51v.js} +50 -44
- package/dist/chunks/{sensitive-input-bjg6m791yz7g6bn3.js.map → sensitive-input-dgoxjtoxl4zqa51v.js.map} +1 -1
- package/dist/chunks/sidebar-hzio700cg85f7f31.js +1014 -0
- package/dist/chunks/sidebar-hzio700cg85f7f31.js.map +1 -0
- package/dist/chunks/{surface-lzwbh3f5t0gxc83t.js → surface-iyejjbqogjbo7ise.js} +2 -2
- package/dist/chunks/{surface-lzwbh3f5t0gxc83t.js.map → surface-iyejjbqogjbo7ise.js.map} +1 -1
- package/dist/chunks/{switch-d9cs31oj4rjtg717.js → switch-g8f77h69h34xld06.js} +50 -45
- package/dist/chunks/switch-g8f77h69h34xld06.js.map +1 -0
- package/dist/chunks/{table-c6qemc2jmv22cv3p.js → table-e1te1im2tt2ez05y.js} +2 -2
- package/dist/chunks/{table-c6qemc2jmv22cv3p.js.map → table-e1te1im2tt2ez05y.js.map} +1 -1
- package/dist/chunks/{table-of-contents-fzyv7uhnnyr13dqu.js → table-of-contents-jco9kvt48d34dwsw.js} +34 -30
- package/dist/chunks/table-of-contents-jco9kvt48d34dwsw.js.map +1 -0
- package/dist/chunks/{tabs-f0ztlooi91ko9g04.js → tabs-hice1yy5q2t889z8.js} +6 -4
- package/dist/chunks/tabs-hice1yy5q2t889z8.js.map +1 -0
- package/dist/chunks/{toast-ejfm5cbt9yulqhol.js → toast-kvbgct0jvfmn4mas.js} +29 -27
- package/dist/chunks/{toast-ejfm5cbt9yulqhol.js.map → toast-kvbgct0jvfmn4mas.js.map} +1 -1
- package/dist/chunks/{tooltip-o6xfw9jjclv9pxaj.js → tooltip-ken77ixya0qpidie.js} +6 -6
- package/dist/chunks/{tooltip-o6xfw9jjclv9pxaj.js.map → tooltip-ken77ixya0qpidie.js.map} +1 -1
- package/dist/chunks/{vendor-base-ui-mzjqwv5teijixz8h.js → vendor-base-ui-knphx7dts1vm1x37.js} +1726 -1719
- package/dist/chunks/{vendor-base-ui-mzjqwv5teijixz8h.js.map → vendor-base-ui-knphx7dts1vm1x37.js.map} +1 -1
- package/dist/code.js +1 -1
- package/dist/components/autocomplete.js +1 -1
- package/dist/components/badge.js +1 -1
- package/dist/components/banner.js +1 -1
- package/dist/components/breadcrumbs.js +1 -1
- package/dist/components/button.js +1 -1
- package/dist/components/chart.js +1 -1
- package/dist/components/checkbox.js +1 -1
- package/dist/components/clipboard-text.js +1 -1
- package/dist/components/collapsible.js +1 -1
- package/dist/components/combobox.js +1 -1
- package/dist/components/command-palette.js +1 -1
- package/dist/components/dialog.js +1 -1
- package/dist/components/dropdown.js +1 -1
- package/dist/components/empty.js +1 -1
- package/dist/components/field.js +1 -1
- package/dist/components/input-group.js +1 -1
- package/dist/components/input.js +3 -3
- package/dist/components/label.js +1 -1
- package/dist/components/layer-card.js +1 -1
- package/dist/components/link.js +1 -1
- package/dist/components/menubar.js +1 -1
- package/dist/components/meter.js +1 -1
- package/dist/components/pagination.js +1 -1
- package/dist/components/popover.js +1 -1
- package/dist/components/radio.js +1 -1
- package/dist/components/select.js +1 -1
- package/dist/components/sensitive-input.js +1 -1
- package/dist/components/sidebar.js +22 -23
- package/dist/components/surface.js +1 -1
- package/dist/components/switch.js +1 -1
- package/dist/components/table-of-contents.js +1 -1
- package/dist/components/table.js +1 -1
- package/dist/components/tabs.js +1 -1
- package/dist/components/toast.js +2 -2
- package/dist/components/tooltip.js +1 -1
- package/dist/index.js +122 -123
- package/dist/primitives/accordion.js +1 -1
- package/dist/primitives/alert-dialog.js +1 -1
- package/dist/primitives/autocomplete.js +1 -1
- package/dist/primitives/avatar.js +1 -1
- package/dist/primitives/button.js +1 -1
- package/dist/primitives/checkbox-group.js +1 -1
- package/dist/primitives/checkbox.js +1 -1
- package/dist/primitives/collapsible.js +1 -1
- package/dist/primitives/combobox.js +1 -1
- package/dist/primitives/context-menu.js +1 -1
- package/dist/primitives/csp-provider.js +1 -1
- package/dist/primitives/dialog.js +1 -1
- package/dist/primitives/direction-provider.js +1 -1
- package/dist/primitives/drawer.js +1 -1
- package/dist/primitives/field.js +1 -1
- package/dist/primitives/fieldset.js +1 -1
- package/dist/primitives/form.js +1 -1
- package/dist/primitives/input.js +1 -1
- package/dist/primitives/menu.js +1 -1
- package/dist/primitives/menubar.js +1 -1
- package/dist/primitives/meter.js +1 -1
- package/dist/primitives/navigation-menu.js +1 -1
- package/dist/primitives/number-field.js +1 -1
- package/dist/primitives/otp-field.js +1 -1
- package/dist/primitives/popover.js +1 -1
- package/dist/primitives/preview-card.js +1 -1
- package/dist/primitives/progress.js +1 -1
- package/dist/primitives/radio-group.js +1 -1
- package/dist/primitives/radio.js +1 -1
- package/dist/primitives/scroll-area.js +1 -1
- package/dist/primitives/select.js +1 -1
- package/dist/primitives/separator.js +1 -1
- package/dist/primitives/slider.js +1 -1
- package/dist/primitives/switch.js +1 -1
- package/dist/primitives/tabs.js +1 -1
- package/dist/primitives/toast.js +1 -1
- package/dist/primitives/toggle-group.js +1 -1
- package/dist/primitives/toggle.js +1 -1
- package/dist/primitives/toolbar.js +1 -1
- package/dist/primitives/tooltip.js +1 -1
- package/dist/primitives.js +1 -1
- package/dist/scripts/theme-generator/config.d.ts.map +1 -1
- package/dist/scripts/theme-generator/config.js +36 -38
- package/dist/scripts/theme-generator/config.js.map +1 -1
- package/dist/scripts/theme-generator/generate-css.d.ts.map +1 -1
- package/dist/scripts/theme-generator/types.d.ts +8 -2
- package/dist/scripts/theme-generator/types.d.ts.map +1 -1
- package/dist/src/components/autocomplete/autocomplete.d.ts +1 -0
- package/dist/src/components/autocomplete/autocomplete.d.ts.map +1 -1
- package/dist/src/components/autocomplete/index.d.ts +1 -0
- package/dist/src/components/autocomplete/index.d.ts.map +1 -1
- package/dist/src/components/badge/badge.d.ts +1 -1
- package/dist/src/components/banner/banner.d.ts +14 -7
- package/dist/src/components/banner/banner.d.ts.map +1 -1
- package/dist/src/components/breadcrumbs/breadcrumbs.d.ts.map +1 -1
- package/dist/src/components/button/button.d.ts.map +1 -1
- package/dist/src/components/chart/TimeseriesChart.d.ts +43 -1
- package/dist/src/components/chart/TimeseriesChart.d.ts.map +1 -1
- package/dist/src/components/checkbox/checkbox.d.ts.map +1 -1
- package/dist/src/components/collapsible/collapsible.d.ts.map +1 -1
- package/dist/src/components/combobox/combobox.d.ts +1 -0
- package/dist/src/components/combobox/combobox.d.ts.map +1 -1
- package/dist/src/components/combobox/index.d.ts +1 -0
- package/dist/src/components/combobox/index.d.ts.map +1 -1
- package/dist/src/components/dialog/dialog.d.ts.map +1 -1
- package/dist/src/components/dropdown/dropdown.d.ts.map +1 -1
- package/dist/src/components/link/link.d.ts.map +1 -1
- package/dist/src/components/menubar/menubar.d.ts.map +1 -1
- package/dist/src/components/popover/popover.d.ts.map +1 -1
- package/dist/src/components/radio/radio.d.ts.map +1 -1
- package/dist/src/components/select/select.d.ts.map +1 -1
- package/dist/src/components/sensitive-input/sensitive-input.d.ts.map +1 -1
- package/dist/src/components/sidebar/index.d.ts +1 -1
- package/dist/src/components/sidebar/index.d.ts.map +1 -1
- package/dist/src/components/sidebar/sidebar.d.ts +159 -146
- package/dist/src/components/sidebar/sidebar.d.ts.map +1 -1
- package/dist/src/components/switch/switch.d.ts.map +1 -1
- package/dist/src/components/table-of-contents/table-of-contents.d.ts.map +1 -1
- package/dist/src/components/tabs/tabs.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/styles/kumo-standalone.css +1 -1
- package/dist/styles/kumo.css +37 -0
- package/dist/styles/theme-kumo.css +28 -35
- package/package.json +4 -1
- package/scripts/theme-generator/config.ts +37 -39
- package/scripts/theme-generator/generate-css.ts +4 -1
- package/scripts/theme-generator/types.ts +8 -2
- package/dist/chunks/SankeyChart-krkvltewpn3bbupw.js +0 -651
- package/dist/chunks/SankeyChart-krkvltewpn3bbupw.js.map +0 -1
- package/dist/chunks/autocomplete-h39m8kzoq0csjh9l.js.map +0 -1
- package/dist/chunks/badge-e9w8qrjmeu9nocf6.js.map +0 -1
- package/dist/chunks/banner-ip2lm8r87hich557.js +0 -88
- package/dist/chunks/banner-ip2lm8r87hich557.js.map +0 -1
- package/dist/chunks/breadcrumbs-g4pyoikibpoxsgw4.js.map +0 -1
- package/dist/chunks/checkbox-dtoq56ieijj9m6vr.js.map +0 -1
- package/dist/chunks/collapsible-cnsxmp7dko87pgx0.js.map +0 -1
- package/dist/chunks/combobox-jcqn64ixr4557a0s.js.map +0 -1
- package/dist/chunks/dropdown-k6orz4j043xybf54.js.map +0 -1
- package/dist/chunks/menubar-d5s6h96nw8ggy04a.js +0 -96
- package/dist/chunks/menubar-d5s6h96nw8ggy04a.js.map +0 -1
- package/dist/chunks/popover-js5ds3szd43kspja.js.map +0 -1
- package/dist/chunks/radio-nyw89v4eafptepmz.js.map +0 -1
- package/dist/chunks/select-o2i7aovnu8v1zv8t.js.map +0 -1
- package/dist/chunks/sidebar-izcfqkrzt4vqn8ez.js +0 -875
- package/dist/chunks/sidebar-izcfqkrzt4vqn8ez.js.map +0 -1
- package/dist/chunks/switch-d9cs31oj4rjtg717.js.map +0 -1
- package/dist/chunks/table-of-contents-fzyv7uhnnyr13dqu.js.map +0 -1
- package/dist/chunks/tabs-f0ztlooi91ko9g04.js.map +0 -1
package/dist/chunks/{sensitive-input-bjg6m791yz7g6bn3.js → sensitive-input-dgoxjtoxl4zqa51v.js}
RENAMED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsxs as b, Fragment as ce, jsx as
|
|
2
|
+
import { jsxs as b, Fragment as ce, jsx as r } from "react/jsx-runtime";
|
|
3
3
|
import { EyeSlash as ue, Eye as pe } from "@phosphor-icons/react";
|
|
4
|
-
import { forwardRef as de, useState as C, useRef as N, useId as
|
|
4
|
+
import { forwardRef as de, useState as C, useRef as N, useId as S, useCallback as c, useEffect as me } from "react";
|
|
5
5
|
import { c as p } from "./cn-ct4n7r74mh8y0f48.js";
|
|
6
|
-
import { K as fe, i as
|
|
7
|
-
import { F as
|
|
8
|
-
import { I as ge } from "./vendor-base-ui-
|
|
9
|
-
const
|
|
6
|
+
import { K as fe, i as ve } from "./input-en8hhb14mmt3tfwn.js";
|
|
7
|
+
import { F as he } from "./field-c8o7h3rlam4c9pcx.js";
|
|
8
|
+
import { I as ge } from "./vendor-base-ui-knphx7dts1vm1x37.js";
|
|
9
|
+
const Te = fe, ye = {
|
|
10
10
|
size: "base",
|
|
11
11
|
variant: "default"
|
|
12
12
|
}, be = de(
|
|
13
13
|
({
|
|
14
|
-
value:
|
|
14
|
+
value: T,
|
|
15
15
|
defaultValue: B = "",
|
|
16
16
|
onChange: E,
|
|
17
17
|
onValueChange: R,
|
|
@@ -33,53 +33,53 @@ const Se = fe, ye = {
|
|
|
33
33
|
process.env.NODE_ENV !== "production" && V === "error" && console.warn(
|
|
34
34
|
'[Kumo SensitiveInput]: variant="error" is deprecated. Error styling is now automatically applied when the `error` prop is truthy. Simply remove the variant prop and pass an error message instead.'
|
|
35
35
|
);
|
|
36
|
-
const W = V ?? (m ? "error" : "default"), q = typeof y == "string" ? y : "Sensitive value", x =
|
|
36
|
+
const W = V ?? (m ? "error" : "default"), q = typeof y == "string" ? y : "Sensitive value", x = T !== void 0, [G, J] = C(B), v = x ? T : G, o = v.length > 0, [n, l] = C(
|
|
37
37
|
() => o ? "masked" : "empty"
|
|
38
|
-
), [
|
|
38
|
+
), [h, w] = C(!1), I = N(null), u = N(null), K = S(), Q = S(), Z = j ?? Q, A = S(), z = c(
|
|
39
39
|
(e) => {
|
|
40
40
|
I.current = e, typeof f == "function" ? f(e) : f && (f.current = e);
|
|
41
41
|
},
|
|
42
42
|
[f]
|
|
43
43
|
);
|
|
44
44
|
me(() => {
|
|
45
|
-
if (
|
|
45
|
+
if (h) {
|
|
46
46
|
const e = setTimeout(() => w(!1), 2e3);
|
|
47
47
|
return () => clearTimeout(e);
|
|
48
48
|
}
|
|
49
|
-
}, [
|
|
49
|
+
}, [h]);
|
|
50
50
|
const ee = c(
|
|
51
51
|
async (e) => {
|
|
52
52
|
e.stopPropagation();
|
|
53
53
|
try {
|
|
54
54
|
if (typeof navigator < "u" && navigator.clipboard && typeof navigator.clipboard.writeText == "function") {
|
|
55
|
-
await navigator.clipboard.writeText(
|
|
55
|
+
await navigator.clipboard.writeText(v), w(!0), k?.();
|
|
56
56
|
return;
|
|
57
57
|
}
|
|
58
58
|
} catch {
|
|
59
59
|
}
|
|
60
60
|
if (typeof document < "u") {
|
|
61
|
-
const
|
|
62
|
-
|
|
61
|
+
const a = document.createElement("textarea");
|
|
62
|
+
a.value = v, a.setAttribute("readonly", ""), a.style.position = "absolute", a.style.left = "-9999px", document.body.appendChild(a);
|
|
63
63
|
const g = document.getSelection(), M = g?.rangeCount ? g.getRangeAt(0) : null;
|
|
64
|
-
|
|
64
|
+
a.select();
|
|
65
65
|
try {
|
|
66
66
|
document.execCommand("copy"), w(!0), k?.();
|
|
67
67
|
} catch (le) {
|
|
68
68
|
console.warn("Clipboard copy failed", le);
|
|
69
69
|
} finally {
|
|
70
|
-
document.body.removeChild(
|
|
70
|
+
document.body.removeChild(a), M && (g?.removeAllRanges(), g?.addRange(M));
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
|
-
[
|
|
74
|
+
[v, k]
|
|
75
75
|
), _ = N(o);
|
|
76
76
|
_.current !== o && (_.current = o, !o && n === "masked" && l("empty"));
|
|
77
77
|
const te = c(
|
|
78
78
|
(e) => {
|
|
79
79
|
if (!i) {
|
|
80
80
|
if (u.current) {
|
|
81
|
-
const
|
|
82
|
-
if (!(e.clientX >=
|
|
81
|
+
const a = u.current.getBoundingClientRect();
|
|
82
|
+
if (!(e.clientX >= a.left && e.clientX <= a.right && e.clientY >= a.top && e.clientY <= a.bottom)) return;
|
|
83
83
|
}
|
|
84
84
|
n === "masked" && o && (l("revealed"), d || setTimeout(() => I.current?.focus(), 0));
|
|
85
85
|
}
|
|
@@ -92,11 +92,11 @@ const Se = fe, ye = {
|
|
|
92
92
|
[n, o]
|
|
93
93
|
), oe = c(
|
|
94
94
|
(e) => {
|
|
95
|
-
const
|
|
96
|
-
x || J(
|
|
95
|
+
const a = e.target.value;
|
|
96
|
+
x || J(a), n === "empty" && a.length > 0 && l("revealed"), E?.(e), R?.(a);
|
|
97
97
|
},
|
|
98
98
|
[x, E, R, n]
|
|
99
|
-
),
|
|
99
|
+
), ae = c(
|
|
100
100
|
(e) => {
|
|
101
101
|
u.current && e.relatedTarget instanceof Node && u.current.contains(e.relatedTarget) || o && l("masked");
|
|
102
102
|
},
|
|
@@ -106,13 +106,13 @@ const Se = fe, ye = {
|
|
|
106
106
|
i || n === "masked" && o && (e.key === "Enter" || e.key === " ") && (e.preventDefault(), l("revealed"), d || setTimeout(() => I.current?.focus(), 0));
|
|
107
107
|
},
|
|
108
108
|
[n, o, i, d]
|
|
109
|
-
),
|
|
109
|
+
), re = c(
|
|
110
110
|
(e) => {
|
|
111
111
|
n === "revealed" && e.key === "Escape" && (l("masked"), setTimeout(() => u.current?.focus(), 0));
|
|
112
112
|
},
|
|
113
113
|
[n]
|
|
114
114
|
), s = n === "masked" && o, D = !i && (n === "revealed" || n === "empty" && o), se = t === "xs" || t === "sm" ? "size-3" : "size-4", U = p(
|
|
115
|
-
|
|
115
|
+
ve({ size: t, variant: W, parentFocusIndicator: !0 }),
|
|
116
116
|
"group/container relative flex w-full items-center",
|
|
117
117
|
// Show browser-native focus outline on container when child input is focused
|
|
118
118
|
"focus-within:outline focus-within:outline-2 focus-within:outline-kumo-focus",
|
|
@@ -120,16 +120,16 @@ const Se = fe, ye = {
|
|
|
120
120
|
i && "cursor-not-allowed",
|
|
121
121
|
H
|
|
122
122
|
), F = /* @__PURE__ */ b(ce, { children: [
|
|
123
|
-
/* @__PURE__ */
|
|
123
|
+
/* @__PURE__ */ r(
|
|
124
124
|
ge,
|
|
125
125
|
{
|
|
126
126
|
ref: z,
|
|
127
127
|
id: Z,
|
|
128
128
|
type: n === "revealed" ? "text" : "password",
|
|
129
|
-
value:
|
|
129
|
+
value: v,
|
|
130
130
|
onChange: oe,
|
|
131
|
-
onBlur:
|
|
132
|
-
onKeyDown:
|
|
131
|
+
onBlur: ae,
|
|
132
|
+
onKeyDown: re,
|
|
133
133
|
disabled: i,
|
|
134
134
|
readOnly: d || s,
|
|
135
135
|
autoComplete: $,
|
|
@@ -146,7 +146,7 @@ const Se = fe, ye = {
|
|
|
146
146
|
...O
|
|
147
147
|
}
|
|
148
148
|
),
|
|
149
|
-
/* @__PURE__ */
|
|
149
|
+
/* @__PURE__ */ r(
|
|
150
150
|
"span",
|
|
151
151
|
{
|
|
152
152
|
className: p(
|
|
@@ -172,7 +172,7 @@ const Se = fe, ye = {
|
|
|
172
172
|
),
|
|
173
173
|
"aria-hidden": "true",
|
|
174
174
|
children: /* @__PURE__ */ b("span", { className: "relative", children: [
|
|
175
|
-
/* @__PURE__ */
|
|
175
|
+
/* @__PURE__ */ r(
|
|
176
176
|
"span",
|
|
177
177
|
{
|
|
178
178
|
className: p(
|
|
@@ -181,14 +181,16 @@ const Se = fe, ye = {
|
|
|
181
181
|
children: "••••••••"
|
|
182
182
|
}
|
|
183
183
|
),
|
|
184
|
-
s && !i && /* @__PURE__ */
|
|
184
|
+
s && !i && /* @__PURE__ */ r("span", { className: "invisible absolute left-0 top-0 whitespace-nowrap text-kumo-subtle group-focus-within/container:visible group-hover/mask:visible", children: "Click to reveal" })
|
|
185
185
|
] })
|
|
186
186
|
}
|
|
187
187
|
),
|
|
188
|
-
/* @__PURE__ */
|
|
188
|
+
/* @__PURE__ */ r(
|
|
189
189
|
"button",
|
|
190
190
|
{
|
|
191
191
|
type: "button",
|
|
192
|
+
"data-kumo-component": "SensitiveInput",
|
|
193
|
+
"data-kumo-part": "toggle-visibility",
|
|
192
194
|
onClick: ne,
|
|
193
195
|
onKeyDown: (e) => e.stopPropagation(),
|
|
194
196
|
"aria-label": n === "revealed" ? "Hide value" : "Reveal value",
|
|
@@ -205,30 +207,34 @@ const Se = fe, ye = {
|
|
|
205
207
|
se,
|
|
206
208
|
!D && "pointer-events-none opacity-0"
|
|
207
209
|
),
|
|
208
|
-
children: n === "revealed" ? /* @__PURE__ */
|
|
210
|
+
children: n === "revealed" ? /* @__PURE__ */ r(ue, { className: "size-full" }) : /* @__PURE__ */ r(pe, { className: "size-full" })
|
|
209
211
|
}
|
|
210
212
|
),
|
|
211
|
-
o && !i && /* @__PURE__ */
|
|
213
|
+
o && !i && /* @__PURE__ */ r(
|
|
212
214
|
"button",
|
|
213
215
|
{
|
|
214
216
|
type: "button",
|
|
217
|
+
"data-kumo-component": "SensitiveInput",
|
|
218
|
+
"data-kumo-part": "copy",
|
|
215
219
|
onClick: ee,
|
|
216
220
|
onKeyDown: (e) => e.stopPropagation(),
|
|
217
|
-
"aria-label":
|
|
221
|
+
"aria-label": h ? "Copied" : "Copy to clipboard",
|
|
218
222
|
className: p(
|
|
219
223
|
"absolute -top-px right-2 -translate-y-full cursor-pointer rounded-t-md bg-kumo-brand px-2 py-0.5 text-xs text-white opacity-0 transition-opacity group-focus-within/container:opacity-100 group-hover/container:opacity-100 hover:brightness-120 focus:outline-none focus:ring-kumo-focus/50 focus-visible:ring-2 focus-visible:ring-kumo-brand",
|
|
220
224
|
// Defensive styles to prevent global CSS pollution
|
|
221
225
|
"border-none shadow-none m-0 h-auto min-h-0"
|
|
222
226
|
),
|
|
223
|
-
children:
|
|
227
|
+
children: h ? "Copied" : "Copy"
|
|
224
228
|
}
|
|
225
229
|
)
|
|
226
230
|
] }), P = /* @__PURE__ */ b("div", { children: [
|
|
227
|
-
s ? /* @__PURE__ */
|
|
231
|
+
s ? /* @__PURE__ */ r(
|
|
228
232
|
"div",
|
|
229
233
|
{
|
|
230
234
|
ref: u,
|
|
231
235
|
role: "button",
|
|
236
|
+
"data-kumo-component": "SensitiveInput",
|
|
237
|
+
"data-kumo-part": "masked-container",
|
|
232
238
|
tabIndex: i ? -1 : 0,
|
|
233
239
|
className: U,
|
|
234
240
|
onClick: te,
|
|
@@ -238,15 +244,15 @@ const Se = fe, ye = {
|
|
|
238
244
|
"aria-disabled": i,
|
|
239
245
|
children: F
|
|
240
246
|
}
|
|
241
|
-
) : /* @__PURE__ */
|
|
242
|
-
s && /* @__PURE__ */
|
|
247
|
+
) : /* @__PURE__ */ r("div", { ref: u, className: U, children: F }),
|
|
248
|
+
s && /* @__PURE__ */ r("span", { id: A, className: "sr-only", children: "Click or press Enter to reveal." }),
|
|
243
249
|
/* @__PURE__ */ b("span", { id: K, className: "sr-only", "aria-live": "polite", children: [
|
|
244
250
|
n === "masked" && o && "Value hidden",
|
|
245
|
-
|
|
251
|
+
h && "Copied to clipboard"
|
|
246
252
|
] })
|
|
247
253
|
] });
|
|
248
|
-
return y ? /* @__PURE__ */
|
|
249
|
-
|
|
254
|
+
return y ? /* @__PURE__ */ r(
|
|
255
|
+
he,
|
|
250
256
|
{
|
|
251
257
|
label: y,
|
|
252
258
|
required: Y,
|
|
@@ -260,8 +266,8 @@ const Se = fe, ye = {
|
|
|
260
266
|
);
|
|
261
267
|
be.displayName = "SensitiveInput";
|
|
262
268
|
export {
|
|
263
|
-
|
|
269
|
+
Te as K,
|
|
264
270
|
be as S,
|
|
265
271
|
ye as a
|
|
266
272
|
};
|
|
267
|
-
//# sourceMappingURL=sensitive-input-
|
|
273
|
+
//# sourceMappingURL=sensitive-input-dgoxjtoxl4zqa51v.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sensitive-input-bjg6m791yz7g6bn3.js","sources":["../../src/components/sensitive-input/sensitive-input.tsx"],"sourcesContent":["import { Eye, EyeSlash } from \"@phosphor-icons/react\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Input as BaseInput } from \"@base-ui/react/input\";\nimport {\n inputVariants,\n KUMO_INPUT_VARIANTS,\n type KumoInputSize,\n type KumoInputVariant,\n} from \"../input/input\";\nimport { Field, type FieldErrorMatch } from \"../field/field\";\n\nexport const KUMO_SENSITIVE_INPUT_VARIANTS = KUMO_INPUT_VARIANTS;\n\nexport const KUMO_SENSITIVE_INPUT_DEFAULT_VARIANTS = {\n size: \"base\",\n variant: \"default\",\n} as const;\n\ntype Mode = \"masked\" | \"revealed\" | \"empty\";\n\n/**\n * SensitiveInput component props.\n *\n * @example\n * ```tsx\n * <SensitiveInput label=\"API Key\" defaultValue=\"sk_live_abc123xyz789\" />\n * <SensitiveInput label=\"Secret\" value={secret} onValueChange={setSecret} />\n * ```\n */\nexport interface SensitiveInputProps\n extends Omit<\n ComponentPropsWithoutRef<\"input\">,\n \"size\" | \"type\" | \"value\" | \"defaultValue\"\n > {\n /** Controlled value */\n value?: string;\n /** Uncontrolled default value */\n defaultValue?: string;\n /** Simplified change handler receiving just the value */\n onValueChange?: (value: string) => void;\n /** Callback fired after value is copied to clipboard */\n onCopy?: () => void;\n /**\n * Size of the input.\n * - `\"xs\"` — Extra small for compact UIs\n * - `\"sm\"` — Small for secondary fields\n * - `\"base\"` — Default input size\n * - `\"lg\"` — Large for prominent fields\n * @default \"base\"\n */\n size?: KumoInputSize;\n /**\n * Style variant of the input.\n * - `\"default\"` — Default input appearance\n * - `\"error\"` — Error state for validation failures\n * @default \"default\"\n */\n variant?: KumoInputVariant;\n /** Label content for the input (enables Field wrapper and sets masked state label) - can be a string or any React node */\n label?: ReactNode;\n /** Tooltip content to display next to the label via an info icon */\n labelTooltip?: ReactNode;\n /** Helper text displayed below the input */\n description?: ReactNode;\n /** Error message or validation error object */\n error?: string | { message: ReactNode; match: FieldErrorMatch };\n}\n\n/**\n * Password/secret input that masks its value by default and reveals on click.\n * Includes a built-in copy-to-clipboard button on hover.\n *\n * @example\n * ```tsx\n * <SensitiveInput label=\"API Key\" defaultValue=\"sk_live_abc123xyz789\" />\n * ```\n */\nexport const SensitiveInput = forwardRef<HTMLInputElement, SensitiveInputProps>(\n (\n {\n value: controlledValue,\n defaultValue = \"\",\n onChange,\n onValueChange,\n onCopy,\n size = KUMO_SENSITIVE_INPUT_DEFAULT_VARIANTS.size,\n variant: variantProp,\n disabled = false,\n readOnly = false,\n id,\n autoComplete = \"off\",\n className,\n label,\n labelTooltip,\n description,\n error,\n required,\n ...inputProps\n },\n ref,\n ) => {\n // Deprecation warning for variant=\"error\"\n if (process.env.NODE_ENV !== \"production\" && variantProp === \"error\") {\n console.warn(\n '[Kumo SensitiveInput]: variant=\"error\" is deprecated. ' +\n \"Error styling is now automatically applied when the `error` prop is truthy. \" +\n \"Simply remove the variant prop and pass an error message instead.\",\n );\n }\n\n // Auto-apply error styling when error prop is truthy\n // Explicit variant prop takes precedence for backwards compatibility\n const variant = variantProp ?? (error ? \"error\" : \"default\");\n // For aria-label, only use string labels (ReactNode labels can't be used for aria-label)\n const ariaLabelFallback =\n typeof label === \"string\" ? label : \"Sensitive value\";\n const isControlled = controlledValue !== undefined;\n const [internalValue, setInternalValue] = useState(defaultValue);\n const value = isControlled ? controlledValue : internalValue;\n const hasValue = value.length > 0;\n\n const [mode, setMode] = useState<Mode>(() =>\n hasValue ? \"masked\" : \"empty\",\n );\n\n const [copied, setCopied] = useState(false);\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const liveRegionId = useId();\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const maskedInstructionId = useId();\n\n const mergedRef = useCallback(\n (node: HTMLInputElement | null) => {\n inputRef.current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [ref],\n );\n\n // Reset copied state after 2 seconds\n useEffect(() => {\n if (copied) {\n const timeoutId = setTimeout(() => setCopied(false), 2000);\n return () => clearTimeout(timeoutId);\n }\n }, [copied]);\n\n const copyToClipboard = useCallback(\n async (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation();\n try {\n if (\n typeof navigator !== \"undefined\" &&\n navigator.clipboard &&\n typeof navigator.clipboard.writeText === \"function\"\n ) {\n await navigator.clipboard.writeText(value);\n setCopied(true);\n onCopy?.();\n return;\n }\n } catch {\n // Fall through to manual fallback\n }\n\n if (typeof document !== \"undefined\") {\n const textarea = document.createElement(\"textarea\");\n textarea.value = value;\n textarea.setAttribute(\"readonly\", \"\");\n textarea.style.position = \"absolute\";\n textarea.style.left = \"-9999px\";\n document.body.appendChild(textarea);\n const selection = document.getSelection();\n const previousRange = selection?.rangeCount\n ? selection.getRangeAt(0)\n : null;\n textarea.select();\n try {\n document.execCommand(\"copy\");\n setCopied(true);\n onCopy?.();\n } catch (error) {\n console.warn(\"Clipboard copy failed\", error);\n } finally {\n document.body.removeChild(textarea);\n if (previousRange) {\n selection?.removeAllRanges();\n selection?.addRange(previousRange);\n }\n }\n }\n },\n [value, onCopy],\n );\n\n // Sync mode when value changes externally\n const prevHasValueRef = useRef(hasValue);\n if (prevHasValueRef.current !== hasValue) {\n prevHasValueRef.current = hasValue;\n if (!hasValue && mode === \"masked\") {\n setMode(\"empty\");\n }\n }\n\n const handleContainerClick = useCallback(\n (e: React.MouseEvent) => {\n if (disabled) return;\n // Ignore clicks that originated from outside (e.g., label click focusing input)\n // Label clicks trigger a click on the input, but the click coordinates are outside the container\n if (containerRef.current) {\n const rect = containerRef.current.getBoundingClientRect();\n const isClickInsideContainer =\n e.clientX >= rect.left &&\n e.clientX <= rect.right &&\n e.clientY >= rect.top &&\n e.clientY <= rect.bottom;\n if (!isClickInsideContainer) return;\n }\n if (mode === \"masked\" && hasValue) {\n setMode(\"revealed\");\n if (!readOnly) {\n setTimeout(() => inputRef.current?.focus(), 0);\n }\n }\n },\n [mode, hasValue, disabled, readOnly],\n );\n\n const handleToggleVisibility = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation();\n if (mode === \"revealed\") {\n setMode(\"masked\");\n } else if (mode === \"empty\" && hasValue) {\n setMode(\"revealed\");\n }\n },\n [mode, hasValue],\n );\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n if (!isControlled) {\n setInternalValue(newValue);\n }\n // When typing into an empty field, switch to revealed mode\n // so the input shows as type=\"text\" instead of type=\"password\"\n if (mode === \"empty\" && newValue.length > 0) {\n setMode(\"revealed\");\n }\n onChange?.(e);\n onValueChange?.(newValue);\n },\n [isControlled, onChange, onValueChange, mode],\n );\n\n const handleBlur = useCallback(\n (e: React.FocusEvent<HTMLInputElement>) => {\n // Don't mask if focus is moving to a button inside the container (copy/eye buttons)\n if (\n containerRef.current &&\n e.relatedTarget instanceof Node &&\n containerRef.current.contains(e.relatedTarget)\n ) {\n return;\n }\n if (hasValue) {\n setMode(\"masked\");\n }\n },\n [hasValue],\n );\n\n const handleContainerKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (disabled) return;\n if (mode === \"masked\" && hasValue) {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setMode(\"revealed\");\n if (!readOnly) {\n setTimeout(() => inputRef.current?.focus(), 0);\n }\n }\n }\n },\n [mode, hasValue, disabled, readOnly],\n );\n\n const handleInputKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (mode === \"revealed\" && e.key === \"Escape\") {\n setMode(\"masked\");\n // Move focus to container to avoid focus trap (input becomes tabIndex={-1})\n setTimeout(() => containerRef.current?.focus(), 0);\n }\n },\n [mode],\n );\n\n const isMaskedWithValue = mode === \"masked\" && hasValue;\n const showEyeButton =\n !disabled && (mode === \"revealed\" || (mode === \"empty\" && hasValue));\n\n // Icon sizes matching input sizes\n const iconSize = size === \"xs\" || size === \"sm\" ? \"size-3\" : \"size-4\";\n\n const containerClassName = cn(\n inputVariants({ size, variant, parentFocusIndicator: true }),\n \"group/container relative flex w-full items-center\",\n // Show browser-native focus outline on container when child input is focused\n \"focus-within:outline focus-within:outline-2 focus-within:outline-kumo-focus\",\n isMaskedWithValue && !disabled && \"cursor-pointer\",\n disabled && \"cursor-not-allowed\",\n className,\n );\n\n const containerContent = (\n <>\n {/* Input - defines the width, always rendered */}\n <BaseInput\n ref={mergedRef}\n id={inputId}\n type={mode === \"revealed\" ? \"text\" : \"password\"}\n value={value}\n onChange={handleChange}\n onBlur={handleBlur}\n onKeyDown={handleInputKeyDown}\n disabled={disabled}\n readOnly={readOnly || isMaskedWithValue}\n autoComplete={autoComplete}\n tabIndex={isMaskedWithValue ? -1 : 0}\n className={cn(\n \"w-full border-0 bg-transparent p-0 text-kumo-default ring-0 outline-none kumo-input-placeholder disabled:cursor-not-allowed disabled:text-kumo-subtle\",\n size === \"xs\" && \"pr-5\",\n size === \"sm\" && \"pr-6\",\n size === \"base\" && \"pr-8\",\n size === \"lg\" && \"pr-10\",\n isMaskedWithValue && \"pointer-events-none text-transparent\",\n )}\n aria-hidden={isMaskedWithValue}\n {...inputProps}\n />\n\n {/* Mask overlay - absolutely positioned, doesn't affect layout */}\n <span\n className={cn(\n \"pointer-events-none absolute inset-y-0 left-0 flex items-center overflow-hidden select-none\",\n // Match input pr padding (space for icon)\n size === \"xs\" && \"right-5\",\n size === \"sm\" && \"right-6\",\n size === \"base\" && \"right-8\",\n size === \"lg\" && \"right-10\",\n // Match the padding from inputVariants\n size === \"xs\" && \"px-1.5\",\n size === \"sm\" && \"px-2\",\n size === \"base\" && \"px-3\",\n size === \"lg\" && \"px-4\",\n // Hidden when not masked\n !isMaskedWithValue && \"invisible\",\n // When masked: enable pointer events\n isMaskedWithValue && \"pointer-events-auto\",\n // Text color - use text-kumo-default to contrast with bg-kumo-control input background\n \"text-kumo-default\",\n // Hover state - pure CSS, no React state (group for children)\n \"group/mask\",\n )}\n aria-hidden=\"true\"\n >\n {/* Both texts rendered, stacked. Visibility toggled on hover to prevent layout shift */}\n <span className=\"relative\">\n <span\n className={cn(\n isMaskedWithValue &&\n !disabled &&\n \"group-focus-within/container:invisible group-hover/mask:invisible\",\n )}\n >\n ••••••••\n </span>\n {isMaskedWithValue && !disabled && (\n <span className=\"invisible absolute left-0 top-0 whitespace-nowrap text-kumo-subtle group-focus-within/container:visible group-hover/mask:visible\">\n Click to reveal\n </span>\n )}\n </span>\n </span>\n\n {/* Eye button - absolutely positioned to the right */}\n <button\n type=\"button\"\n onClick={handleToggleVisibility}\n onKeyDown={(e) => e.stopPropagation()}\n aria-label={mode === \"revealed\" ? \"Hide value\" : \"Reveal value\"}\n tabIndex={showEyeButton ? 0 : -1}\n className={cn(\n \"absolute top-1/2 right-0 -translate-y-1/2 cursor-pointer text-kumo-subtle hover:text-kumo-default focus:text-kumo-default focus:ring-kumo-focus/50 focus-visible:ring-2 focus-visible:ring-kumo-brand focus-visible:rounded-sm\",\n // Defensive styles to prevent global CSS pollution (e.g., button { background: gray })\n \"bg-transparent border-none shadow-none p-0 m-0 h-auto min-h-0 inline-flex items-center justify-center\",\n // Match right padding from inputVariants\n size === \"xs\" && \"right-1.5\",\n size === \"sm\" && \"right-2\",\n size === \"base\" && \"right-3\",\n size === \"lg\" && \"right-4\",\n iconSize,\n !showEyeButton && \"pointer-events-none opacity-0\",\n )}\n >\n {mode === \"revealed\" ? (\n <EyeSlash className=\"size-full\" />\n ) : (\n <Eye className=\"size-full\" />\n )}\n </button>\n\n {/* Copy tab - appears on hover/focus at top right (hidden when disabled) */}\n {hasValue && !disabled && (\n <button\n type=\"button\"\n onClick={copyToClipboard}\n onKeyDown={(e) => e.stopPropagation()}\n aria-label={copied ? \"Copied\" : \"Copy to clipboard\"}\n className={cn(\n \"absolute -top-px right-2 -translate-y-full cursor-pointer rounded-t-md bg-kumo-brand px-2 py-0.5 text-xs text-white opacity-0 transition-opacity group-focus-within/container:opacity-100 group-hover/container:opacity-100 hover:brightness-120 focus:outline-none focus:ring-kumo-focus/50 focus-visible:ring-2 focus-visible:ring-kumo-brand\",\n // Defensive styles to prevent global CSS pollution\n \"border-none shadow-none m-0 h-auto min-h-0\",\n )}\n >\n {copied ? \"Copied\" : \"Copy\"}\n </button>\n )}\n </>\n );\n\n const input = (\n <div>\n {isMaskedWithValue ? (\n <div\n ref={containerRef}\n // Cannot use <button> here because containerContent contains interactive button elements (Copy, Reveal).\n // Using role=\"button\" with proper keyboard handling instead.\n // oxlint-disable-next-line prefer-tag-over-role\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n className={containerClassName}\n onClick={handleContainerClick}\n onKeyDown={handleContainerKeyDown}\n aria-label={`${ariaLabelFallback}, masked.`}\n aria-describedby={`${maskedInstructionId} ${liveRegionId}`}\n aria-disabled={disabled}\n >\n {containerContent}\n </div>\n ) : (\n <div ref={containerRef} className={containerClassName}>\n {containerContent}\n </div>\n )}\n {isMaskedWithValue && (\n <span id={maskedInstructionId} className=\"sr-only\">\n Click or press Enter to reveal.\n </span>\n )}\n <span id={liveRegionId} className=\"sr-only\" aria-live=\"polite\">\n {mode === \"masked\" && hasValue && \"Value hidden\"}\n {copied && \"Copied to clipboard\"}\n </span>\n </div>\n );\n\n // Render with Field wrapper if label is provided\n if (label) {\n return (\n <Field\n label={label}\n required={required}\n labelTooltip={labelTooltip}\n description={description}\n error={\n error\n ? typeof error === \"string\"\n ? { message: error, match: true }\n : error\n : undefined\n }\n >\n {input}\n </Field>\n );\n }\n\n // Render bare input without Field wrapper\n return input;\n },\n);\n\nSensitiveInput.displayName = \"SensitiveInput\";\n"],"names":["KUMO_SENSITIVE_INPUT_VARIANTS","KUMO_INPUT_VARIANTS","KUMO_SENSITIVE_INPUT_DEFAULT_VARIANTS","SensitiveInput","forwardRef","controlledValue","defaultValue","onChange","onValueChange","onCopy","size","variantProp","disabled","readOnly","id","autoComplete","className","label","labelTooltip","description","error","required","inputProps","ref","variant","ariaLabelFallback","isControlled","internalValue","setInternalValue","useState","value","hasValue","mode","setMode","copied","setCopied","inputRef","useRef","containerRef","liveRegionId","useId","generatedId","inputId","maskedInstructionId","mergedRef","useCallback","node","useEffect","timeoutId","copyToClipboard","textarea","selection","previousRange","prevHasValueRef","handleContainerClick","rect","handleToggleVisibility","handleChange","newValue","handleBlur","handleContainerKeyDown","handleInputKeyDown","isMaskedWithValue","showEyeButton","iconSize","containerClassName","cn","inputVariants","containerContent","jsxs","Fragment","jsx","BaseInput","EyeSlash","Eye","input","Field"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sensitive-input-dgoxjtoxl4zqa51v.js","sources":["../../src/components/sensitive-input/sensitive-input.tsx"],"sourcesContent":["import { Eye, EyeSlash } from \"@phosphor-icons/react\";\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Input as BaseInput } from \"@base-ui/react/input\";\nimport {\n inputVariants,\n KUMO_INPUT_VARIANTS,\n type KumoInputSize,\n type KumoInputVariant,\n} from \"../input/input\";\nimport { Field, type FieldErrorMatch } from \"../field/field\";\n\nexport const KUMO_SENSITIVE_INPUT_VARIANTS = KUMO_INPUT_VARIANTS;\n\nexport const KUMO_SENSITIVE_INPUT_DEFAULT_VARIANTS = {\n size: \"base\",\n variant: \"default\",\n} as const;\n\ntype Mode = \"masked\" | \"revealed\" | \"empty\";\n\n/**\n * SensitiveInput component props.\n *\n * @example\n * ```tsx\n * <SensitiveInput label=\"API Key\" defaultValue=\"sk_live_abc123xyz789\" />\n * <SensitiveInput label=\"Secret\" value={secret} onValueChange={setSecret} />\n * ```\n */\nexport interface SensitiveInputProps\n extends Omit<\n ComponentPropsWithoutRef<\"input\">,\n \"size\" | \"type\" | \"value\" | \"defaultValue\"\n > {\n /** Controlled value */\n value?: string;\n /** Uncontrolled default value */\n defaultValue?: string;\n /** Simplified change handler receiving just the value */\n onValueChange?: (value: string) => void;\n /** Callback fired after value is copied to clipboard */\n onCopy?: () => void;\n /**\n * Size of the input.\n * - `\"xs\"` — Extra small for compact UIs\n * - `\"sm\"` — Small for secondary fields\n * - `\"base\"` — Default input size\n * - `\"lg\"` — Large for prominent fields\n * @default \"base\"\n */\n size?: KumoInputSize;\n /**\n * Style variant of the input.\n * - `\"default\"` — Default input appearance\n * - `\"error\"` — Error state for validation failures\n * @default \"default\"\n */\n variant?: KumoInputVariant;\n /** Label content for the input (enables Field wrapper and sets masked state label) - can be a string or any React node */\n label?: ReactNode;\n /** Tooltip content to display next to the label via an info icon */\n labelTooltip?: ReactNode;\n /** Helper text displayed below the input */\n description?: ReactNode;\n /** Error message or validation error object */\n error?: string | { message: ReactNode; match: FieldErrorMatch };\n}\n\n/**\n * Password/secret input that masks its value by default and reveals on click.\n * Includes a built-in copy-to-clipboard button on hover.\n *\n * @example\n * ```tsx\n * <SensitiveInput label=\"API Key\" defaultValue=\"sk_live_abc123xyz789\" />\n * ```\n */\nexport const SensitiveInput = forwardRef<HTMLInputElement, SensitiveInputProps>(\n (\n {\n value: controlledValue,\n defaultValue = \"\",\n onChange,\n onValueChange,\n onCopy,\n size = KUMO_SENSITIVE_INPUT_DEFAULT_VARIANTS.size,\n variant: variantProp,\n disabled = false,\n readOnly = false,\n id,\n autoComplete = \"off\",\n className,\n label,\n labelTooltip,\n description,\n error,\n required,\n ...inputProps\n },\n ref,\n ) => {\n // Deprecation warning for variant=\"error\"\n if (process.env.NODE_ENV !== \"production\" && variantProp === \"error\") {\n console.warn(\n '[Kumo SensitiveInput]: variant=\"error\" is deprecated. ' +\n \"Error styling is now automatically applied when the `error` prop is truthy. \" +\n \"Simply remove the variant prop and pass an error message instead.\",\n );\n }\n\n // Auto-apply error styling when error prop is truthy\n // Explicit variant prop takes precedence for backwards compatibility\n const variant = variantProp ?? (error ? \"error\" : \"default\");\n // For aria-label, only use string labels (ReactNode labels can't be used for aria-label)\n const ariaLabelFallback =\n typeof label === \"string\" ? label : \"Sensitive value\";\n const isControlled = controlledValue !== undefined;\n const [internalValue, setInternalValue] = useState(defaultValue);\n const value = isControlled ? controlledValue : internalValue;\n const hasValue = value.length > 0;\n\n const [mode, setMode] = useState<Mode>(() =>\n hasValue ? \"masked\" : \"empty\",\n );\n\n const [copied, setCopied] = useState(false);\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const liveRegionId = useId();\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const maskedInstructionId = useId();\n\n const mergedRef = useCallback(\n (node: HTMLInputElement | null) => {\n inputRef.current = node;\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n },\n [ref],\n );\n\n // Reset copied state after 2 seconds\n useEffect(() => {\n if (copied) {\n const timeoutId = setTimeout(() => setCopied(false), 2000);\n return () => clearTimeout(timeoutId);\n }\n }, [copied]);\n\n const copyToClipboard = useCallback(\n async (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation();\n try {\n if (\n typeof navigator !== \"undefined\" &&\n navigator.clipboard &&\n typeof navigator.clipboard.writeText === \"function\"\n ) {\n await navigator.clipboard.writeText(value);\n setCopied(true);\n onCopy?.();\n return;\n }\n } catch {\n // Fall through to manual fallback\n }\n\n if (typeof document !== \"undefined\") {\n const textarea = document.createElement(\"textarea\");\n textarea.value = value;\n textarea.setAttribute(\"readonly\", \"\");\n textarea.style.position = \"absolute\";\n textarea.style.left = \"-9999px\";\n document.body.appendChild(textarea);\n const selection = document.getSelection();\n const previousRange = selection?.rangeCount\n ? selection.getRangeAt(0)\n : null;\n textarea.select();\n try {\n document.execCommand(\"copy\");\n setCopied(true);\n onCopy?.();\n } catch (error) {\n console.warn(\"Clipboard copy failed\", error);\n } finally {\n document.body.removeChild(textarea);\n if (previousRange) {\n selection?.removeAllRanges();\n selection?.addRange(previousRange);\n }\n }\n }\n },\n [value, onCopy],\n );\n\n // Sync mode when value changes externally\n const prevHasValueRef = useRef(hasValue);\n if (prevHasValueRef.current !== hasValue) {\n prevHasValueRef.current = hasValue;\n if (!hasValue && mode === \"masked\") {\n setMode(\"empty\");\n }\n }\n\n const handleContainerClick = useCallback(\n (e: React.MouseEvent) => {\n if (disabled) return;\n // Ignore clicks that originated from outside (e.g., label click focusing input)\n // Label clicks trigger a click on the input, but the click coordinates are outside the container\n if (containerRef.current) {\n const rect = containerRef.current.getBoundingClientRect();\n const isClickInsideContainer =\n e.clientX >= rect.left &&\n e.clientX <= rect.right &&\n e.clientY >= rect.top &&\n e.clientY <= rect.bottom;\n if (!isClickInsideContainer) return;\n }\n if (mode === \"masked\" && hasValue) {\n setMode(\"revealed\");\n if (!readOnly) {\n setTimeout(() => inputRef.current?.focus(), 0);\n }\n }\n },\n [mode, hasValue, disabled, readOnly],\n );\n\n const handleToggleVisibility = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation();\n if (mode === \"revealed\") {\n setMode(\"masked\");\n } else if (mode === \"empty\" && hasValue) {\n setMode(\"revealed\");\n }\n },\n [mode, hasValue],\n );\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n if (!isControlled) {\n setInternalValue(newValue);\n }\n // When typing into an empty field, switch to revealed mode\n // so the input shows as type=\"text\" instead of type=\"password\"\n if (mode === \"empty\" && newValue.length > 0) {\n setMode(\"revealed\");\n }\n onChange?.(e);\n onValueChange?.(newValue);\n },\n [isControlled, onChange, onValueChange, mode],\n );\n\n const handleBlur = useCallback(\n (e: React.FocusEvent<HTMLInputElement>) => {\n // Don't mask if focus is moving to a button inside the container (copy/eye buttons)\n if (\n containerRef.current &&\n e.relatedTarget instanceof Node &&\n containerRef.current.contains(e.relatedTarget)\n ) {\n return;\n }\n if (hasValue) {\n setMode(\"masked\");\n }\n },\n [hasValue],\n );\n\n const handleContainerKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (disabled) return;\n if (mode === \"masked\" && hasValue) {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setMode(\"revealed\");\n if (!readOnly) {\n setTimeout(() => inputRef.current?.focus(), 0);\n }\n }\n }\n },\n [mode, hasValue, disabled, readOnly],\n );\n\n const handleInputKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (mode === \"revealed\" && e.key === \"Escape\") {\n setMode(\"masked\");\n // Move focus to container to avoid focus trap (input becomes tabIndex={-1})\n setTimeout(() => containerRef.current?.focus(), 0);\n }\n },\n [mode],\n );\n\n const isMaskedWithValue = mode === \"masked\" && hasValue;\n const showEyeButton =\n !disabled && (mode === \"revealed\" || (mode === \"empty\" && hasValue));\n\n // Icon sizes matching input sizes\n const iconSize = size === \"xs\" || size === \"sm\" ? \"size-3\" : \"size-4\";\n\n const containerClassName = cn(\n inputVariants({ size, variant, parentFocusIndicator: true }),\n \"group/container relative flex w-full items-center\",\n // Show browser-native focus outline on container when child input is focused\n \"focus-within:outline focus-within:outline-2 focus-within:outline-kumo-focus\",\n isMaskedWithValue && !disabled && \"cursor-pointer\",\n disabled && \"cursor-not-allowed\",\n className,\n );\n\n const containerContent = (\n <>\n {/* Input - defines the width, always rendered */}\n <BaseInput\n ref={mergedRef}\n id={inputId}\n type={mode === \"revealed\" ? \"text\" : \"password\"}\n value={value}\n onChange={handleChange}\n onBlur={handleBlur}\n onKeyDown={handleInputKeyDown}\n disabled={disabled}\n readOnly={readOnly || isMaskedWithValue}\n autoComplete={autoComplete}\n tabIndex={isMaskedWithValue ? -1 : 0}\n className={cn(\n \"w-full border-0 bg-transparent p-0 text-kumo-default ring-0 outline-none kumo-input-placeholder disabled:cursor-not-allowed disabled:text-kumo-subtle\",\n size === \"xs\" && \"pr-5\",\n size === \"sm\" && \"pr-6\",\n size === \"base\" && \"pr-8\",\n size === \"lg\" && \"pr-10\",\n isMaskedWithValue && \"pointer-events-none text-transparent\",\n )}\n aria-hidden={isMaskedWithValue}\n {...inputProps}\n />\n\n {/* Mask overlay - absolutely positioned, doesn't affect layout */}\n <span\n className={cn(\n \"pointer-events-none absolute inset-y-0 left-0 flex items-center overflow-hidden select-none\",\n // Match input pr padding (space for icon)\n size === \"xs\" && \"right-5\",\n size === \"sm\" && \"right-6\",\n size === \"base\" && \"right-8\",\n size === \"lg\" && \"right-10\",\n // Match the padding from inputVariants\n size === \"xs\" && \"px-1.5\",\n size === \"sm\" && \"px-2\",\n size === \"base\" && \"px-3\",\n size === \"lg\" && \"px-4\",\n // Hidden when not masked\n !isMaskedWithValue && \"invisible\",\n // When masked: enable pointer events\n isMaskedWithValue && \"pointer-events-auto\",\n // Text color - use text-kumo-default to contrast with bg-kumo-control input background\n \"text-kumo-default\",\n // Hover state - pure CSS, no React state (group for children)\n \"group/mask\",\n )}\n aria-hidden=\"true\"\n >\n {/* Both texts rendered, stacked. Visibility toggled on hover to prevent layout shift */}\n <span className=\"relative\">\n <span\n className={cn(\n isMaskedWithValue &&\n !disabled &&\n \"group-focus-within/container:invisible group-hover/mask:invisible\",\n )}\n >\n ••••••••\n </span>\n {isMaskedWithValue && !disabled && (\n <span className=\"invisible absolute left-0 top-0 whitespace-nowrap text-kumo-subtle group-focus-within/container:visible group-hover/mask:visible\">\n Click to reveal\n </span>\n )}\n </span>\n </span>\n\n {/* Eye button - absolutely positioned to the right */}\n <button\n type=\"button\"\n data-kumo-component=\"SensitiveInput\"\n data-kumo-part=\"toggle-visibility\"\n onClick={handleToggleVisibility}\n onKeyDown={(e) => e.stopPropagation()}\n aria-label={mode === \"revealed\" ? \"Hide value\" : \"Reveal value\"}\n tabIndex={showEyeButton ? 0 : -1}\n className={cn(\n \"absolute top-1/2 right-0 -translate-y-1/2 cursor-pointer text-kumo-subtle hover:text-kumo-default focus:text-kumo-default focus:ring-kumo-focus/50 focus-visible:ring-2 focus-visible:ring-kumo-brand focus-visible:rounded-sm\",\n // Defensive styles to prevent global CSS pollution (e.g., button { background: gray })\n \"bg-transparent border-none shadow-none p-0 m-0 h-auto min-h-0 inline-flex items-center justify-center\",\n // Match right padding from inputVariants\n size === \"xs\" && \"right-1.5\",\n size === \"sm\" && \"right-2\",\n size === \"base\" && \"right-3\",\n size === \"lg\" && \"right-4\",\n iconSize,\n !showEyeButton && \"pointer-events-none opacity-0\",\n )}\n >\n {mode === \"revealed\" ? (\n <EyeSlash className=\"size-full\" />\n ) : (\n <Eye className=\"size-full\" />\n )}\n </button>\n\n {/* Copy tab - appears on hover/focus at top right (hidden when disabled) */}\n {hasValue && !disabled && (\n <button\n type=\"button\"\n data-kumo-component=\"SensitiveInput\"\n data-kumo-part=\"copy\"\n onClick={copyToClipboard}\n onKeyDown={(e) => e.stopPropagation()}\n aria-label={copied ? \"Copied\" : \"Copy to clipboard\"}\n className={cn(\n \"absolute -top-px right-2 -translate-y-full cursor-pointer rounded-t-md bg-kumo-brand px-2 py-0.5 text-xs text-white opacity-0 transition-opacity group-focus-within/container:opacity-100 group-hover/container:opacity-100 hover:brightness-120 focus:outline-none focus:ring-kumo-focus/50 focus-visible:ring-2 focus-visible:ring-kumo-brand\",\n // Defensive styles to prevent global CSS pollution\n \"border-none shadow-none m-0 h-auto min-h-0\",\n )}\n >\n {copied ? \"Copied\" : \"Copy\"}\n </button>\n )}\n </>\n );\n\n const input = (\n <div>\n {isMaskedWithValue ? (\n <div\n ref={containerRef}\n // Cannot use <button> here because containerContent contains interactive button elements (Copy, Reveal).\n // Using role=\"button\" with proper keyboard handling instead.\n // oxlint-disable-next-line prefer-tag-over-role\n role=\"button\"\n data-kumo-component=\"SensitiveInput\"\n data-kumo-part=\"masked-container\"\n tabIndex={disabled ? -1 : 0}\n className={containerClassName}\n onClick={handleContainerClick}\n onKeyDown={handleContainerKeyDown}\n aria-label={`${ariaLabelFallback}, masked.`}\n aria-describedby={`${maskedInstructionId} ${liveRegionId}`}\n aria-disabled={disabled}\n >\n {containerContent}\n </div>\n ) : (\n <div ref={containerRef} className={containerClassName}>\n {containerContent}\n </div>\n )}\n {isMaskedWithValue && (\n <span id={maskedInstructionId} className=\"sr-only\">\n Click or press Enter to reveal.\n </span>\n )}\n <span id={liveRegionId} className=\"sr-only\" aria-live=\"polite\">\n {mode === \"masked\" && hasValue && \"Value hidden\"}\n {copied && \"Copied to clipboard\"}\n </span>\n </div>\n );\n\n // Render with Field wrapper if label is provided\n if (label) {\n return (\n <Field\n label={label}\n required={required}\n labelTooltip={labelTooltip}\n description={description}\n error={\n error\n ? typeof error === \"string\"\n ? { message: error, match: true }\n : error\n : undefined\n }\n >\n {input}\n </Field>\n );\n }\n\n // Render bare input without Field wrapper\n return input;\n },\n);\n\nSensitiveInput.displayName = \"SensitiveInput\";\n"],"names":["KUMO_SENSITIVE_INPUT_VARIANTS","KUMO_INPUT_VARIANTS","KUMO_SENSITIVE_INPUT_DEFAULT_VARIANTS","SensitiveInput","forwardRef","controlledValue","defaultValue","onChange","onValueChange","onCopy","size","variantProp","disabled","readOnly","id","autoComplete","className","label","labelTooltip","description","error","required","inputProps","ref","variant","ariaLabelFallback","isControlled","internalValue","setInternalValue","useState","value","hasValue","mode","setMode","copied","setCopied","inputRef","useRef","containerRef","liveRegionId","useId","generatedId","inputId","maskedInstructionId","mergedRef","useCallback","node","useEffect","timeoutId","copyToClipboard","textarea","selection","previousRange","prevHasValueRef","handleContainerClick","rect","handleToggleVisibility","handleChange","newValue","handleBlur","handleContainerKeyDown","handleInputKeyDown","isMaskedWithValue","showEyeButton","iconSize","containerClassName","cn","inputVariants","containerContent","jsxs","Fragment","jsx","BaseInput","EyeSlash","Eye","input","Field"],"mappings":"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"}
|