@plumile/ui 0.1.145 → 0.1.147

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.
Files changed (94) hide show
  1. package/README.md +3 -0
  2. package/lib/esm/admin/organisms/admin_sidebar/adminSidebar.css.js +0 -2
  3. package/lib/esm/admin/theme/adminSurface.css.js +2 -0
  4. package/lib/esm/atomic/molecules/form_grid/FormGrid.css.js +8 -0
  5. package/lib/esm/atomic/molecules/form_grid/FormGrid.css.js.map +1 -0
  6. package/lib/esm/atomic/molecules/form_grid/FormGrid.js +16 -0
  7. package/lib/esm/atomic/molecules/form_grid/FormGrid.js.map +1 -0
  8. package/lib/esm/atomic/molecules/markdown/components/MarkdownArticleContainer.css.js +1 -0
  9. package/lib/esm/atomic/molecules/markdown/components/MarkdownCodeCopyButton.js +19 -35
  10. package/lib/esm/atomic/molecules/markdown/components/MarkdownCodeCopyButton.js.map +1 -1
  11. package/lib/esm/atomic/molecules/markdown/components/MarkdownLink.css.js +0 -1
  12. package/lib/esm/backoffice/atoms/copyable_text/CopyableText.js +22 -42
  13. package/lib/esm/backoffice/atoms/copyable_text/CopyableText.js.map +1 -1
  14. package/lib/esm/backoffice/molecules/backoffice_json_viewer/BackofficeJsonViewer.js +2 -1
  15. package/lib/esm/backoffice/molecules/backoffice_json_viewer/BackofficeJsonViewer.js.map +1 -1
  16. package/lib/esm/backoffice/shared/copyWithExecCommand.js +1 -14
  17. package/lib/esm/components/feedback/OperationFeedback.js +21 -14
  18. package/lib/esm/components/feedback/OperationFeedback.js.map +1 -1
  19. package/lib/esm/components/layout/top_navigation_shell/TopNavigationShell.css.js +17 -0
  20. package/lib/esm/components/layout/top_navigation_shell/TopNavigationShell.css.js.map +1 -0
  21. package/lib/esm/components/layout/top_navigation_shell/TopNavigationShell.js +24 -0
  22. package/lib/esm/components/layout/top_navigation_shell/TopNavigationShell.js.map +1 -0
  23. package/lib/esm/hooks/useClipboardCopy.js +31 -0
  24. package/lib/esm/hooks/useClipboardCopy.js.map +1 -0
  25. package/lib/esm/index.js +230 -226
  26. package/lib/esm/node_modules/@shikijs/core/dist/index.js +99 -96
  27. package/lib/esm/node_modules/@shikijs/core/dist/index.js.map +1 -1
  28. package/lib/esm/node_modules/@shikijs/core/node_modules/@shikijs/types/dist/index.js.map +1 -1
  29. package/lib/esm/node_modules/@shikijs/primitive/dist/index.js +91 -85
  30. package/lib/esm/node_modules/@shikijs/primitive/dist/index.js.map +1 -1
  31. package/lib/esm/node_modules/@shikijs/primitive/node_modules/@shikijs/types/dist/index.js.map +1 -1
  32. package/lib/esm/node_modules/cytoscape/dist/cytoscape.esm.js +1 -1
  33. package/lib/esm/node_modules/cytoscape/dist/cytoscape.esm.js.map +1 -1
  34. package/lib/esm/node_modules/dompurify/dist/purify.es.js +173 -166
  35. package/lib/esm/node_modules/dompurify/dist/purify.es.js.map +1 -1
  36. package/lib/esm/node_modules/react-shiki/dist/index.js +1 -1
  37. package/lib/esm/node_modules/shiki/dist/bundle-full.js +1 -1
  38. package/lib/esm/node_modules/shiki/dist/bundle-full.js.map +1 -1
  39. package/lib/esm/node_modules/shiki/dist/{chunk-CtajNgzt.js → chunk-D1SwGrFN.js} +2 -2
  40. package/lib/esm/node_modules/shiki/dist/chunk-D1SwGrFN.js.map +1 -0
  41. package/lib/esm/node_modules/shiki/dist/engine-oniguruma.js +1 -1
  42. package/lib/esm/node_modules/shiki/dist/engine-oniguruma.js.map +1 -1
  43. package/lib/esm/node_modules/shiki/dist/{langs-bundle-full-DfKZStlK.js → langs-bundle-full-YTHnHqaM.js} +2 -2
  44. package/lib/esm/node_modules/shiki/dist/{langs-bundle-full-DfKZStlK.js.map → langs-bundle-full-YTHnHqaM.js.map} +1 -1
  45. package/lib/esm/node_modules/shiki/dist/themes.js.map +1 -1
  46. package/lib/esm/node_modules/shiki/node_modules/@shikijs/engine-oniguruma/dist/index.js.map +1 -1
  47. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/apex.js +1 -1
  48. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/apex.js.map +1 -1
  49. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/c3.js +1 -1
  50. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/c3.js.map +1 -1
  51. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/csharp.js +1 -1
  52. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/csharp.js.map +1 -1
  53. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/hack.js +1 -1
  54. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/hack.js.map +1 -1
  55. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/julia.js +1 -1
  56. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/julia.js.map +1 -1
  57. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/just.js +1 -1
  58. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/just.js.map +1 -1
  59. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/latex.js +1 -1
  60. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/latex.js.map +1 -1
  61. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/luau.js +1 -1
  62. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/luau.js.map +1 -1
  63. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/php.js +1 -1
  64. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/php.js.map +1 -1
  65. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/sql.js +1 -1
  66. package/lib/esm/node_modules/shiki/node_modules/@shikijs/langs/dist/sql.js.map +1 -1
  67. package/lib/esm/node_modules/shiki/node_modules/@shikijs/themes/dist/vesper.js +1 -1
  68. package/lib/esm/node_modules/shiki/node_modules/@shikijs/themes/dist/vesper.js.map +1 -1
  69. package/lib/esm/shared/clipboard.js +55 -0
  70. package/lib/esm/shared/clipboard.js.map +1 -0
  71. package/lib/esm/style.css +1 -1
  72. package/lib/types/atomic/molecules/form_grid/FormGrid.css.d.ts +3 -0
  73. package/lib/types/atomic/molecules/form_grid/FormGrid.css.d.ts.map +1 -0
  74. package/lib/types/atomic/molecules/form_grid/FormGrid.d.ts +9 -0
  75. package/lib/types/atomic/molecules/form_grid/FormGrid.d.ts.map +1 -0
  76. package/lib/types/atomic/molecules/markdown/components/MarkdownCodeCopyButton.d.ts.map +1 -1
  77. package/lib/types/backoffice/atoms/copyable_text/CopyableText.d.ts.map +1 -1
  78. package/lib/types/backoffice/shared/copyWithExecCommand.d.ts +1 -1
  79. package/lib/types/backoffice/shared/copyWithExecCommand.d.ts.map +1 -1
  80. package/lib/types/components/feedback/OperationFeedback.d.ts +3 -2
  81. package/lib/types/components/feedback/OperationFeedback.d.ts.map +1 -1
  82. package/lib/types/components/layout/top_navigation_shell/TopNavigationShell.css.d.ts +8 -0
  83. package/lib/types/components/layout/top_navigation_shell/TopNavigationShell.css.d.ts.map +1 -0
  84. package/lib/types/components/layout/top_navigation_shell/TopNavigationShell.d.ts +18 -0
  85. package/lib/types/components/layout/top_navigation_shell/TopNavigationShell.d.ts.map +1 -0
  86. package/lib/types/hooks/useClipboardCopy.d.ts +9 -0
  87. package/lib/types/hooks/useClipboardCopy.d.ts.map +1 -0
  88. package/lib/types/index.d.ts +4 -0
  89. package/lib/types/index.d.ts.map +1 -1
  90. package/lib/types/shared/clipboard.d.ts +9 -0
  91. package/lib/types/shared/clipboard.d.ts.map +1 -0
  92. package/package.json +4 -4
  93. package/lib/esm/backoffice/shared/copyWithExecCommand.js.map +0 -1
  94. 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.
