@plumile/ui 0.1.146 → 0.1.150
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 +3 -0
- package/lib/esm/admin/theme/adminSurface.css.js +0 -2
- package/lib/esm/atomic/atoms/textarea/textarea.css.js +2 -0
- package/lib/esm/atomic/molecules/markdown/components/MarkdownCodeCopyButton.js +19 -35
- package/lib/esm/atomic/molecules/markdown/components/MarkdownCodeCopyButton.js.map +1 -1
- package/lib/esm/atomic/molecules/markdown/components/MarkdownEmphasis.css.js +0 -1
- package/lib/esm/atomic/molecules/markdown/components/MarkdownSubscript.css.js +1 -0
- package/lib/esm/backoffice/atoms/copyable_text/CopyableText.js +22 -42
- package/lib/esm/backoffice/atoms/copyable_text/CopyableText.js.map +1 -1
- package/lib/esm/backoffice/molecules/backoffice_json_viewer/BackofficeJsonViewer.js +2 -1
- package/lib/esm/backoffice/molecules/backoffice_json_viewer/BackofficeJsonViewer.js.map +1 -1
- package/lib/esm/backoffice/shared/copyWithExecCommand.js +1 -14
- package/lib/esm/hooks/useClipboardCopy.js +31 -0
- package/lib/esm/hooks/useClipboardCopy.js.map +1 -0
- package/lib/esm/index.js +223 -221
- package/lib/esm/node_modules/@shikijs/core/dist/index.js +99 -96
- package/lib/esm/node_modules/@shikijs/core/dist/index.js.map +1 -1
- package/lib/esm/node_modules/@shikijs/core/node_modules/@shikijs/types/dist/index.js.map +1 -1
- package/lib/esm/node_modules/@shikijs/primitive/dist/index.js +91 -85
- package/lib/esm/node_modules/@shikijs/primitive/dist/index.js.map +1 -1
- package/lib/esm/node_modules/@shikijs/primitive/node_modules/@shikijs/types/dist/index.js.map +1 -1
- package/lib/esm/node_modules/@vitest/runner/dist/chunk-artifact.js.map +1 -1
- package/lib/esm/node_modules/cytoscape/dist/cytoscape.esm.js +1 -1
- package/lib/esm/node_modules/cytoscape/dist/cytoscape.esm.js.map +1 -1
- package/lib/esm/node_modules/react-shiki/dist/index.js +1 -1
- package/lib/esm/node_modules/shiki/dist/bundle-full.js +1 -1
- package/lib/esm/node_modules/shiki/dist/bundle-full.js.map +1 -1
- package/lib/esm/node_modules/shiki/dist/{chunk-CtajNgzt.js → chunk-D1SwGrFN.js} +2 -2
- package/lib/esm/node_modules/shiki/dist/chunk-D1SwGrFN.js.map +1 -0
- package/lib/esm/node_modules/shiki/dist/engine-oniguruma.js +1 -1
- package/lib/esm/node_modules/shiki/dist/engine-oniguruma.js.map +1 -1
- package/lib/esm/node_modules/shiki/dist/{langs-bundle-full-DfKZStlK.js → langs-bundle-full-YTHnHqaM.js} +2 -2
- package/lib/esm/node_modules/shiki/dist/{langs-bundle-full-DfKZStlK.js.map → langs-bundle-full-YTHnHqaM.js.map} +1 -1
- package/lib/esm/node_modules/shiki/dist/themes.js.map +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/engine-oniguruma/dist/index.js.map +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/apex.js +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/apex.js.map +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/c3.js +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/c3.js.map +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/csharp.js +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/csharp.js.map +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/hack.js +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/hack.js.map +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/julia.js +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/julia.js.map +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/just.js +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/just.js.map +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/latex.js +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/latex.js.map +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/luau.js +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/luau.js.map +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/php.js +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/php.js.map +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/sql.js +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/sql.js.map +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/themes/dist/vesper.js +1 -1
- package/lib/esm/node_modules/shiki/node_modules/@shikijs/themes/dist/vesper.js.map +1 -1
- package/lib/esm/shared/clipboard.js +55 -0
- package/lib/esm/shared/clipboard.js.map +1 -0
- package/lib/types/atomic/molecules/markdown/components/MarkdownCodeCopyButton.d.ts.map +1 -1
- package/lib/types/backoffice/atoms/copyable_text/CopyableText.d.ts.map +1 -1
- package/lib/types/backoffice/shared/copyWithExecCommand.d.ts +1 -1
- package/lib/types/backoffice/shared/copyWithExecCommand.d.ts.map +1 -1
- package/lib/types/hooks/useClipboardCopy.d.ts +9 -0
- package/lib/types/hooks/useClipboardCopy.d.ts.map +1 -0
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/shared/clipboard.d.ts +9 -0
- package/lib/types/shared/clipboard.d.ts.map +1 -0
- package/package.json +4 -4
- package/lib/esm/backoffice/shared/copyWithExecCommand.js.map +0 -1
- package/lib/esm/node_modules/shiki/dist/chunk-CtajNgzt.js.map +0 -1
package/README.md
CHANGED
|
@@ -129,6 +129,9 @@ flat mental model.
|
|
|
129
129
|
- `HighlightCode` is the general code-display primitive. It supports a badge,
|
|
130
130
|
copy action, placeholder text, highlighted HTML/React content, and a plain
|
|
131
131
|
preformatted fallback.
|
|
132
|
+
- `copyTextToClipboard`, `copyRichClipboard`, and `useClipboardCopy` provide
|
|
133
|
+
shared clipboard behavior with rich multi-format writes where browsers
|
|
134
|
+
support them and text fallbacks everywhere else.
|
|
132
135
|
- `BackofficeJsonViewer` is the canonical structured JSON viewer for
|
|
133
136
|
backoffice surfaces. It safely stringifies unknown values, exposes copy and
|
|
134
137
|
collapse/expand controls, and accepts max-height and label overrides.
|
|
@@ -1,46 +1,30 @@
|
|
|
1
1
|
import { useUiTranslation as e } from "../../../../i18n/useUiTranslation.js";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { jsx as
|
|
2
|
+
import t from "../../../../hooks/useClipboardCopy.js";
|
|
3
|
+
import { MarkdownCopySuccessSvg as n } from "../../../../icons/markdown/MarkdownCopySuccessSvg.js";
|
|
4
|
+
import { MarkdownCopySvg as r } from "../../../../icons/markdown/MarkdownCopySvg.js";
|
|
5
|
+
import { copyButton as i, icon as a, label as o } from "./MarkdownCodeCopyButton.css.js";
|
|
6
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
7
7
|
//#region src/atomic/molecules/markdown/components/MarkdownCodeCopyButton.tsx
|
|
8
|
-
var
|
|
9
|
-
let { t:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
let
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (typeof navigator < "u" && (e = navigator.clipboard), e != null && typeof e.writeText == "function") await e.writeText(f);
|
|
17
|
-
else {
|
|
18
|
-
let e = document.createElement("textarea");
|
|
19
|
-
e.value = f, e.setAttribute("readonly", ""), e.style.position = "absolute", e.style.left = "-9999px", document.body.appendChild(e), e.select(), document.execCommand("copy"), document.body.removeChild(e);
|
|
20
|
-
}
|
|
21
|
-
h(!0), g.current != null && window.clearTimeout(g.current), g.current = window.setTimeout(() => {
|
|
22
|
-
h(!1), g.current = null;
|
|
23
|
-
}, 2e3);
|
|
24
|
-
} catch {}
|
|
25
|
-
}, [f]), v = p("markdown.code.copyTitle");
|
|
26
|
-
m && (v = p("markdown.code.copiedTitle"));
|
|
27
|
-
let y = /* @__PURE__ */ u(n, { className: i });
|
|
28
|
-
m && (y = /* @__PURE__ */ u(t, { className: i }));
|
|
29
|
-
let b = p("markdown.code.copy");
|
|
30
|
-
return m && (b = p("markdown.code.copied")), /* @__PURE__ */ d("button", {
|
|
31
|
-
className: r,
|
|
8
|
+
var l = ({ code: l }) => {
|
|
9
|
+
let { t: u } = e(), { copiedKey: d, copyText: f } = t(), p = d === l, m = u("markdown.code.copyTitle");
|
|
10
|
+
p && (m = u("markdown.code.copiedTitle"));
|
|
11
|
+
let h = /* @__PURE__ */ s(r, { className: a });
|
|
12
|
+
p && (h = /* @__PURE__ */ s(n, { className: a }));
|
|
13
|
+
let g = u("markdown.code.copy");
|
|
14
|
+
return p && (g = u("markdown.code.copied")), /* @__PURE__ */ c("button", {
|
|
15
|
+
className: i,
|
|
32
16
|
onClick: () => {
|
|
33
|
-
|
|
17
|
+
f(l, l).catch(() => {});
|
|
34
18
|
},
|
|
35
|
-
title:
|
|
19
|
+
title: m,
|
|
36
20
|
type: "button",
|
|
37
|
-
children: [
|
|
38
|
-
className:
|
|
39
|
-
children:
|
|
21
|
+
children: [h, /* @__PURE__ */ s("span", {
|
|
22
|
+
className: o,
|
|
23
|
+
children: g
|
|
40
24
|
})]
|
|
41
25
|
});
|
|
42
26
|
};
|
|
43
27
|
//#endregion
|
|
44
|
-
export {
|
|
28
|
+
export { l as MarkdownCodeCopyButton };
|
|
45
29
|
|
|
46
30
|
//# sourceMappingURL=MarkdownCodeCopyButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownCodeCopyButton.js","names":[],"sources":["../../../../../../src/atomic/molecules/markdown/components/MarkdownCodeCopyButton.tsx"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"MarkdownCodeCopyButton.js","names":[],"sources":["../../../../../../src/atomic/molecules/markdown/components/MarkdownCodeCopyButton.tsx"],"sourcesContent":["import { type JSX } from 'react';\n\nimport { useClipboardCopy } from '../../../../hooks/useClipboardCopy.js';\nimport { MarkdownCopySuccessSvg } from '../../../../icons/markdown/MarkdownCopySuccessSvg.js';\nimport { MarkdownCopySvg } from '../../../../icons/markdown/MarkdownCopySvg.js';\nimport { useUiTranslation } from '../../../../i18n/useUiTranslation.js';\n\nimport {\n copyButton,\n icon as iconClass,\n label,\n} from './MarkdownCodeCopyButton.css.js';\n\ntype Props = {\n code: string;\n};\n\nexport const MarkdownCodeCopyButton = ({ code }: Props): JSX.Element => {\n const { t } = useUiTranslation();\n const { copiedKey, copyText } = useClipboardCopy();\n const copied = copiedKey === code;\n\n let buttonTitle = t('markdown.code.copyTitle');\n if (copied) {\n buttonTitle = t('markdown.code.copiedTitle');\n }\n\n let iconElement: JSX.Element = <MarkdownCopySvg className={iconClass} />;\n if (copied) {\n iconElement = <MarkdownCopySuccessSvg className={iconClass} />;\n }\n\n let labelText = t('markdown.code.copy');\n if (copied) {\n labelText = t('markdown.code.copied');\n }\n\n return (\n <button\n className={copyButton}\n onClick={() => {\n copyText(code, code).catch(() => {\n // ignore copy failures surfaced via promise rejection\n });\n }}\n title={buttonTitle}\n type=\"button\"\n >\n {iconElement}\n <span className={label}>{labelText}</span>\n </button>\n );\n};\n"],"mappings":";;;;;;;AAiBA,IAAa,KAA0B,EAAE,cAA+B;CACtE,IAAM,EAAE,SAAM,EAAiB,GACzB,EAAE,cAAW,gBAAa,EAAiB,GAC3C,IAAS,MAAc,GAEzB,IAAc,EAAE,yBAAyB;CAC7C,AAAI,MACF,IAAc,EAAE,2BAA2B;CAG7C,IAAI,IAA2B,kBAAC,GAAD,EAAiB,WAAW,EAAY,CAAA;CACvE,AAAI,MACF,IAAc,kBAAC,GAAD,EAAwB,WAAW,EAAY,CAAA;CAG/D,IAAI,IAAY,EAAE,oBAAoB;CAKtC,OAJI,MACF,IAAY,EAAE,sBAAsB,IAIpC,kBAAC,UAAD;EACE,WAAW;EACX,eAAe;GACb,EAAS,GAAM,CAAI,EAAE,YAAY,CAEjC,CAAC;EACH;EACA,OAAO;EACP,MAAK;YARP,CAUG,GACD,kBAAC,QAAD;GAAM,WAAW;aAAQ;EAAgB,CAAA,CACnC;;AAEZ"}
|
|
@@ -1,63 +1,43 @@
|
|
|
1
1
|
import { cx as e } from "../../../theme/tools.js";
|
|
2
2
|
import { Button as t } from "../../../atomic/atoms/button/Button.js";
|
|
3
|
-
import
|
|
3
|
+
import n from "../../../hooks/useClipboardCopy.js";
|
|
4
4
|
import { feedback as r, root as i, value as a, valueNoTruncate as o } from "./copyableText.css.js";
|
|
5
|
-
import {
|
|
6
|
-
import { jsx as
|
|
7
|
-
import { useTranslation as
|
|
5
|
+
import { useMemo as s } from "react";
|
|
6
|
+
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
7
|
+
import { useTranslation as u } from "react-i18next";
|
|
8
8
|
//#region src/backoffice/atoms/copyable_text/CopyableText.tsx
|
|
9
|
-
var
|
|
10
|
-
let { t:
|
|
9
|
+
var d = ({ value: d, copyValue: f, className: p, truncate: m = !0, copyLabel: h, copiedLabel: g }) => {
|
|
10
|
+
let { t: _ } = u("ui", { useSuspense: !1 }), { copiedKey: v, copyText: y } = n(1400), b = h ?? _("backoffice.copyableText.copy", { defaultValue: "Copy" }), x = g ?? _("backoffice.copyableText.copied", { defaultValue: "Copied" }), S = f ?? d, C = S, w = v === C, T = s(() => {
|
|
11
11
|
let t = null;
|
|
12
|
-
return
|
|
13
|
-
}, [
|
|
14
|
-
|
|
15
|
-
},
|
|
16
|
-
|
|
17
|
-
k();
|
|
18
|
-
}, [k]);
|
|
19
|
-
let A = s(async () => {
|
|
20
|
-
k();
|
|
21
|
-
let e = !1;
|
|
22
|
-
try {
|
|
23
|
-
if (typeof navigator < "u") {
|
|
24
|
-
let { clipboard: t } = navigator;
|
|
25
|
-
await t.writeText(D), e = !0;
|
|
26
|
-
}
|
|
27
|
-
} catch {
|
|
28
|
-
e = !1;
|
|
29
|
-
}
|
|
30
|
-
e ||= n(D), e && (C(!0), w.current = window.setTimeout(() => {
|
|
31
|
-
C(!1), w.current = null;
|
|
32
|
-
}, 1400));
|
|
33
|
-
}, [k, D]), j = () => {
|
|
34
|
-
A().catch(() => {});
|
|
35
|
-
}, M = null;
|
|
36
|
-
return S && (M = /* @__PURE__ */ f("span", {
|
|
12
|
+
return m || (t = o), e(a, t, p);
|
|
13
|
+
}, [p, m]), E = () => {
|
|
14
|
+
y(S, C).catch(() => {});
|
|
15
|
+
}, D = null;
|
|
16
|
+
return w && (D = /* @__PURE__ */ c("span", {
|
|
37
17
|
className: r,
|
|
38
18
|
role: "status",
|
|
39
19
|
"aria-live": "polite",
|
|
40
|
-
children:
|
|
41
|
-
})), /* @__PURE__ */
|
|
20
|
+
children: x
|
|
21
|
+
})), /* @__PURE__ */ l("span", {
|
|
42
22
|
className: i,
|
|
43
23
|
children: [
|
|
44
|
-
/* @__PURE__ */
|
|
45
|
-
className:
|
|
46
|
-
title:
|
|
47
|
-
children:
|
|
24
|
+
/* @__PURE__ */ c("span", {
|
|
25
|
+
className: T,
|
|
26
|
+
title: d,
|
|
27
|
+
children: d
|
|
48
28
|
}),
|
|
49
|
-
/* @__PURE__ */
|
|
29
|
+
/* @__PURE__ */ c(t, {
|
|
50
30
|
type: "button",
|
|
51
31
|
variant: "secondary",
|
|
52
32
|
size: "small",
|
|
53
|
-
onClick:
|
|
54
|
-
children:
|
|
33
|
+
onClick: E,
|
|
34
|
+
children: b
|
|
55
35
|
}),
|
|
56
|
-
|
|
36
|
+
D
|
|
57
37
|
]
|
|
58
38
|
});
|
|
59
39
|
};
|
|
60
40
|
//#endregion
|
|
61
|
-
export {
|
|
41
|
+
export { d as CopyableText, d as default };
|
|
62
42
|
|
|
63
43
|
//# sourceMappingURL=CopyableText.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopyableText.js","names":[],"sources":["../../../../../src/backoffice/atoms/copyable_text/CopyableText.tsx"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"CopyableText.js","names":[],"sources":["../../../../../src/backoffice/atoms/copyable_text/CopyableText.tsx"],"sourcesContent":["import { useMemo, type JSX } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { Button } from '../../../atomic/atoms/button/Button.js';\nimport { useClipboardCopy } from '../../../hooks/useClipboardCopy.js';\nimport { cx } from '../../../theme/tools.js';\n\nimport * as styles from './copyableText.css.js';\n\nexport type CopyableTextProps = {\n value: string;\n copyValue?: string;\n className?: string;\n truncate?: boolean;\n copyLabel?: string;\n copiedLabel?: string;\n};\n\nexport const CopyableText = ({\n value,\n copyValue,\n className,\n truncate = true,\n copyLabel,\n copiedLabel,\n}: CopyableTextProps): JSX.Element => {\n const { t } = useTranslation('ui', { useSuspense: false });\n const { copiedKey, copyText } = useClipboardCopy(1400);\n const resolvedCopyLabel =\n copyLabel ??\n t('backoffice.copyableText.copy', {\n defaultValue: 'Copy',\n });\n const resolvedCopiedLabel =\n copiedLabel ??\n t('backoffice.copyableText.copied', {\n defaultValue: 'Copied',\n });\n\n const resolvedCopyValue = copyValue ?? value;\n const copyKey = resolvedCopyValue;\n const copied = copiedKey === copyKey;\n\n const displayClassName = useMemo(() => {\n let noTruncateClass: string | null = null;\n if (!truncate) {\n noTruncateClass = styles.valueNoTruncate;\n }\n return cx(styles.value, noTruncateClass, className);\n }, [className, truncate]);\n\n const handleCopyClick = () => {\n copyText(resolvedCopyValue, copyKey).catch(() => {});\n };\n\n let feedbackNode: JSX.Element | null = null;\n if (copied) {\n feedbackNode = (\n <span className={styles.feedback} role=\"status\" aria-live=\"polite\">\n {resolvedCopiedLabel}\n </span>\n );\n }\n\n return (\n <span className={styles.root}>\n <span className={displayClassName} title={value}>\n {value}\n </span>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={handleCopyClick}\n >\n {resolvedCopyLabel}\n </Button>\n {feedbackNode}\n </span>\n );\n};\n\nexport default CopyableText;\n"],"mappings":";;;;;;;;AAkBA,IAAa,KAAgB,EAC3B,OAAA,GACA,cACA,cACA,cAAW,IACX,cACA,qBACoC;CACpC,IAAM,EAAE,SAAM,EAAe,MAAM,EAAE,aAAa,GAAM,CAAC,GACnD,EAAE,cAAW,gBAAa,EAAiB,IAAI,GAC/C,IACJ,KACA,EAAE,gCAAgC,EAChC,cAAc,OAChB,CAAC,GACG,IACJ,KACA,EAAE,kCAAkC,EAClC,cAAc,SAChB,CAAC,GAEG,IAAoB,KAAa,GACjC,IAAU,GACV,IAAS,MAAc,GAEvB,IAAmB,QAAc;EACrC,IAAI,IAAiC;EAIrC,OAHK,MACH,IAAkB,IAEb,EAAG,GAAc,GAAiB,CAAS;CACpD,GAAG,CAAC,GAAW,CAAQ,CAAC,GAElB,UAAwB;EAC5B,EAAS,GAAmB,CAAO,EAAE,YAAY,CAAC,CAAC;CACrD,GAEI,IAAmC;CASvC,OARI,MACF,IACE,kBAAC,QAAD;EAAM,WAAW;EAAiB,MAAK;EAAS,aAAU;YACvD;CACG,CAAA,IAKR,kBAAC,QAAD;EAAM,WAAW;YAAjB;GACE,kBAAC,QAAD;IAAM,WAAW;IAAkB,OAAO;cACvC;GACG,CAAA;GACN,kBAAC,GAAD;IACE,MAAK;IACL,SAAQ;IACR,MAAK;IACL,SAAS;cAER;GACK,CAAA;GACP;EACG;;AAEV"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cx as e } from "../../../theme/tools.js";
|
|
2
2
|
import { Button as t } from "../../../atomic/atoms/button/Button.js";
|
|
3
|
-
import { copyWithExecCommand as n } from "
|
|
3
|
+
import { copyWithExecCommand as n } from "../../../shared/clipboard.js";
|
|
4
|
+
import "../../shared/copyWithExecCommand.js";
|
|
4
5
|
import { actions as r, container as i, header as a, pre as o, title as s, truncated as c } from "./backofficeJsonViewer.css.js";
|
|
5
6
|
import { useCallback as l, useMemo as u, useState as d } from "react";
|
|
6
7
|
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackofficeJsonViewer.js","names":[],"sources":["../../../../../src/backoffice/molecules/backoffice_json_viewer/BackofficeJsonViewer.tsx"],"sourcesContent":["import { useCallback, useMemo, useState, type JSX } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { Button } from '../../../atomic/atoms/button/Button.js';\nimport { cx } from '../../../theme/tools.js';\nimport { copyWithExecCommand } from '../../shared/copyWithExecCommand.js';\n\nimport * as styles from './backofficeJsonViewer.css.js';\n\nexport type BackofficeJsonViewerProps = {\n value: unknown;\n title?: string;\n className?: string;\n maxHeight?: string;\n truncate?: boolean;\n truncateLabel?: string;\n expandLabel?: string;\n copyLabel?: string;\n copiedLabel?: string;\n};\n\nexport const BackofficeJsonViewer = ({\n value,\n title,\n className,\n maxHeight,\n truncate = false,\n truncateLabel,\n expandLabel,\n copyLabel,\n copiedLabel,\n}: BackofficeJsonViewerProps): JSX.Element => {\n const { t } = useTranslation('ui');\n const [isCollapsed, setIsCollapsed] = useState(truncate);\n const [copied, setCopied] = useState(false);\n const resolvedTitle = title ?? t('backoffice.jsonViewer.title');\n const resolvedTruncateLabel =\n truncateLabel ?? t('backoffice.jsonViewer.collapse');\n const resolvedExpandLabel = expandLabel ?? t('backoffice.jsonViewer.expand');\n const resolvedCopyLabel = copyLabel ?? t('backoffice.jsonViewer.copy');\n const resolvedCopiedLabel = copiedLabel ?? t('backoffice.jsonViewer.copied');\n\n const jsonText = useMemo(() => {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return JSON.stringify({\n error: t('backoffice.jsonViewer.serializationError'),\n });\n }\n }, [t, value]);\n\n const handleCopy = useCallback(async () => {\n let ok = false;\n try {\n if (typeof navigator !== 'undefined') {\n await navigator.clipboard.writeText(jsonText);\n ok = true;\n }\n } catch {\n ok = false;\n }\n\n if (!ok) {\n ok = copyWithExecCommand(jsonText);\n }\n\n if (ok) {\n setCopied(true);\n window.setTimeout(() => {\n setCopied(false);\n }, 1400);\n }\n }, [jsonText]);\n\n const preStyle = useMemo(() => {\n if (maxHeight == null) {\n return undefined;\n }\n return { maxHeight };\n }, [maxHeight]);\n\n let copyButtonLabel = resolvedCopyLabel;\n if (copied) {\n copyButtonLabel = resolvedCopiedLabel;\n }\n\n let collapseButtonLabel = resolvedTruncateLabel;\n if (isCollapsed) {\n collapseButtonLabel = resolvedExpandLabel;\n }\n\n return (\n <div className={cx(styles.container, className)}>\n <div className={styles.header}>\n <span className={styles.title}>{resolvedTitle}</span>\n <div className={styles.actions}>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={() => {\n handleCopy().catch(() => {});\n }}\n >\n {copyButtonLabel}\n </Button>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={() => {\n setIsCollapsed((v) => {\n return !v;\n });\n }}\n >\n {collapseButtonLabel}\n </Button>\n </div>\n </div>\n <pre\n className={cx(styles.pre, { [styles.truncated]: isCollapsed })}\n style={preStyle}\n >\n {jsonText}\n </pre>\n </div>\n );\n};\n\nexport default BackofficeJsonViewer;\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"BackofficeJsonViewer.js","names":[],"sources":["../../../../../src/backoffice/molecules/backoffice_json_viewer/BackofficeJsonViewer.tsx"],"sourcesContent":["import { useCallback, useMemo, useState, type JSX } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { Button } from '../../../atomic/atoms/button/Button.js';\nimport { cx } from '../../../theme/tools.js';\nimport { copyWithExecCommand } from '../../shared/copyWithExecCommand.js';\n\nimport * as styles from './backofficeJsonViewer.css.js';\n\nexport type BackofficeJsonViewerProps = {\n value: unknown;\n title?: string;\n className?: string;\n maxHeight?: string;\n truncate?: boolean;\n truncateLabel?: string;\n expandLabel?: string;\n copyLabel?: string;\n copiedLabel?: string;\n};\n\nexport const BackofficeJsonViewer = ({\n value,\n title,\n className,\n maxHeight,\n truncate = false,\n truncateLabel,\n expandLabel,\n copyLabel,\n copiedLabel,\n}: BackofficeJsonViewerProps): JSX.Element => {\n const { t } = useTranslation('ui');\n const [isCollapsed, setIsCollapsed] = useState(truncate);\n const [copied, setCopied] = useState(false);\n const resolvedTitle = title ?? t('backoffice.jsonViewer.title');\n const resolvedTruncateLabel =\n truncateLabel ?? t('backoffice.jsonViewer.collapse');\n const resolvedExpandLabel = expandLabel ?? t('backoffice.jsonViewer.expand');\n const resolvedCopyLabel = copyLabel ?? t('backoffice.jsonViewer.copy');\n const resolvedCopiedLabel = copiedLabel ?? t('backoffice.jsonViewer.copied');\n\n const jsonText = useMemo(() => {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return JSON.stringify({\n error: t('backoffice.jsonViewer.serializationError'),\n });\n }\n }, [t, value]);\n\n const handleCopy = useCallback(async () => {\n let ok = false;\n try {\n if (typeof navigator !== 'undefined') {\n await navigator.clipboard.writeText(jsonText);\n ok = true;\n }\n } catch {\n ok = false;\n }\n\n if (!ok) {\n ok = copyWithExecCommand(jsonText);\n }\n\n if (ok) {\n setCopied(true);\n window.setTimeout(() => {\n setCopied(false);\n }, 1400);\n }\n }, [jsonText]);\n\n const preStyle = useMemo(() => {\n if (maxHeight == null) {\n return undefined;\n }\n return { maxHeight };\n }, [maxHeight]);\n\n let copyButtonLabel = resolvedCopyLabel;\n if (copied) {\n copyButtonLabel = resolvedCopiedLabel;\n }\n\n let collapseButtonLabel = resolvedTruncateLabel;\n if (isCollapsed) {\n collapseButtonLabel = resolvedExpandLabel;\n }\n\n return (\n <div className={cx(styles.container, className)}>\n <div className={styles.header}>\n <span className={styles.title}>{resolvedTitle}</span>\n <div className={styles.actions}>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={() => {\n handleCopy().catch(() => {});\n }}\n >\n {copyButtonLabel}\n </Button>\n <Button\n type=\"button\"\n variant=\"secondary\"\n size=\"small\"\n onClick={() => {\n setIsCollapsed((v) => {\n return !v;\n });\n }}\n >\n {collapseButtonLabel}\n </Button>\n </div>\n </div>\n <pre\n className={cx(styles.pre, { [styles.truncated]: isCollapsed })}\n style={preStyle}\n >\n {jsonText}\n </pre>\n </div>\n );\n};\n\nexport default BackofficeJsonViewer;\n"],"mappings":";;;;;;;;;AAqBA,IAAa,KAAwB,EACnC,UACA,OAAA,GACA,cACA,cACA,cAAW,IACX,kBACA,gBACA,cACA,qBAC4C;CAC5C,IAAM,EAAE,SAAM,EAAe,IAAI,GAC3B,CAAC,GAAa,KAAkB,EAAS,CAAQ,GACjD,CAAC,GAAQ,KAAa,EAAS,EAAK,GACpC,IAAgB,KAAS,EAAE,6BAA6B,GACxD,IACJ,KAAiB,EAAE,gCAAgC,GAC/C,IAAsB,KAAe,EAAE,8BAA8B,GACrE,IAAoB,KAAa,EAAE,4BAA4B,GAC/D,IAAsB,KAAe,EAAE,8BAA8B,GAErE,IAAW,QAAc;EAC7B,IAAI;GACF,OAAO,KAAK,UAAU,GAAO,MAAM,CAAC;EACtC,QAAQ;GACN,OAAO,KAAK,UAAU,EACpB,OAAO,EAAE,0CAA0C,EACrD,CAAC;EACH;CACF,GAAG,CAAC,GAAG,CAAK,CAAC,GAEP,IAAa,EAAY,YAAY;EACzC,IAAI,IAAK;EACT,IAAI;GACF,AAAI,OAAO,YAAc,QACvB,MAAM,UAAU,UAAU,UAAU,CAAQ,GAC5C,IAAK;EAET,QAAQ;GACN,IAAK;EACP;EAMA,AAJA,AACE,MAAK,EAAoB,CAAQ,GAG/B,MACF,EAAU,EAAI,GACd,OAAO,iBAAiB;GACtB,EAAU,EAAK;EACjB,GAAG,IAAI;CAEX,GAAG,CAAC,CAAQ,CAAC,GAEP,IAAW,QAAc;EACzB,SAAa,MAGjB,OAAO,EAAE,aAAU;CACrB,GAAG,CAAC,CAAS,CAAC,GAEV,IAAkB;CACtB,AAAI,MACF,IAAkB;CAGpB,IAAI,IAAsB;CAK1B,OAJI,MACF,IAAsB,IAItB,kBAAC,OAAD;EAAK,WAAW,EAAG,GAAkB,CAAS;YAA9C,CACE,kBAAC,OAAD;GAAK,WAAW;aAAhB,CACE,kBAAC,QAAD;IAAM,WAAW;cAAe;GAAoB,CAAA,GACpD,kBAAC,OAAD;IAAK,WAAW;cAAhB,CACE,kBAAC,GAAD;KACE,MAAK;KACL,SAAQ;KACR,MAAK;KACL,eAAe;MACb,EAAW,EAAE,YAAY,CAAC,CAAC;KAC7B;eAEC;IACK,CAAA,GACR,kBAAC,GAAD;KACE,MAAK;KACL,SAAQ;KACR,MAAK;KACL,eAAe;MACb,GAAgB,MACP,CAAC,CACT;KACH;eAEC;IACK,CAAA,CACL;KACF;MACL,kBAAC,OAAD;GACE,WAAW,EAAG,GAAY,GAAG,IAAmB,EAAY,CAAC;GAC7D,OAAO;aAEN;EACE,CAAA,CACF;;AAET"}
|
|
@@ -1,15 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
function e(e) {
|
|
3
|
-
try {
|
|
4
|
-
let t = document.createElement("textarea");
|
|
5
|
-
t.value = e, t.setAttribute("readonly", "true"), t.style.position = "fixed", t.style.top = "-1000px", t.style.left = "-1000px", document.body.appendChild(t), t.select();
|
|
6
|
-
let n = document.execCommand("copy");
|
|
7
|
-
return document.body.removeChild(t), n;
|
|
8
|
-
} catch {
|
|
9
|
-
return !1;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
//#endregion
|
|
1
|
+
import { copyWithExecCommand as e } from "../../shared/clipboard.js";
|
|
13
2
|
export { e as copyWithExecCommand };
|
|
14
|
-
|
|
15
|
-
//# sourceMappingURL=copyWithExecCommand.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { copyRichClipboard as e, copyTextToClipboard as t } from "../shared/clipboard.js";
|
|
2
|
+
import { useCallback as n, useEffect as r, useRef as i, useState as a } from "react";
|
|
3
|
+
//#region src/hooks/useClipboardCopy.ts
|
|
4
|
+
function o(o = 2e3) {
|
|
5
|
+
let [s, c] = a(null), l = i(null), u = n(() => {
|
|
6
|
+
l.current != null && (window.clearTimeout(l.current), l.current = null);
|
|
7
|
+
}, []);
|
|
8
|
+
r(() => () => {
|
|
9
|
+
u();
|
|
10
|
+
}, [u]);
|
|
11
|
+
let d = n((e) => {
|
|
12
|
+
e != null && (c(e), u(), l.current = window.setTimeout(() => {
|
|
13
|
+
c(null), l.current = null;
|
|
14
|
+
}, o));
|
|
15
|
+
}, [u, o]);
|
|
16
|
+
return {
|
|
17
|
+
copiedKey: s,
|
|
18
|
+
copyText: n(async (e, n) => {
|
|
19
|
+
let r = await t(e);
|
|
20
|
+
return r && d(n), r;
|
|
21
|
+
}, [d]),
|
|
22
|
+
copyRich: n(async (t, n) => {
|
|
23
|
+
let r = await e(t);
|
|
24
|
+
return r && d(n), r;
|
|
25
|
+
}, [d])
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { o as default, o as useClipboardCopy };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=useClipboardCopy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useClipboardCopy.js","names":[],"sources":["../../../src/hooks/useClipboardCopy.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport {\n copyRichClipboard,\n copyTextToClipboard,\n type RichClipboardContent,\n} from '../shared/clipboard.js';\n\nexport type UseClipboardCopyResult = {\n copiedKey: string | null;\n copyText: (value: string, key?: string) => Promise<boolean>;\n copyRich: (content: RichClipboardContent, key?: string) => Promise<boolean>;\n};\n\n/** Copy text or rich content while tracking a short-lived copied state. */\nexport function useClipboardCopy(timeoutMs = 2000): UseClipboardCopyResult {\n const [copiedKey, setCopiedKey] = useState<string | null>(null);\n const timeoutRef = useRef<number | null>(null);\n\n const clearTimer = useCallback((): void => {\n if (timeoutRef.current != null) {\n window.clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n }, []);\n\n useEffect(() => {\n return () => {\n clearTimer();\n };\n }, [clearTimer]);\n\n const markCopied = useCallback(\n (key?: string): void => {\n if (key == null) {\n return;\n }\n\n setCopiedKey(key);\n clearTimer();\n timeoutRef.current = window.setTimeout(() => {\n setCopiedKey(null);\n timeoutRef.current = null;\n }, timeoutMs);\n },\n [clearTimer, timeoutMs],\n );\n\n const copyText = useCallback(\n async (value: string, key?: string): Promise<boolean> => {\n const copied = await copyTextToClipboard(value);\n if (copied) {\n markCopied(key);\n }\n return copied;\n },\n [markCopied],\n );\n\n const copyRich = useCallback(\n async (content: RichClipboardContent, key?: string): Promise<boolean> => {\n const copied = await copyRichClipboard(content);\n if (copied) {\n markCopied(key);\n }\n return copied;\n },\n [markCopied],\n );\n\n return { copiedKey, copyText, copyRich };\n}\n\nexport default useClipboardCopy;\n"],"mappings":";;;AAeA,SAAgB,EAAiB,IAAY,KAA8B;CACzE,IAAM,CAAC,GAAW,KAAgB,EAAwB,IAAI,GACxD,IAAa,EAAsB,IAAI,GAEvC,IAAa,QAAwB;EACzC,AAAI,EAAW,WAAW,SACxB,OAAO,aAAa,EAAW,OAAO,GACtC,EAAW,UAAU;CAEzB,GAAG,CAAC,CAAC;CAEL,cACe;EACX,EAAW;CACb,GACC,CAAC,CAAU,CAAC;CAEf,IAAM,IAAa,GAChB,MAAuB;EAClB,KAAO,SAIX,EAAa,CAAG,GAChB,EAAW,GACX,EAAW,UAAU,OAAO,iBAAiB;GAE3C,AADA,EAAa,IAAI,GACjB,EAAW,UAAU;EACvB,GAAG,CAAS;CACd,GACA,CAAC,GAAY,CAAS,CACxB;CAwBA,OAAO;EAAE;EAAW,UAtBH,EACf,OAAO,GAAe,MAAmC;GACvD,IAAM,IAAS,MAAM,EAAoB,CAAK;GAI9C,OAHI,KACF,EAAW,CAAG,GAET;EACT,GACA,CAAC,CAAU,CAcO;EAAU,UAXb,EACf,OAAO,GAA+B,MAAmC;GACvE,IAAM,IAAS,MAAM,EAAkB,CAAO;GAI9C,OAHI,KACF,EAAW,CAAG,GAET;EACT,GACA,CAAC,CAAU,CAGiB;CAAS;AACzC"}
|