@akanjs/ui 0.9.43 → 0.9.45

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/Clipboard.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { type ReactElement } from "react";
2
+ export interface ClipboardProps {
3
+ text?: string;
4
+ clipboardMessage?: string;
5
+ className?: string;
6
+ }
7
+ export declare const Clipboard: ({ text, className }: ClipboardProps) => ReactElement;
@@ -27,5 +27,5 @@ export default function AdminPanel<T extends string, State, Input, Full extends
27
27
  id: string;
28
28
  }, Light extends {
29
29
  id: string;
30
- }, Sort extends SortType>({ sliceName, components, queryMap, summaryColumns, insightColumns, renderInsight, renderDashboard, ...props }: AdminPanelProps<T, State, Input, Full, Light, Sort>): import("react/jsx-runtime").JSX.Element;
30
+ }, Sort extends SortType>({ sliceName, components, summaryColumns, insightColumns, renderInsight, renderDashboard, ...props }: AdminPanelProps<T, State, Input, Full, Light, Sort>): import("react/jsx-runtime").JSX.Element;
31
31
  export {};
@@ -3,7 +3,7 @@ import { type Location, type TransitionStyle } from "@akanjs/client";
3
3
  import { HTMLAttributes, RefObject } from "react";
4
4
  export declare const Client: {
5
5
  (): import("react/jsx-runtime").JSX.Element;
6
- Wrapper: ({ children, theme }: ClientWrapperProps) => import("react/jsx-runtime").JSX.Element;
6
+ Wrapper: ({ children, theme, lang, dictionary }: ClientWrapperProps) => import("react/jsx-runtime").JSX.Element;
7
7
  Bridge: ({ env, lang, mePromise, selfPromise, theme, prefix, gaTrackingId }: ClientBridgeProps) => "" | import("react/jsx-runtime").JSX.Element | undefined;
8
8
  Inner: () => import("react/jsx-runtime").JSX.Element;
9
9
  NextBridge: ({ lang, prefix }: ClientNextBridgeProps) => null;
@@ -11,8 +11,14 @@ export declare const Client: {
11
11
  interface ClientWrapperProps {
12
12
  children: any;
13
13
  theme?: string;
14
+ lang?: string;
15
+ dictionary?: {
16
+ [key: string]: {
17
+ [key: string]: string;
18
+ };
19
+ };
14
20
  }
15
- export declare const ClientWrapper: ({ children, theme }: ClientWrapperProps) => import("react/jsx-runtime").JSX.Element;
21
+ export declare const ClientWrapper: ({ children, theme, lang, dictionary }: ClientWrapperProps) => import("react/jsx-runtime").JSX.Element;
16
22
  interface ClientPathWrapperProps extends Omit<HTMLAttributes<HTMLDivElement>, "style"> {
17
23
  bind?: () => any;
18
24
  wrapperRef?: RefObject<HTMLDivElement | null> | null;
@@ -0,0 +1,70 @@
1
+ "use client";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var Clipboard_exports = {};
20
+ __export(Clipboard_exports, {
21
+ Clipboard: () => Clipboard
22
+ });
23
+ module.exports = __toCommonJS(Clipboard_exports);
24
+ var import_jsx_runtime = require("react/jsx-runtime");
25
+ var import_client = require("@akanjs/client");
26
+ var import_react = require("react");
27
+ var import_fa = require("react-icons/fa");
28
+ var import_md = require("react-icons/md");
29
+ const Clipboard = ({ text, className }) => {
30
+ const [isCopied, setIsCopied] = (0, import_react.useState)(false);
31
+ (0, import_react.useEffect)(() => {
32
+ if (isCopied) {
33
+ setTimeout(() => {
34
+ setIsCopied(false);
35
+ }, 2e3);
36
+ }
37
+ }, [isCopied]);
38
+ const handleCopy = async () => {
39
+ if (!text)
40
+ return;
41
+ await navigator.clipboard.writeText(text);
42
+ setIsCopied(true);
43
+ };
44
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
45
+ "button",
46
+ {
47
+ onClick: async () => {
48
+ await handleCopy();
49
+ },
50
+ className: (0, import_client.clsx)(
51
+ "flex h-6 w-6 items-center justify-center rounded-md bg-white/30 text-white transition-all duration-300 hover:bg-white/20",
52
+ className
53
+ ),
54
+ children: [
55
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
56
+ import_fa.FaCheck,
57
+ {
58
+ className: `absolute h-4 w-4 transition-opacity duration-300 ${isCopied ? "opacity-100" : "opacity-0"}`
59
+ }
60
+ ),
61
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
62
+ import_md.MdContentCopy,
63
+ {
64
+ className: `absolute h-4 w-4 transition-opacity duration-300 ${isCopied ? "opacity-0" : "opacity-100"}`
65
+ }
66
+ )
67
+ ]
68
+ }
69
+ );
70
+ };
@@ -41,9 +41,7 @@ function QueryMaker({ className, sliceName, query }) {
41
41
  const storeDo = import_store.st.do;
42
42
  const cnst = (0, import_constant.getCnstMeta)(sliceName);
43
43
  const isModelSearchable = (0, import_constant.hasTextField)(cnst.Full);
44
- const summaryRef = cnst.Summary;
45
44
  const { subMenu, filter } = import_store.st.use.searchParams();
46
- const summaryQueryMap = (0, import_constant.getQueryMap)(summaryRef);
47
45
  const filterRef = cnst.Filter;
48
46
  const filterQueryMap = (0, import_constant.getFilterQueryMap)(filterRef);
49
47
  const defaultQuerySetting = { ...isModelSearchable ? searchQuerySetting : byStatusQuerySetting, ...query ?? {} };
@@ -51,12 +49,7 @@ function QueryMaker({ className, sliceName, query }) {
51
49
  const [querySetting, setQuerySetting] = (0, import_react.useState)(defaultQuerySetting);
52
50
  const getQuery = (0, import_react.useCallback)(
53
51
  (querySetting2) => {
54
- if (summaryQueryMap[querySetting2.queryKey]) {
55
- const query2 = typeof summaryQueryMap[querySetting2.queryKey] === "function" ? summaryQueryMap[querySetting2.queryKey]() : summaryQueryMap[querySetting2.queryKey] ?? null;
56
- if (!query2)
57
- throw new Error(`Query not found`);
58
- return query2;
59
- } else if (querySetting2.queryKey === "search") {
52
+ if (querySetting2.queryKey === "search") {
60
53
  const query2 = querySetting2.arg;
61
54
  return query2;
62
55
  } else {
@@ -91,7 +84,7 @@ function QueryMaker({ className, sliceName, query }) {
91
84
  import_Select.Select,
92
85
  {
93
86
  value: querySetting.queryKey,
94
- options: Object.keys(summaryQueryMap).map((queryKey) => ({
87
+ options: Object.keys(filterQueryMap).map((queryKey) => ({
95
88
  label: l.field("summary", queryKey),
96
89
  value: queryKey
97
90
  })),
@@ -125,7 +118,7 @@ function QueryMaker({ className, sliceName, query }) {
125
118
  ),
126
119
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_bi.BiSearch, { className: "size-4 opacity-70" })
127
120
  ] })
128
- ] }) : summaryQueryMap[querySetting.queryKey] ? null : (0, import_constant.getFilterArgMetas)(filterRef, querySetting.queryKey).map((queryArgMeta, idx) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-2", children: [
121
+ ] }) : (0, import_constant.getFilterArgMetas)(filterRef, querySetting.queryKey).map((queryArgMeta, idx) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-2", children: [
129
122
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-sm text-gray-500", children: l.qarg(sliceName, querySetting.queryKey, queryArgMeta.name) }),
130
123
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
131
124
  QueryArg,
@@ -24,14 +24,21 @@ module.exports = __toCommonJS(BottomTab_exports);
24
24
  var import_jsx_runtime = require("react/jsx-runtime");
25
25
  var import_client = require("@akanjs/client");
26
26
  var import_next = require("@akanjs/next");
27
+ var import_react = require("react");
27
28
  var import_Link = require("../Link");
28
29
  var import_BottomInset = require("./BottomInset");
29
30
  const BottomTab = ({ className, tabs, height = 64 }) => {
30
- const { lang } = (0, import_next.usePage)();
31
+ const { lang, path } = (0, import_next.usePage)();
32
+ const [isRendered, setIsRendered] = (0, import_react.useState)(false);
31
33
  const isActiveTab = (tabHref) => {
34
+ if (!isRendered)
35
+ return false;
32
36
  const locationPath = window.location.pathname.startsWith(`/${lang}`) ? window.location.pathname.slice(lang.length + 1) === "" ? "/" : window.location.pathname.slice(lang.length + 1) : window.location.pathname;
33
37
  return tabHref === "/" ? locationPath === tabHref : locationPath.startsWith(tabHref);
34
38
  };
39
+ (0, import_react.useEffect)(() => {
40
+ setIsRendered(true);
41
+ }, []);
35
42
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_BottomInset.BottomInset, { className: "h-full", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
36
43
  "div",
37
44
  {
@@ -21,17 +21,14 @@ __export(AdminPanel_exports, {
21
21
  });
22
22
  module.exports = __toCommonJS(AdminPanel_exports);
23
23
  var import_jsx_runtime = require("react/jsx-runtime");
24
- var import_common = require("@akanjs/common");
25
- var import_constant = require("@akanjs/constant");
26
24
  var import_Data = require("../Data");
27
25
  function AdminPanel({
28
26
  sliceName,
29
27
  components,
30
- queryMap = (0, import_constant.getQueryMap)((0, import_constant.getScalarModelRef)(`${(0, import_common.capitalize)(sliceName)}Summary`)),
31
28
  summaryColumns = ["totalAdmin"],
32
29
  insightColumns = ["count"],
33
30
  renderInsight = ({ insight }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Data.Data.Insight, { insight, sliceName, columns: insightColumns }),
34
- renderDashboard = ({ summary }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Data.Data.Dashboard, { summary, sliceName, columns: summaryColumns, queryMap }),
31
+ renderDashboard = ({ summary }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Data.Data.Dashboard, { summary, sliceName, columns: summaryColumns, queryMap: {} }),
35
32
  ...props
36
33
  }) {
37
34
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -32,9 +32,9 @@ const ListenerResult = ({ status, data }) => {
32
32
  const dataStr = typeof data === "object" ? JSON.stringify(data, null, 2) : data;
33
33
  const ref = (0, import_react.useRef)(null);
34
34
  (0, import_react.useEffect)(() => {
35
- if (ref.current) {
36
- ref.current.scrollTop = ref.current.scrollHeight;
37
- }
35
+ if (!ref.current)
36
+ return;
37
+ ref.current.scrollTop = ref.current.scrollHeight;
38
38
  }, [dataStr]);
39
39
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative", children: [
40
40
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -168,7 +168,7 @@ const MessageTry = ({ sigRef, gqlMeta, gqlArgMetas, uploadArgMetas }) => {
168
168
  const [uploadRequest, setUploadRequest] = (0, import_react.useState)({});
169
169
  const [stopListen, setStopListen] = (0, import_react.useState)(null);
170
170
  const [messages, setMessages] = (0, import_react.useState)("");
171
- const [response, setResponse] = (0, import_react.useState)({ status: "ready", data: null });
171
+ const [response, setResponse] = (0, import_react.useState)({ status: "ready", data: "" });
172
172
  const onSend = async () => {
173
173
  const request = { ...JSON.parse(gqlRequest), ...uploadRequest };
174
174
  const argData = [...gqlArgMetas, ...uploadArgMetas].sort((a, b) => a.idx - b.idx).map((argMeta) => request[argMeta.name]);
@@ -180,7 +180,7 @@ const MessageTry = ({ sigRef, gqlMeta, gqlArgMetas, uploadArgMetas }) => {
180
180
  const request = { ...JSON.parse(gqlRequest), ...uploadRequest };
181
181
  const fetchFn = import_signal.fetch[`listen${(0, import_common.capitalize)(gqlMeta.key)}`].bind(import_signal.fetch);
182
182
  setResponse({ status: "loading", data: messages });
183
- const stopListen2 = fetchFn(({ event, data }) => {
183
+ const stopListen2 = fetchFn((data) => {
184
184
  setMessages(
185
185
  (prev) => typeof data === "boolean" ? data : typeof data === "string" ? `${prev}
186
186
  ${data}` : typeof data === "object" ? [...prev && prev.length ? [...prev] : [], data] : data
@@ -167,18 +167,15 @@ const PubSubTry = ({ sigRef, gqlMeta, gqlArgMetas, uploadArgMetas }) => {
167
167
  const [gqlRequest, setGqlRequest] = (0, import_react.useState)(requestExample);
168
168
  const [uploadRequest, setUploadRequest] = (0, import_react.useState)({});
169
169
  const [unsubscribe, setUnsubscribe] = (0, import_react.useState)(null);
170
- const [messages, setMessages] = (0, import_react.useState)(null);
171
- const [response, setResponse] = (0, import_react.useState)({
172
- status: "ready",
173
- data: null
174
- });
170
+ const [messages, setMessages] = (0, import_react.useState)("");
171
+ const [response, setResponse] = (0, import_react.useState)({ status: "ready", data: "" });
175
172
  const onSubscribe = () => {
176
- setResponse({ status: "loading", data: null });
173
+ setResponse({ status: "loading", data: "" });
177
174
  const request = { ...JSON.parse(gqlRequest), ...uploadRequest };
178
175
  const argData = [...gqlArgMetas, ...uploadArgMetas].sort((a, b) => a.idx - b.idx).map((argMeta) => request[argMeta.name]);
179
176
  const fetchFn = import_signal.fetch[`subscribe${(0, import_common.capitalize)(gqlMeta.key)}`].bind(import_signal.fetch);
180
177
  setResponse({ status: "loading", data: messages });
181
- const unsubscribe2 = fetchFn([...argData], (data) => {
178
+ const unsubscribe2 = fetchFn(...argData, (data) => {
182
179
  setMessages(
183
180
  (prev) => typeof data === "boolean" ? data : typeof data === "string" ? `${prev}
184
181
  ${data}` : typeof data === "object" ? [
package/cjs/System/CSR.js CHANGED
@@ -24,6 +24,7 @@ __export(CSR_exports, {
24
24
  module.exports = __toCommonJS(CSR_exports);
25
25
  var import_jsx_runtime = require("react/jsx-runtime");
26
26
  var import_client = require("@akanjs/client");
27
+ var import_dictionary = require("@akanjs/dictionary");
27
28
  var import_next = require("@akanjs/next");
28
29
  var import_store = require("@akanjs/store");
29
30
  var import_ui = require("@akanjs/ui");
@@ -61,10 +62,11 @@ const CSRProvider = ({
61
62
  of,
62
63
  loader: async () => {
63
64
  const { lang } = await params;
64
- return { lang };
65
+ const dictionary = await import_dictionary.serverTranslator.getDictionary(lang);
66
+ return { lang, dictionary };
65
67
  },
66
- render: ({ lang }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
67
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Client.Client.Wrapper, { theme, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
68
+ render: ({ lang, dictionary }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
69
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Client.Client.Wrapper, { theme, lang, dictionary, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
68
70
  CSRWrapper,
69
71
  {
70
72
  className,
@@ -30,6 +30,7 @@ var import_jsx_runtime = require("react/jsx-runtime");
30
30
  var import_base = require("@akanjs/base");
31
31
  var import_client = require("@akanjs/client");
32
32
  var import_common = require("@akanjs/common");
33
+ var import_dictionary = require("@akanjs/dictionary");
33
34
  var import_next = require("@akanjs/next");
34
35
  var import_signal = require("@akanjs/signal");
35
36
  var import_store = require("@akanjs/store");
@@ -39,14 +40,20 @@ var import_next_themes = require("next-themes");
39
40
  var import_react = require("react");
40
41
  var import_Gtag = require("./Gtag");
41
42
  var import_Messages = require("./Messages");
43
+ var import_Reconnect = require("./Reconnect");
42
44
  const Client = () => {
43
45
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {});
44
46
  };
45
- const ClientWrapper = ({ children, theme }) => {
47
+ const ClientWrapper = ({ children, theme, lang = "en", dictionary = {} }) => {
48
+ if (!import_dictionary.serverTranslator.hasTranslator(lang))
49
+ import_dictionary.serverTranslator.setTranslator(lang, dictionary);
46
50
  (0, import_react.useEffect)(() => {
47
51
  import_common.Logger.rawLog(import_base.logo);
48
52
  }, []);
49
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_next_themes.ThemeProvider, { defaultTheme: theme, children });
53
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_next_themes.ThemeProvider, { defaultTheme: theme, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_client.dictionaryContext.Provider, { value: dictionary, children: [
54
+ children,
55
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Reconnect.Reconnect, {})
56
+ ] }) });
50
57
  };
51
58
  Client.Wrapper = ClientWrapper;
52
59
  const ClientPathWrapper = ({
@@ -24,7 +24,6 @@ var import_jsx_runtime = require("react/jsx-runtime");
24
24
  var import_ko = require("dayjs/locale/ko");
25
25
  var import_client = require("@akanjs/client");
26
26
  var import_Load = require("../Load");
27
- var import_Reconnect = require("./Reconnect");
28
27
  const Common = () => {
29
28
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {});
30
29
  };
@@ -37,32 +36,29 @@ const CommonWrapper = ({
37
36
  fetchSelf = (props) => fetch.getSelf?.(props)
38
37
  }) => {
39
38
  const account = (0, import_client.getAccount)();
40
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
41
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
42
- import_Load.Load.Page,
43
- {
44
- of: CommonWrapper,
45
- loader: async () => {
46
- const mePromise = (async () => {
47
- try {
48
- return account.me ? await fetchMe({ crystalize: false }) : null;
49
- } catch (e) {
50
- return null;
51
- }
52
- })();
53
- const selfPromise = (async () => {
54
- try {
55
- return account.self ? await fetchSelf({ crystalize: false }) : null;
56
- } catch (e) {
57
- return null;
58
- }
59
- })();
60
- return Promise.resolve({ mePromise, selfPromise });
61
- },
62
- render
63
- }
64
- ),
65
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Reconnect.Reconnect, {})
66
- ] });
39
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
40
+ import_Load.Load.Page,
41
+ {
42
+ of: CommonWrapper,
43
+ loader: async () => {
44
+ const mePromise = (async () => {
45
+ try {
46
+ return account.me ? await fetchMe({ crystalize: false }) : null;
47
+ } catch (e) {
48
+ return null;
49
+ }
50
+ })();
51
+ const selfPromise = (async () => {
52
+ try {
53
+ return account.self ? await fetchSelf({ crystalize: false }) : null;
54
+ } catch (e) {
55
+ return null;
56
+ }
57
+ })();
58
+ return Promise.resolve({ mePromise, selfPromise });
59
+ },
60
+ render
61
+ }
62
+ );
67
63
  };
68
64
  Common.Wrapper = CommonWrapper;
@@ -49,7 +49,7 @@ const Reconnect = () => {
49
49
  setConnectStatus((prev) => prev === "normal" || prev === "initial" ? "disconnected" : prev);
50
50
  setTimeout(() => {
51
51
  setConnectStatus((prev) => prev === "disconnected" ? "connecting" : prev);
52
- }, 3e3);
52
+ }, 2e3);
53
53
  }, []);
54
54
  (0, import_react.useEffect)(() => {
55
55
  const io = import_signal.client.getIo();
package/cjs/System/SSR.js CHANGED
@@ -23,6 +23,7 @@ __export(SSR_exports, {
23
23
  module.exports = __toCommonJS(SSR_exports);
24
24
  var import_jsx_runtime = require("react/jsx-runtime");
25
25
  var import_client = require("@akanjs/client");
26
+ var import_dictionary = require("@akanjs/dictionary");
26
27
  var import_react = require("react");
27
28
  var import_Load = require("../Load");
28
29
  var import_Client = require("./Client");
@@ -54,11 +55,13 @@ const SSRProvider = ({
54
55
  of,
55
56
  loader: async () => {
56
57
  const { lang } = await params;
58
+ await import_dictionary.serverTranslator.init(lang);
57
59
  if (!import_client.router.isInitialized)
58
60
  import_client.router.init({ type: "next", side: "server", lang, prefix });
59
- return { lang };
61
+ const dictionary = await import_dictionary.serverTranslator.getDictionary(lang);
62
+ return { lang, dictionary };
60
63
  },
61
- render: ({ lang }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
64
+ render: ({ lang, dictionary }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
62
65
  import_Common.Common.Wrapper,
63
66
  {
64
67
  fetch,
@@ -76,7 +79,7 @@ const SSRProvider = ({
76
79
  fonts,
77
80
  prefix,
78
81
  layoutStyle,
79
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_Client.ClientWrapper, { theme, children: [
82
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_Client.ClientWrapper, { theme, lang, dictionary, children: [
80
83
  children,
81
84
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.Suspense, { fallback: null, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Client.ClientInner, {}) }),
82
85
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.Suspense, { fallback: null, children: [
@@ -38,7 +38,7 @@ const ThemeToggle = () => {
38
38
  return null;
39
39
  }
40
40
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "form-control", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "label cursor-pointer", children: [
41
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "label-text mr-2 text-sm whitespace-nowrap", children: (0, import_common.capitalize)(theme ?? "") }),
41
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-base-content mr-2 text-sm whitespace-nowrap", children: (0, import_common.capitalize)(theme ?? "") }),
42
42
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", className: "toggle toggle-sm", checked: theme === "dark", onChange: handleTheme })
43
43
  ] }) });
44
44
  };
package/cjs/index.js CHANGED
@@ -20,6 +20,7 @@ __export(ui_exports, {
20
20
  BottomSheet: () => import_BottomSheet.BottomSheet,
21
21
  Button: () => import_Button.Button,
22
22
  ClientSide: () => import_ClientSide.ClientSide,
23
+ Clipboard: () => import_Clipboard.Clipboard,
23
24
  Copy: () => import_Copy.Copy,
24
25
  CsrImage: () => import_CsrImage.CsrImage,
25
26
  Data: () => import_Data.Data,
@@ -75,6 +76,7 @@ var import_BottomSheet = require("./BottomSheet");
75
76
  var import_Button = require("./Button");
76
77
  var import_ClientSide = require("./ClientSide");
77
78
  var import_Copy = require("./Copy");
79
+ var import_Clipboard = require("./Clipboard");
78
80
  var import_CsrImage = require("./CsrImage");
79
81
  var import_DatePicker = require("./DatePicker");
80
82
  var import_DragAction = require("./DragAction");
@@ -0,0 +1,51 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { clsx } from "@akanjs/client";
4
+ import { useEffect, useState } from "react";
5
+ import { FaCheck } from "react-icons/fa";
6
+ import { MdContentCopy } from "react-icons/md";
7
+ const Clipboard = ({ text, className }) => {
8
+ const [isCopied, setIsCopied] = useState(false);
9
+ useEffect(() => {
10
+ if (isCopied) {
11
+ setTimeout(() => {
12
+ setIsCopied(false);
13
+ }, 2e3);
14
+ }
15
+ }, [isCopied]);
16
+ const handleCopy = async () => {
17
+ if (!text)
18
+ return;
19
+ await navigator.clipboard.writeText(text);
20
+ setIsCopied(true);
21
+ };
22
+ return /* @__PURE__ */ jsxs(
23
+ "button",
24
+ {
25
+ onClick: async () => {
26
+ await handleCopy();
27
+ },
28
+ className: clsx(
29
+ "flex h-6 w-6 items-center justify-center rounded-md bg-white/30 text-white transition-all duration-300 hover:bg-white/20",
30
+ className
31
+ ),
32
+ children: [
33
+ /* @__PURE__ */ jsx(
34
+ FaCheck,
35
+ {
36
+ className: `absolute h-4 w-4 transition-opacity duration-300 ${isCopied ? "opacity-100" : "opacity-0"}`
37
+ }
38
+ ),
39
+ /* @__PURE__ */ jsx(
40
+ MdContentCopy,
41
+ {
42
+ className: `absolute h-4 w-4 transition-opacity duration-300 ${isCopied ? "opacity-0" : "opacity-100"}`
43
+ }
44
+ )
45
+ ]
46
+ }
47
+ );
48
+ };
49
+ export {
50
+ Clipboard
51
+ };
@@ -9,7 +9,6 @@ import {
9
9
  getFilterQuery,
10
10
  getFilterQueryMap,
11
11
  getGqlTypeStr,
12
- getQueryMap,
13
12
  hasTextField
14
13
  } from "@akanjs/constant";
15
14
  import { useDebounce, usePage } from "@akanjs/next";
@@ -27,9 +26,7 @@ function QueryMaker({ className, sliceName, query }) {
27
26
  const storeDo = st.do;
28
27
  const cnst = getCnstMeta(sliceName);
29
28
  const isModelSearchable = hasTextField(cnst.Full);
30
- const summaryRef = cnst.Summary;
31
29
  const { subMenu, filter } = st.use.searchParams();
32
- const summaryQueryMap = getQueryMap(summaryRef);
33
30
  const filterRef = cnst.Filter;
34
31
  const filterQueryMap = getFilterQueryMap(filterRef);
35
32
  const defaultQuerySetting = { ...isModelSearchable ? searchQuerySetting : byStatusQuerySetting, ...query ?? {} };
@@ -37,12 +34,7 @@ function QueryMaker({ className, sliceName, query }) {
37
34
  const [querySetting, setQuerySetting] = useState(defaultQuerySetting);
38
35
  const getQuery = useCallback(
39
36
  (querySetting2) => {
40
- if (summaryQueryMap[querySetting2.queryKey]) {
41
- const query2 = typeof summaryQueryMap[querySetting2.queryKey] === "function" ? summaryQueryMap[querySetting2.queryKey]() : summaryQueryMap[querySetting2.queryKey] ?? null;
42
- if (!query2)
43
- throw new Error(`Query not found`);
44
- return query2;
45
- } else if (querySetting2.queryKey === "search") {
37
+ if (querySetting2.queryKey === "search") {
46
38
  const query2 = querySetting2.arg;
47
39
  return query2;
48
40
  } else {
@@ -77,7 +69,7 @@ function QueryMaker({ className, sliceName, query }) {
77
69
  Select,
78
70
  {
79
71
  value: querySetting.queryKey,
80
- options: Object.keys(summaryQueryMap).map((queryKey) => ({
72
+ options: Object.keys(filterQueryMap).map((queryKey) => ({
81
73
  label: l.field("summary", queryKey),
82
74
  value: queryKey
83
75
  })),
@@ -111,7 +103,7 @@ function QueryMaker({ className, sliceName, query }) {
111
103
  ),
112
104
  /* @__PURE__ */ jsx(BiSearch, { className: "size-4 opacity-70" })
113
105
  ] })
114
- ] }) : summaryQueryMap[querySetting.queryKey] ? null : getFilterArgMetas(filterRef, querySetting.queryKey).map((queryArgMeta, idx) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
106
+ ] }) : getFilterArgMetas(filterRef, querySetting.queryKey).map((queryArgMeta, idx) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
115
107
  /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-500", children: l.qarg(sliceName, querySetting.queryKey, queryArgMeta.name) }),
116
108
  /* @__PURE__ */ jsx(
117
109
  QueryArg,
@@ -2,14 +2,21 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { clsx } from "@akanjs/client";
4
4
  import { usePage } from "@akanjs/next";
5
+ import { useEffect, useState } from "react";
5
6
  import { Link } from "../Link";
6
7
  import { BottomInset } from "./BottomInset";
7
8
  const BottomTab = ({ className, tabs, height = 64 }) => {
8
- const { lang } = usePage();
9
+ const { lang, path } = usePage();
10
+ const [isRendered, setIsRendered] = useState(false);
9
11
  const isActiveTab = (tabHref) => {
12
+ if (!isRendered)
13
+ return false;
10
14
  const locationPath = window.location.pathname.startsWith(`/${lang}`) ? window.location.pathname.slice(lang.length + 1) === "" ? "/" : window.location.pathname.slice(lang.length + 1) : window.location.pathname;
11
15
  return tabHref === "/" ? locationPath === tabHref : locationPath.startsWith(tabHref);
12
16
  };
17
+ useEffect(() => {
18
+ setIsRendered(true);
19
+ }, []);
13
20
  return /* @__PURE__ */ jsx(BottomInset, { className: "h-full", children: /* @__PURE__ */ jsx(
14
21
  "div",
15
22
  {
@@ -1,15 +1,12 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { capitalize } from "@akanjs/common";
3
- import { getQueryMap, getScalarModelRef } from "@akanjs/constant";
4
2
  import { Data } from "../Data";
5
3
  function AdminPanel({
6
4
  sliceName,
7
5
  components,
8
- queryMap = getQueryMap(getScalarModelRef(`${capitalize(sliceName)}Summary`)),
9
6
  summaryColumns = ["totalAdmin"],
10
7
  insightColumns = ["count"],
11
8
  renderInsight = ({ insight }) => /* @__PURE__ */ jsx(Data.Insight, { insight, sliceName, columns: insightColumns }),
12
- renderDashboard = ({ summary }) => /* @__PURE__ */ jsx(Data.Dashboard, { summary, sliceName, columns: summaryColumns, queryMap }),
9
+ renderDashboard = ({ summary }) => /* @__PURE__ */ jsx(Data.Dashboard, { summary, sliceName, columns: summaryColumns, queryMap: {} }),
13
10
  ...props
14
11
  }) {
15
12
  return /* @__PURE__ */ jsx(
@@ -10,9 +10,9 @@ const ListenerResult = ({ status, data }) => {
10
10
  const dataStr = typeof data === "object" ? JSON.stringify(data, null, 2) : data;
11
11
  const ref = useRef(null);
12
12
  useEffect(() => {
13
- if (ref.current) {
14
- ref.current.scrollTop = ref.current.scrollHeight;
15
- }
13
+ if (!ref.current)
14
+ return;
15
+ ref.current.scrollTop = ref.current.scrollHeight;
16
16
  }, [dataStr]);
17
17
  return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
18
18
  /* @__PURE__ */ jsx(
@@ -136,7 +136,7 @@ const MessageTry = ({ sigRef, gqlMeta, gqlArgMetas, uploadArgMetas }) => {
136
136
  const [uploadRequest, setUploadRequest] = useState({});
137
137
  const [stopListen, setStopListen] = useState(null);
138
138
  const [messages, setMessages] = useState("");
139
- const [response, setResponse] = useState({ status: "ready", data: null });
139
+ const [response, setResponse] = useState({ status: "ready", data: "" });
140
140
  const onSend = async () => {
141
141
  const request = { ...JSON.parse(gqlRequest), ...uploadRequest };
142
142
  const argData = [...gqlArgMetas, ...uploadArgMetas].sort((a, b) => a.idx - b.idx).map((argMeta) => request[argMeta.name]);
@@ -148,7 +148,7 @@ const MessageTry = ({ sigRef, gqlMeta, gqlArgMetas, uploadArgMetas }) => {
148
148
  const request = { ...JSON.parse(gqlRequest), ...uploadRequest };
149
149
  const fetchFn = fetch[`listen${capitalize(gqlMeta.key)}`].bind(fetch);
150
150
  setResponse({ status: "loading", data: messages });
151
- const stopListen2 = fetchFn(({ event, data }) => {
151
+ const stopListen2 = fetchFn((data) => {
152
152
  setMessages(
153
153
  (prev) => typeof data === "boolean" ? data : typeof data === "string" ? `${prev}
154
154
  ${data}` : typeof data === "object" ? [...prev && prev.length ? [...prev] : [], data] : data
@@ -135,18 +135,15 @@ const PubSubTry = ({ sigRef, gqlMeta, gqlArgMetas, uploadArgMetas }) => {
135
135
  const [gqlRequest, setGqlRequest] = useState(requestExample);
136
136
  const [uploadRequest, setUploadRequest] = useState({});
137
137
  const [unsubscribe, setUnsubscribe] = useState(null);
138
- const [messages, setMessages] = useState(null);
139
- const [response, setResponse] = useState({
140
- status: "ready",
141
- data: null
142
- });
138
+ const [messages, setMessages] = useState("");
139
+ const [response, setResponse] = useState({ status: "ready", data: "" });
143
140
  const onSubscribe = () => {
144
- setResponse({ status: "loading", data: null });
141
+ setResponse({ status: "loading", data: "" });
145
142
  const request = { ...JSON.parse(gqlRequest), ...uploadRequest };
146
143
  const argData = [...gqlArgMetas, ...uploadArgMetas].sort((a, b) => a.idx - b.idx).map((argMeta) => request[argMeta.name]);
147
144
  const fetchFn = fetch[`subscribe${capitalize(gqlMeta.key)}`].bind(fetch);
148
145
  setResponse({ status: "loading", data: messages });
149
- const unsubscribe2 = fetchFn([...argData], (data) => {
146
+ const unsubscribe2 = fetchFn(...argData, (data) => {
150
147
  setMessages(
151
148
  (prev) => typeof data === "boolean" ? data : typeof data === "string" ? `${prev}
152
149
  ${data}` : typeof data === "object" ? [
package/esm/System/CSR.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { clsx, device, getPathInfo, router, useCsr } from "@akanjs/client";
4
+ import { serverTranslator } from "@akanjs/dictionary";
4
5
  import { usePushNoti } from "@akanjs/next";
5
6
  import { st } from "@akanjs/store";
6
7
  import { animated } from "@akanjs/ui";
@@ -38,10 +39,11 @@ const CSRProvider = ({
38
39
  of,
39
40
  loader: async () => {
40
41
  const { lang } = await params;
41
- return { lang };
42
+ const dictionary = await serverTranslator.getDictionary(lang);
43
+ return { lang, dictionary };
42
44
  },
43
- render: ({ lang }) => /* @__PURE__ */ jsxs(Fragment, { children: [
44
- /* @__PURE__ */ jsx(Client.Wrapper, { theme, children: /* @__PURE__ */ jsx(
45
+ render: ({ lang, dictionary }) => /* @__PURE__ */ jsxs(Fragment, { children: [
46
+ /* @__PURE__ */ jsx(Client.Wrapper, { theme, lang, dictionary, children: /* @__PURE__ */ jsx(
45
47
  CSRWrapper,
46
48
  {
47
49
  className,
@@ -5,6 +5,7 @@ import {
5
5
  clsx,
6
6
  defaultPageState,
7
7
  device,
8
+ dictionaryContext,
8
9
  getPathInfo,
9
10
  initAuth,
10
11
  pathContext,
@@ -13,6 +14,7 @@ import {
13
14
  storage
14
15
  } from "@akanjs/client";
15
16
  import { Logger } from "@akanjs/common";
17
+ import { serverTranslator } from "@akanjs/dictionary";
16
18
  import { useFetch } from "@akanjs/next";
17
19
  import { fetch } from "@akanjs/signal";
18
20
  import { st } from "@akanjs/store";
@@ -22,14 +24,20 @@ import { ThemeProvider, useTheme } from "next-themes";
22
24
  import { useEffect, useState } from "react";
23
25
  import { Gtag } from "./Gtag";
24
26
  import { Messages } from "./Messages";
27
+ import { Reconnect } from "./Reconnect";
25
28
  const Client = () => {
26
29
  return /* @__PURE__ */ jsx(Fragment, {});
27
30
  };
28
- const ClientWrapper = ({ children, theme }) => {
31
+ const ClientWrapper = ({ children, theme, lang = "en", dictionary = {} }) => {
32
+ if (!serverTranslator.hasTranslator(lang))
33
+ serverTranslator.setTranslator(lang, dictionary);
29
34
  useEffect(() => {
30
35
  Logger.rawLog(logo);
31
36
  }, []);
32
- return /* @__PURE__ */ jsx(ThemeProvider, { defaultTheme: theme, children });
37
+ return /* @__PURE__ */ jsx(ThemeProvider, { defaultTheme: theme, children: /* @__PURE__ */ jsxs(dictionaryContext.Provider, { value: dictionary, children: [
38
+ children,
39
+ /* @__PURE__ */ jsx(Reconnect, {})
40
+ ] }) });
33
41
  };
34
42
  Client.Wrapper = ClientWrapper;
35
43
  const ClientPathWrapper = ({
@@ -1,8 +1,7 @@
1
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
1
+ import { Fragment, jsx } from "react/jsx-runtime";
2
2
  import "dayjs/locale/ko";
3
3
  import { getAccount } from "@akanjs/client";
4
4
  import { Load } from "../Load";
5
- import { Reconnect } from "./Reconnect";
6
5
  const Common = () => {
7
6
  return /* @__PURE__ */ jsx(Fragment, {});
8
7
  };
@@ -15,33 +14,30 @@ const CommonWrapper = ({
15
14
  fetchSelf = (props) => fetch.getSelf?.(props)
16
15
  }) => {
17
16
  const account = getAccount();
18
- return /* @__PURE__ */ jsxs(Fragment, { children: [
19
- /* @__PURE__ */ jsx(
20
- Load.Page,
21
- {
22
- of: CommonWrapper,
23
- loader: async () => {
24
- const mePromise = (async () => {
25
- try {
26
- return account.me ? await fetchMe({ crystalize: false }) : null;
27
- } catch (e) {
28
- return null;
29
- }
30
- })();
31
- const selfPromise = (async () => {
32
- try {
33
- return account.self ? await fetchSelf({ crystalize: false }) : null;
34
- } catch (e) {
35
- return null;
36
- }
37
- })();
38
- return Promise.resolve({ mePromise, selfPromise });
39
- },
40
- render
41
- }
42
- ),
43
- /* @__PURE__ */ jsx(Reconnect, {})
44
- ] });
17
+ return /* @__PURE__ */ jsx(
18
+ Load.Page,
19
+ {
20
+ of: CommonWrapper,
21
+ loader: async () => {
22
+ const mePromise = (async () => {
23
+ try {
24
+ return account.me ? await fetchMe({ crystalize: false }) : null;
25
+ } catch (e) {
26
+ return null;
27
+ }
28
+ })();
29
+ const selfPromise = (async () => {
30
+ try {
31
+ return account.self ? await fetchSelf({ crystalize: false }) : null;
32
+ } catch (e) {
33
+ return null;
34
+ }
35
+ })();
36
+ return Promise.resolve({ mePromise, selfPromise });
37
+ },
38
+ render
39
+ }
40
+ );
45
41
  };
46
42
  Common.Wrapper = CommonWrapper;
47
43
  export {
@@ -17,7 +17,7 @@ const Reconnect = () => {
17
17
  setConnectStatus((prev) => prev === "normal" || prev === "initial" ? "disconnected" : prev);
18
18
  setTimeout(() => {
19
19
  setConnectStatus((prev) => prev === "disconnected" ? "connecting" : prev);
20
- }, 3e3);
20
+ }, 2e3);
21
21
  }, []);
22
22
  useEffect(() => {
23
23
  const io = client.getIo();
package/esm/System/SSR.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { clsx, router } from "@akanjs/client";
3
+ import { serverTranslator } from "@akanjs/dictionary";
3
4
  import { Suspense } from "react";
4
5
  import { Load } from "../Load";
5
6
  import { ClientBridge, ClientInner, ClientNextBridge, ClientPathWrapper, ClientWrapper } from "./Client";
@@ -31,11 +32,13 @@ const SSRProvider = ({
31
32
  of,
32
33
  loader: async () => {
33
34
  const { lang } = await params;
35
+ await serverTranslator.init(lang);
34
36
  if (!router.isInitialized)
35
37
  router.init({ type: "next", side: "server", lang, prefix });
36
- return { lang };
38
+ const dictionary = await serverTranslator.getDictionary(lang);
39
+ return { lang, dictionary };
37
40
  },
38
- render: ({ lang }) => /* @__PURE__ */ jsx(
41
+ render: ({ lang, dictionary }) => /* @__PURE__ */ jsx(
39
42
  Common.Wrapper,
40
43
  {
41
44
  fetch,
@@ -53,7 +56,7 @@ const SSRProvider = ({
53
56
  fonts,
54
57
  prefix,
55
58
  layoutStyle,
56
- children: /* @__PURE__ */ jsxs(ClientWrapper, { theme, children: [
59
+ children: /* @__PURE__ */ jsxs(ClientWrapper, { theme, lang, dictionary, children: [
57
60
  children,
58
61
  /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(ClientInner, {}) }),
59
62
  /* @__PURE__ */ jsxs(Suspense, { fallback: null, children: [
@@ -16,7 +16,7 @@ const ThemeToggle = () => {
16
16
  return null;
17
17
  }
18
18
  return /* @__PURE__ */ jsx("div", { className: "form-control", children: /* @__PURE__ */ jsxs("label", { className: "label cursor-pointer", children: [
19
- /* @__PURE__ */ jsx("span", { className: "label-text mr-2 text-sm whitespace-nowrap", children: capitalize(theme ?? "") }),
19
+ /* @__PURE__ */ jsx("span", { className: "text-base-content mr-2 text-sm whitespace-nowrap", children: capitalize(theme ?? "") }),
20
20
  /* @__PURE__ */ jsx("input", { type: "checkbox", className: "toggle toggle-sm", checked: theme === "dark", onChange: handleTheme })
21
21
  ] }) });
22
22
  };
package/esm/index.js CHANGED
@@ -12,6 +12,7 @@ import { BottomSheet } from "./BottomSheet";
12
12
  import { Button } from "./Button";
13
13
  import { ClientSide } from "./ClientSide";
14
14
  import { Copy } from "./Copy";
15
+ import { Clipboard } from "./Clipboard";
15
16
  import { CsrImage } from "./CsrImage";
16
17
  import { DatePicker } from "./DatePicker";
17
18
  import { DragAction } from "./DragAction";
@@ -44,6 +45,7 @@ export {
44
45
  BottomSheet,
45
46
  Button,
46
47
  ClientSide,
48
+ Clipboard,
47
49
  Copy,
48
50
  CsrImage,
49
51
  Data,
package/index.d.ts CHANGED
@@ -12,6 +12,7 @@ export { BottomSheet, type BottomSheetRef } from "./BottomSheet";
12
12
  export { Button } from "./Button";
13
13
  export { ClientSide } from "./ClientSide";
14
14
  export { Copy } from "./Copy";
15
+ export { Clipboard } from "./Clipboard";
15
16
  export { CsrImage } from "./CsrImage";
16
17
  export { DatePicker } from "./DatePicker";
17
18
  export { DragAction } from "./DragAction";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akanjs/ui",
3
- "version": "0.9.43",
3
+ "version": "0.9.45",
4
4
  "sourceType": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"