@@ -4,8 +4,6 @@
4
4
  /* empty css */
5
5
  /* empty css */
6
6
  /* empty css */
7
- /* empty css */
8
- /* empty css */
9
7
  /* empty css */
10
8
  import { createRuntimeFn as e } from "@vanilla-extract/recipes/createRuntimeFn";
11
9
  //#region src/admin/organisms/admin_sidebar/adminSidebar.css.ts
@@ -6,6 +6,8 @@
6
6
  /* empty css */
7
7
  /* empty css */
8
8
  /* empty css */
9
+ /* empty css */
10
+ /* empty css */
9
11
  import { createRuntimeFn as e } from "@vanilla-extract/recipes/createRuntimeFn";
10
12
  //#region src/admin/theme/adminSurface.css.ts
11
13
  var t = e({
@@ -0,0 +1,8 @@
1
+ /* empty css */
2
+ /* empty css */
3
+ //#region src/atomic/molecules/form_grid/FormGrid.css.ts
4
+ var e = "var(--_1nx8f960)", t = "_1nx8f962 _1nx8f961 txvbqbfq0 txvbqbhdy txvbqb19uf";
5
+ //#endregion
6
+ export { t as grid, e as minColumnWidthVar };
7
+
8
+ //# sourceMappingURL=FormGrid.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormGrid.css.js","names":[],"sources":["../../../../../src/atomic/molecules/form_grid/FormGrid.css.ts"],"sourcesContent":["import { createVar, style } from '@vanilla-extract/css';\n\nimport { sprinkles } from '../../../theme/sprinkles.css.js';\n\nexport const minColumnWidthVar = createVar();\n\nexport const grid = style([\n sprinkles({\n display: 'grid',\n gap: 3,\n width: 'full',\n }),\n {\n gridTemplateColumns: `repeat(auto-fit, minmax(${minColumnWidthVar}, 1fr))`,\n },\n]);\n"],"mappings":""}
@@ -0,0 +1,16 @@
1
+ import { cx as e } from "../../../theme/tools.js";
2
+ import { grid as t, minColumnWidthVar as n } from "./FormGrid.css.js";
3
+ import { jsx as r } from "react/jsx-runtime";
4
+ //#region src/atomic/molecules/form_grid/FormGrid.tsx
5
+ var i = ({ children: i, className: a, minColumnWidth: o = "220px" }) => {
6
+ let s = { [n]: o };
7
+ return /* @__PURE__ */ r("div", {
8
+ className: e(t, a),
9
+ style: s,
10
+ children: i
11
+ });
12
+ };
13
+ //#endregion
14
+ export { i as FormGrid, i as default };
15
+
16
+ //# sourceMappingURL=FormGrid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormGrid.js","names":[],"sources":["../../../../../src/atomic/molecules/form_grid/FormGrid.tsx"],"sourcesContent":["import { type CSSProperties, type JSX, type ReactNode } from 'react';\n\nimport { cx } from '../../../theme/tools.js';\n\nimport * as styles from './FormGrid.css.js';\n\nexport type FormGridProps = {\n children: ReactNode;\n minColumnWidth?: string;\n className?: string;\n};\n\nexport const FormGrid = ({\n children,\n className,\n minColumnWidth = '220px',\n}: FormGridProps): JSX.Element => {\n const style = {\n [styles.minColumnWidthVar]: minColumnWidth,\n } as CSSProperties;\n\n return (\n <div className={cx(styles.grid, className)} style={style}>\n {children}\n </div>\n );\n};\n\nexport default FormGrid;\n"],"mappings":";;;;AAYA,IAAa,KAAY,EACvB,aACA,cACA,oBAAiB,cACe;CAChC,IAAM,IAAQ,GACX,IAA2B,EAC9B;CAEA,OACE,kBAAC,OAAD;EAAK,WAAW,EAAG,GAAa,CAAS;EAAU;EAChD;CACE,CAAA;AAET"}
@@ -1,4 +1,5 @@
1
1
  /* empty css */
2
+ /* empty css */
2
3
  /* empty css */
3
4
  //#region src/atomic/molecules/markdown/components/MarkdownArticleContainer.css.ts
4
5
  var e = "_7ez1431 _7ez1430 txvbqbfpn txvbqbh4x txvbqbheb";
@@ -1,46 +1,30 @@
1
1
  import { useUiTranslation as e } from "../../../../i18n/useUiTranslation.js";
2
- import { MarkdownCopySuccessSvg as t } from "../../../../icons/markdown/MarkdownCopySuccessSvg.js";
3
- import { MarkdownCopySvg as n } from "../../../../icons/markdown/MarkdownCopySvg.js";
4
- import { copyButton as r, icon as i, label as a } from "./MarkdownCodeCopyButton.css.js";
5
- import { useCallback as o, useEffect as s, useRef as c, useState as l } from "react";
6
- import { jsx as u, jsxs as d } from "react/jsx-runtime";
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 f = ({ code: f }) => {
9
- let { t: p } = e(), [m, h] = l(!1), g = c(null);
10
- s(() => () => {
11
- g.current != null && window.clearTimeout(g.current);
12
- }, []);
13
- let _ = o(async () => {
14
- try {
15
- let e;
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
- _().catch(() => {});
17
+ f(l, l).catch(() => {});
34
18
  },
35
- title: v,
19
+ title: m,
36
20
  type: "button",
37
- children: [y, /* @__PURE__ */ u("span", {
38
- className: a,
39
- children: b
21
+ children: [h, /* @__PURE__ */ s("span", {
22
+ className: o,
23
+ children: g
40
24
  })]
41
25
  });
42
26
  };
43
27
  //#endregion
44
- export { f as MarkdownCodeCopyButton };
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 { useCallback, useEffect, useRef, useState, type JSX } from 'react';\n\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 [copied, setCopied] = useState(false);\n const timeoutRef = useRef<number | null>(null);\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current != null) {\n window.clearTimeout(timeoutRef.current);\n }\n };\n }, []);\n\n const handleCopy = useCallback(async () => {\n try {\n let clipboard: Clipboard | undefined;\n if (typeof navigator !== 'undefined') {\n clipboard = navigator.clipboard;\n }\n if (clipboard != null && typeof clipboard.writeText === 'function') {\n await clipboard.writeText(code);\n } else {\n const textarea = document.createElement('textarea');\n textarea.value = code;\n textarea.setAttribute('readonly', '');\n textarea.style.position = 'absolute';\n textarea.style.left = '-9999px';\n document.body.appendChild(textarea);\n textarea.select();\n document.execCommand('copy');\n document.body.removeChild(textarea);\n }\n setCopied(true);\n if (timeoutRef.current != null) {\n window.clearTimeout(timeoutRef.current);\n }\n timeoutRef.current = window.setTimeout(() => {\n setCopied(false);\n timeoutRef.current = null;\n }, 2000);\n } catch {\n // silently ignore copy failures\n }\n }, [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 handleCopy().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":";;;;;;;AAgBA,IAAa,KAA0B,EAAE,cAA+B;CACtE,IAAM,EAAE,SAAM,EAAiB,GACzB,CAAC,GAAQ,KAAa,EAAS,EAAK,GACpC,IAAa,EAAsB,IAAI;CAE7C,cACe;EACX,AAAI,EAAW,WAAW,QACxB,OAAO,aAAa,EAAW,OAAO;CAE1C,GACC,CAAC,CAAC;CAEL,IAAM,IAAa,EAAY,YAAY;EACzC,IAAI;GACF,IAAI;GAIJ,IAHI,OAAO,YAAc,QACvB,IAAY,UAAU,YAEpB,KAAa,QAAQ,OAAO,EAAU,aAAc,YACtD,MAAM,EAAU,UAAU,CAAI;QACzB;IACL,IAAM,IAAW,SAAS,cAAc,UAAU;IAQlD,AAPA,EAAS,QAAQ,GACjB,EAAS,aAAa,YAAY,EAAE,GACpC,EAAS,MAAM,WAAW,YAC1B,EAAS,MAAM,OAAO,WACtB,SAAS,KAAK,YAAY,CAAQ,GAClC,EAAS,OAAO,GAChB,SAAS,YAAY,MAAM,GAC3B,SAAS,KAAK,YAAY,CAAQ;GACpC;GAKA,AAJA,EAAU,EAAI,GACV,EAAW,WAAW,QACxB,OAAO,aAAa,EAAW,OAAO,GAExC,EAAW,UAAU,OAAO,iBAAiB;IAE3C,AADA,EAAU,EAAK,GACf,EAAW,UAAU;GACvB,GAAG,GAAI;EACT,QAAQ,CAER;CACF,GAAG,CAAC,CAAI,CAAC,GAEL,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,EAAW,EAAE,YAAY,CAEzB,CAAC;EACH;EACA,OAAO;EACP,MAAK;YARP,CAUG,GACD,kBAAC,QAAD;GAAM,WAAW;aAAQ;EAAgB,CAAA,CACnC;;AAEZ"}
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,5 +1,4 @@
1
1
  /* empty css */
2
- /* empty css */
3
2
  /* empty css */
4
3
  //#region src/atomic/molecules/markdown/components/MarkdownLink.css.ts
5
4
  var e = "xtwkbg1 xtwkbg0 txvbqb3h txvbqb6f txvbqb7h txvbqb76 txvbqb7v txvbqb1ara", t = "xtwkbg3 xtwkbg1 xtwkbg0 txvbqb3h txvbqb6f txvbqb7h txvbqb76 txvbqb7v txvbqb1ara xtwkbg2 txvbqbey txvbqbfqq txvbqbhd8", n = "xtwkbg5 xtwkbg4 txvbqbfqq", r = "xtwkbg7 xtwkbg6 txvbqbf txvbqb3f";
@@ -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 { copyWithExecCommand as n } from "../../shared/copyWithExecCommand.js";
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 { useCallback as s, useEffect as c, useMemo as l, useRef as u, useState as d } from "react";
6
- import { jsx as f, jsxs as p } from "react/jsx-runtime";
7
- import { useTranslation as m } from "react-i18next";
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 h = ({ value: h, copyValue: g, className: _, truncate: v = !0, copyLabel: y, copiedLabel: b }) => {
10
- let { t: x } = m("ui", { useSuspense: !1 }), [S, C] = d(!1), w = u(null), T = y ?? x("backoffice.copyableText.copy", { defaultValue: "Copy" }), E = b ?? x("backoffice.copyableText.copied", { defaultValue: "Copied" }), D = g ?? h, O = l(() => {
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 v || (t = o), e(a, t, _);
13
- }, [_, v]), k = s(() => {
14
- w.current != null && (window.clearTimeout(w.current), w.current = null);
15
- }, []);
16
- c(() => () => {
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: E
41
- })), /* @__PURE__ */ p("span", {
20
+ children: x
21
+ })), /* @__PURE__ */ l("span", {
42
22
  className: i,
43
23
  children: [
44
- /* @__PURE__ */ f("span", {
45
- className: O,
46
- title: h,
47
- children: h
24
+ /* @__PURE__ */ c("span", {
25
+ className: T,
26
+ title: d,
27
+ children: d
48
28
  }),
49
- /* @__PURE__ */ f(t, {
29
+ /* @__PURE__ */ c(t, {
50
30
  type: "button",
51
31
  variant: "secondary",
52
32
  size: "small",
53
- onClick: j,
54
- children: T
33
+ onClick: E,
34
+ children: b
55
35
  }),
56
- M
36
+ D
57
37
  ]
58
38
  });
59
39
  };
60
40
  //#endregion
61
- export { h as CopyableText, h as default };
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 {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type JSX,\n} 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 './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 [copied, setCopied] = useState(false);\n const timeoutRef = useRef<number | null>(null);\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\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 clearTimer = useCallback(() => {\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 handleCopy = useCallback(async () => {\n clearTimer();\n let ok = false;\n try {\n if (typeof navigator !== 'undefined') {\n const { clipboard } = navigator;\n await clipboard.writeText(resolvedCopyValue);\n ok = true;\n }\n } catch {\n ok = false;\n }\n\n if (!ok) {\n ok = copyWithExecCommand(resolvedCopyValue);\n }\n\n if (ok) {\n setCopied(true);\n timeoutRef.current = window.setTimeout(() => {\n setCopied(false);\n timeoutRef.current = null;\n }, 1400);\n }\n }, [clearTimer, resolvedCopyValue]);\n\n const handleCopyClick = () => {\n handleCopy().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":";;;;;;;;AAyBA,IAAa,KAAgB,EAC3B,OAAA,GACA,cACA,cACA,cAAW,IACX,cACA,qBACoC;CACpC,IAAM,EAAE,SAAM,EAAe,MAAM,EAAE,aAAa,GAAM,CAAC,GACnD,CAAC,GAAQ,KAAa,EAAS,EAAK,GACpC,IAAa,EAAsB,IAAI,GACvC,IACJ,KACA,EAAE,gCAAgC,EAChC,cAAc,OAChB,CAAC,GACG,IACJ,KACA,EAAE,kCAAkC,EAClC,cAAc,SAChB,CAAC,GAEG,IAAoB,KAAa,GAEjC,IAAmB,QAAc;EACrC,IAAI,IAAiC;EAIrC,OAHK,MACH,IAAkB,IAEb,EAAG,GAAc,GAAiB,CAAS;CACpD,GAAG,CAAC,GAAW,CAAQ,CAAC,GAElB,IAAa,QAAkB;EACnC,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,EAAY,YAAY;EACzC,EAAW;EACX,IAAI,IAAK;EACT,IAAI;GACF,IAAI,OAAO,YAAc,KAAa;IACpC,IAAM,EAAE,iBAAc;IAEtB,AADA,MAAM,EAAU,UAAU,CAAiB,GAC3C,IAAK;GACP;EACF,QAAQ;GACN,IAAK;EACP;EAMA,AAJA,AACE,MAAK,EAAoB,CAAiB,GAGxC,MACF,EAAU,EAAI,GACd,EAAW,UAAU,OAAO,iBAAiB;GAE3C,AADA,EAAU,EAAK,GACf,EAAW,UAAU;EACvB,GAAG,IAAI;CAEX,GAAG,CAAC,GAAY,CAAiB,CAAC,GAE5B,UAAwB;EAC5B,EAAW,EAAE,YAAY,CAAC,CAAC;CAC7B,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
+ {"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 "../../shared/copyWithExecCommand.js";
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":";;;;;;;;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
+ {"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
- //#region src/backoffice/shared/copyWithExecCommand.ts
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
@@ -3,24 +3,31 @@ import { InlineBanner as t } from "./InlineBanner.js";
3
3
  import { stack as n } from "./OperationFeedback.css.js";
4
4
  import { jsx as r, jsxs as i } from "react/jsx-runtime";
5
5
  //#region src/components/feedback/OperationFeedback.tsx
6
- var a = ({ errorMessage: a = null, successMessage: o = null, retryLabel: s, onRetry: c }) => {
7
- if (a == null && o == null) return null;
8
- let l = null;
9
- return a != null && c != null && s != null && (l = /* @__PURE__ */ r(e, {
6
+ var a = ({ errorMessage: a = null, neutralMessage: o = null, successMessage: s = null, retryLabel: c, onRetry: l }) => {
7
+ if (a == null && o == null && s == null) return null;
8
+ let u = null;
9
+ return a != null && l != null && c != null && (u = /* @__PURE__ */ r(e, {
10
10
  type: "button",
11
11
  variant: "secondary",
12
- onClick: c,
13
- children: s
12
+ onClick: l,
13
+ children: c
14
14
  })), /* @__PURE__ */ i("div", {
15
15
  className: n,
16
- children: [a != null && /* @__PURE__ */ r(t, {
17
- tone: "danger",
18
- actions: l,
19
- children: a
20
- }), o != null && /* @__PURE__ */ r(t, {
21
- tone: "success",
22
- children: o
23
- })]
16
+ children: [
17
+ a != null && /* @__PURE__ */ r(t, {
18
+ tone: "danger",
19
+ actions: u,
20
+ children: a
21
+ }),
22
+ s != null && /* @__PURE__ */ r(t, {
23
+ tone: "success",
24
+ children: s
25
+ }),
26
+ o != null && /* @__PURE__ */ r(t, {
27
+ tone: "info",
28
+ children: o
29
+ })
30
+ ]
24
31
  });
25
32
  }, o = a;
26
33
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"OperationFeedback.js","names":[],"sources":["../../../../src/components/feedback/OperationFeedback.tsx"],"sourcesContent":["import { type JSX } from 'react';\n\nimport { Button } from '../../atomic/atoms/button/Button.js';\nimport { InlineBanner } from './InlineBanner.js';\n\nimport * as styles from './OperationFeedback.css.js';\n\nexport type OperationFeedbackProps = {\n errorMessage?: string | null;\n successMessage?: string | null;\n retryLabel?: string;\n onRetry?: () => void;\n};\n\nexport const OperationFeedback = ({\n errorMessage = null,\n successMessage = null,\n retryLabel,\n onRetry,\n}: OperationFeedbackProps): JSX.Element | null => {\n if (errorMessage == null && successMessage == null) {\n return null;\n }\n\n let retryAction: JSX.Element | null = null;\n if (errorMessage != null && onRetry != null && retryLabel != null) {\n retryAction = (\n <Button type=\"button\" variant=\"secondary\" onClick={onRetry}>\n {retryLabel}\n </Button>\n );\n }\n\n return (\n <div className={styles.stack}>\n {errorMessage != null && (\n <InlineBanner tone=\"danger\" actions={retryAction}>\n {errorMessage}\n </InlineBanner>\n )}\n {successMessage != null && (\n <InlineBanner tone=\"success\">{successMessage}</InlineBanner>\n )}\n </div>\n );\n};\n\nexport const MutationFeedback = OperationFeedback;\n\nexport default OperationFeedback;\n"],"mappings":";;;;;AAcA,IAAa,KAAqB,EAChC,kBAAe,MACf,oBAAiB,MACjB,eACA,iBACgD;CAChD,IAAI,KAAgB,QAAQ,KAAkB,MAC5C,OAAO;CAGT,IAAI,IAAkC;CAStC,OARI,KAAgB,QAAQ,KAAW,QAAQ,KAAc,SAC3D,IACE,kBAAC,GAAD;EAAQ,MAAK;EAAS,SAAQ;EAAY,SAAS;YAChD;CACK,CAAA,IAKV,kBAAC,OAAD;EAAK,WAAW;YAAhB,CACG,KAAgB,QACf,kBAAC,GAAD;GAAc,MAAK;GAAS,SAAS;aAClC;EACW,CAAA,GAEf,KAAkB,QACjB,kBAAC,GAAD;GAAc,MAAK;aAAW;EAA6B,CAAA,CAE1D;;AAET,GAEa,IAAmB"}
1
+ {"version":3,"file":"OperationFeedback.js","names":[],"sources":["../../../../src/components/feedback/OperationFeedback.tsx"],"sourcesContent":["import { type JSX } from 'react';\n\nimport { Button } from '../../atomic/atoms/button/Button.js';\nimport { InlineBanner } from './InlineBanner.js';\n\nimport * as styles from './OperationFeedback.css.js';\n\nexport type OperationFeedbackProps = {\n errorMessage?: string | null;\n neutralMessage?: string | null;\n successMessage?: string | null;\n retryLabel?: string;\n onRetry?: () => void;\n};\n\nexport const OperationFeedback = ({\n errorMessage = null,\n neutralMessage = null,\n successMessage = null,\n retryLabel,\n onRetry,\n}: OperationFeedbackProps): JSX.Element | null => {\n if (\n errorMessage == null &&\n neutralMessage == null &&\n successMessage == null\n ) {\n return null;\n }\n\n let retryAction: JSX.Element | null = null;\n if (errorMessage != null && onRetry != null && retryLabel != null) {\n retryAction = (\n <Button type=\"button\" variant=\"secondary\" onClick={onRetry}>\n {retryLabel}\n </Button>\n );\n }\n\n return (\n <div className={styles.stack}>\n {errorMessage != null && (\n <InlineBanner tone=\"danger\" actions={retryAction}>\n {errorMessage}\n </InlineBanner>\n )}\n {successMessage != null && (\n <InlineBanner tone=\"success\">{successMessage}</InlineBanner>\n )}\n {neutralMessage != null && (\n <InlineBanner tone=\"info\">{neutralMessage}</InlineBanner>\n )}\n </div>\n );\n};\n\nexport const MutationFeedback = OperationFeedback;\n\nexport default OperationFeedback;\n"],"mappings":";;;;;AAeA,IAAa,KAAqB,EAChC,kBAAe,MACf,oBAAiB,MACjB,oBAAiB,MACjB,eACA,iBACgD;CAChD,IACE,KAAgB,QAChB,KAAkB,QAClB,KAAkB,MAElB,OAAO;CAGT,IAAI,IAAkC;CAStC,OARI,KAAgB,QAAQ,KAAW,QAAQ,KAAc,SAC3D,IACE,kBAAC,GAAD;EAAQ,MAAK;EAAS,SAAQ;EAAY,SAAS;YAChD;CACK,CAAA,IAKV,kBAAC,OAAD;EAAK,WAAW;YAAhB;GACG,KAAgB,QACf,kBAAC,GAAD;IAAc,MAAK;IAAS,SAAS;cAClC;GACW,CAAA;GAEf,KAAkB,QACjB,kBAAC,GAAD;IAAc,MAAK;cAAW;GAA6B,CAAA;GAE5D,KAAkB,QACjB,kBAAC,GAAD;IAAc,MAAK;cAAQ;GAA6B,CAAA;EAEvD;;AAET,GAEa,IAAmB"}
@@ -0,0 +1,17 @@
1
+ /* empty css */
2
+ /* empty css */
3
+ import { createRuntimeFn as e } from "@vanilla-extract/recipes/createRuntimeFn";
4
+ //#region src/components/layout/top_navigation_shell/TopNavigationShell.css.ts
5
+ var t = e({
6
+ defaultClassName: "_1xrtzaa3 _1xrtzaa0 txvbqbfpn txvbqbh4x txvbqbv7k txvbqb1bg1",
7
+ variantClassNames: { variant: {
8
+ default: "_1xrtzaa4 _1xrtzaa1 txvbqb1b87",
9
+ muted: "_1xrtzaa5 _1xrtzaa2 txvbqb1b89"
10
+ } },
11
+ defaultVariants: { variant: "default" },
12
+ compoundVariants: []
13
+ }), n = "_1xrtzaa6 txvbqbfvs txvbqbu86 txvbqbv7x";
14
+ //#endregion
15
+ export { n as main, t as shell };
16
+
17
+ //# sourceMappingURL=TopNavigationShell.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TopNavigationShell.css.js","names":[],"sources":["../../../../../src/components/layout/top_navigation_shell/TopNavigationShell.css.ts"],"sourcesContent":["import { recipe } from '@vanilla-extract/recipes';\n\nimport { sprinkles } from '../../../theme/sprinkles.css.js';\n\nexport const shell = recipe({\n base: sprinkles({\n display: 'flex',\n flexDirection: 'column',\n minHeight: 'screen',\n color: 'text',\n }),\n variants: {\n variant: {\n default: sprinkles({\n backgroundColor: 'background',\n }),\n muted: sprinkles({\n backgroundColor: 'backgroundSecondary',\n }),\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\nexport const main = sprinkles({\n flex: 1,\n minHeight: 0,\n minWidth: 0,\n});\n"],"mappings":""}
@@ -0,0 +1,24 @@
1
+ import { cx as e } from "../../../theme/tools.js";
2
+ import { AppHeader as t } from "../AppHeader.js";
3
+ import { main as n, shell as r } from "./TopNavigationShell.css.js";
4
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
5
+ //#region src/components/layout/top_navigation_shell/TopNavigationShell.tsx
6
+ var o = ({ actions: o, children: s, className: c, contentClassName: l, headerClassName: u, meta: d, primaryNav: f, secondaryNav: p, subtitle: m, title: h, variant: g = "default" }) => /* @__PURE__ */ a("div", {
7
+ className: e(r({ variant: g }), c),
8
+ children: [/* @__PURE__ */ i(t, {
9
+ actions: o,
10
+ className: u,
11
+ meta: d,
12
+ primaryNav: f,
13
+ secondaryNav: p,
14
+ subtitle: m,
15
+ title: h
16
+ }), /* @__PURE__ */ i("main", {
17
+ className: e(n, l),
18
+ children: s
19
+ })]
20
+ });
21
+ //#endregion
22
+ export { o as TopNavigationShell, o as default };
23
+
24
+ //# sourceMappingURL=TopNavigationShell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TopNavigationShell.js","names":[],"sources":["../../../../../src/components/layout/top_navigation_shell/TopNavigationShell.tsx"],"sourcesContent":["import { type JSX, type ReactNode } from 'react';\n\nimport { AppHeader } from '../AppHeader.js';\nimport { cx } from '../../../theme/tools.js';\n\nimport * as styles from './TopNavigationShell.css.js';\n\nexport type TopNavigationShellVariant = 'default' | 'muted';\n\nexport type TopNavigationShellProps = {\n title: ReactNode;\n subtitle?: ReactNode;\n meta?: ReactNode;\n primaryNav?: ReactNode;\n secondaryNav?: ReactNode;\n actions?: ReactNode;\n children: ReactNode;\n className?: string;\n headerClassName?: string;\n contentClassName?: string;\n variant?: TopNavigationShellVariant;\n};\n\nexport const TopNavigationShell = ({\n actions,\n children,\n className,\n contentClassName,\n headerClassName,\n meta,\n primaryNav,\n secondaryNav,\n subtitle,\n title,\n variant = 'default',\n}: TopNavigationShellProps): JSX.Element => {\n return (\n <div className={cx(styles.shell({ variant }), className)}>\n <AppHeader\n actions={actions}\n className={headerClassName}\n meta={meta}\n primaryNav={primaryNav}\n secondaryNav={secondaryNav}\n subtitle={subtitle}\n title={title}\n />\n <main className={cx(styles.main, contentClassName)}>{children}</main>\n </div>\n );\n};\n\nexport default TopNavigationShell;\n"],"mappings":";;;;;AAuBA,IAAa,KAAsB,EACjC,YACA,aACA,cACA,qBACA,oBACA,SACA,eACA,iBACA,aACA,UACA,aAAU,gBAGR,kBAAC,OAAD;CAAK,WAAW,EAAG,EAAa,EAAE,WAAQ,CAAC,GAAG,CAAS;WAAvD,CACE,kBAAC,GAAD;EACW;EACT,WAAW;EACL;EACM;EACE;EACJ;EACH;CACR,CAAA,GACD,kBAAC,QAAD;EAAM,WAAW,EAAG,GAAa,CAAgB;EAAI;CAAe,CAAA,CACjE"}
@@ -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"}