akanjs 2.4.2-rc.2 → 3.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/base/baseEnv.ts +0 -6
- package/client/cn.ts +52 -0
- package/client/csrTypes.ts +2 -2
- package/client/frameConfig.ts +2 -2
- package/client/index.ts +1 -0
- package/client/types.ts +0 -4
- package/common/fileUpload.ts +1 -1
- package/common/index.ts +1 -0
- package/common/isThenable.ts +12 -0
- package/constant/purify.ts +9 -10
- package/fetch/client/fetchClient.ts +1 -1
- package/fetch/client/httpClient.ts +9 -5
- package/fetch/fetchType/sliceFetch.type.ts +1 -1
- package/package.json +4 -7
- package/server/akanApp.ts +2 -0
- package/server/systemPageDocument.tsx +12 -12
- package/signal/endpointInfo.ts +2 -1
- package/signal/slice.ts +1 -1
- package/signal/sliceInfo.ts +2 -1
- package/store/action.ts +18 -2
- package/store/baseSt.ts +2 -2
- package/store/state.ts +9 -1
- package/store/storeInstance.ts +2 -0
- package/test/sampleOf.ts +3 -3
- package/test/signalTestRuntime.ts +0 -2
- package/types/base/baseEnv.d.ts +0 -2
- package/types/client/cn.d.ts +12 -0
- package/types/client/index.d.ts +1 -0
- package/types/client/types.d.ts +0 -3
- package/types/common/fileUpload.d.ts +1 -1
- package/types/common/index.d.ts +1 -0
- package/types/common/isThenable.d.ts +9 -0
- package/types/constant/purify.d.ts +3 -2
- package/types/fetch/fetchType/sliceFetch.type.d.ts +1 -1
- package/types/signal/endpointInfo.d.ts +2 -2
- package/types/signal/slice.d.ts +1 -1
- package/types/signal/sliceInfo.d.ts +2 -2
- package/types/store/action.d.ts +1 -1
- package/types/store/state.d.ts +4 -2
- package/types/test/sampleOf.d.ts +2 -2
- package/types/ui/Badge.d.ts +6 -0
- package/types/ui/Button.d.ts +26 -6
- package/types/ui/Load/Units.d.ts +3 -1
- package/types/ui/RecentTime.d.ts +1 -1
- package/types/ui/Signal/Collapse.d.ts +12 -0
- package/types/ui/Signal/style.d.ts +5 -6
- package/types/ui/Switch.d.ts +14 -0
- package/types/ui/Tooltip.d.ts +11 -0
- package/types/ui/UiOverride/Provider.d.ts +6 -5
- package/types/ui/UiOverride/context.d.ts +22 -1
- package/types/ui/UiOverride/index.d.ts +2 -1
- package/types/ui/UiOverride/override.d.ts +7 -6
- package/types/ui/UiOverride/useUiRecipe.d.ts +8 -0
- package/types/ui/index.d.ts +5 -1
- package/types/ui/recipe/badgeRecipe.d.ts +13 -0
- package/types/ui/recipe/buttonRecipe.d.ts +15 -0
- package/types/ui/recipe/factory.d.ts +24 -0
- package/types/ui/recipe/index.d.ts +18 -0
- package/types/ui/recipe/inputRecipe.d.ts +13 -0
- package/types/ui/recipe.d.ts +1 -0
- package/ui/Badge.tsx +17 -0
- package/ui/BottomSheet.tsx +8 -10
- package/ui/Button.tsx +158 -48
- package/ui/Clipboard.tsx +3 -3
- package/ui/Constant/Doc.tsx +108 -65
- package/ui/Constant/Mermaid.tsx +9 -9
- package/ui/Data/CardList.tsx +3 -3
- package/ui/Data/Dashboard.tsx +22 -13
- package/ui/Data/Insight.tsx +6 -6
- package/ui/Data/Item.tsx +49 -34
- package/ui/Data/ListContainer.tsx +11 -7
- package/ui/Data/Pagination.tsx +2 -2
- package/ui/DatePicker.tsx +5 -5
- package/ui/Dialog/Content.tsx +2 -2
- package/ui/Dialog/Modal.tsx +12 -8
- package/ui/Dialog/Provider.tsx +2 -2
- package/ui/DragAction.tsx +2 -2
- package/ui/DraggableList.tsx +10 -5
- package/ui/Dropdown.tsx +33 -26
- package/ui/Empty.tsx +5 -5
- package/ui/Field.tsx +82 -70
- package/ui/Image.tsx +2 -2
- package/ui/Input.tsx +62 -60
- package/ui/Layout/BottomInset.tsx +2 -2
- package/ui/Layout/BottomTab.tsx +5 -5
- package/ui/Layout/Header.tsx +3 -3
- package/ui/Layout/LeftSider.tsx +6 -5
- package/ui/Layout/Navbar.tsx +2 -12
- package/ui/Layout/RightSider.tsx +10 -8
- package/ui/Layout/Sider.tsx +5 -4
- package/ui/Layout/Template.tsx +2 -2
- package/ui/Layout/TopInset.tsx +2 -2
- package/ui/Layout/Unit.tsx +2 -2
- package/ui/Layout/View.tsx +2 -2
- package/ui/Layout/Zone.tsx +2 -2
- package/ui/Link/Back.tsx +2 -2
- package/ui/Link/Close.tsx +2 -2
- package/ui/Link/CsrLink.tsx +6 -4
- package/ui/Link/Lang.tsx +2 -2
- package/ui/Link/SsrLink.tsx +6 -5
- package/ui/Load/Page.tsx +1 -1
- package/ui/Load/Pagination.tsx +2 -2
- package/ui/Load/Units.tsx +19 -4
- package/ui/Load/View.tsx +2 -2
- package/ui/Loading/Area.tsx +4 -2
- package/ui/Loading/Button.tsx +2 -2
- package/ui/Loading/Input.tsx +2 -2
- package/ui/Loading/ProgressBar.tsx +2 -2
- package/ui/Loading/Skeleton.tsx +6 -6
- package/ui/Loading/Spin.tsx +2 -2
- package/ui/Menu.tsx +29 -27
- package/ui/Model/Edit.tsx +3 -3
- package/ui/Model/EditModal.tsx +5 -5
- package/ui/Model/EditWrapper.tsx +2 -2
- package/ui/Model/New.tsx +3 -3
- package/ui/Model/NewWrapper_Client.tsx +2 -2
- package/ui/Model/Remove.tsx +5 -4
- package/ui/Model/RemoveWrapper.tsx +2 -2
- package/ui/Model/SureToRemove.tsx +7 -6
- package/ui/Model/View.tsx +2 -2
- package/ui/Model/ViewEditModal.tsx +20 -21
- package/ui/Model/ViewWrapper.tsx +2 -2
- package/ui/More.tsx +2 -2
- package/ui/ObjectId.tsx +9 -3
- package/ui/Pagination.tsx +14 -11
- package/ui/Popconfirm.tsx +20 -11
- package/ui/Radio.tsx +4 -4
- package/ui/RecentTime.tsx +30 -83
- package/ui/Refresh.tsx +1 -1
- package/ui/ScreenNavigator.tsx +2 -2
- package/ui/Select.tsx +21 -23
- package/ui/Signal/Arg.tsx +21 -18
- package/ui/Signal/Collapse.tsx +29 -0
- package/ui/Signal/Doc.tsx +27 -22
- package/ui/Signal/Listener.tsx +3 -3
- package/ui/Signal/Message.tsx +31 -17
- package/ui/Signal/Object.tsx +13 -8
- package/ui/Signal/PubSub.tsx +26 -16
- package/ui/Signal/Request.tsx +3 -2
- package/ui/Signal/Response.tsx +5 -4
- package/ui/Signal/RestApi.tsx +27 -17
- package/ui/Signal/style.ts +16 -16
- package/ui/Switch.tsx +62 -0
- package/ui/System/CSR.tsx +40 -35
- package/ui/System/Client.tsx +2 -2
- package/ui/System/DevModeToggle.tsx +10 -12
- package/ui/System/Messages.tsx +14 -16
- package/ui/System/Reconnect.tsx +7 -7
- package/ui/System/SSR.tsx +25 -21
- package/ui/System/SelectLanguage.tsx +24 -28
- package/ui/System/ThemeToggle.tsx +38 -45
- package/ui/Tab/Menu.tsx +20 -18
- package/ui/Tab/Panel.tsx +3 -3
- package/ui/Tab/Provider.tsx +2 -2
- package/ui/Table.tsx +11 -8
- package/ui/ToggleSelect.tsx +14 -18
- package/ui/Tooltip.tsx +55 -0
- package/ui/UiOverride/Provider.tsx +10 -6
- package/ui/UiOverride/context.ts +22 -2
- package/ui/UiOverride/index.ts +8 -1
- package/ui/UiOverride/override.ts +7 -6
- package/ui/UiOverride/useUiRecipe.ts +15 -0
- package/ui/Unauthorized.tsx +5 -5
- package/ui/index.ts +16 -0
- package/ui/recipe/badgeRecipe.ts +23 -0
- package/ui/recipe/buttonRecipe.ts +32 -0
- package/ui/recipe/factory.ts +32 -0
- package/ui/recipe/index.ts +18 -0
- package/ui/recipe/inputRecipe.ts +13 -0
- package/ui/styles.css +150 -21
package/ui/Input.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { cn, usePage } from "akanjs/client";
|
|
3
3
|
import { isEmail } from "akanjs/common";
|
|
4
4
|
import React, {
|
|
5
5
|
type ChangeEvent,
|
|
@@ -13,8 +13,12 @@ import React, {
|
|
|
13
13
|
} from "react";
|
|
14
14
|
import { AiOutlineEye, AiOutlineEyeInvisible } from "react-icons/ai";
|
|
15
15
|
|
|
16
|
+
import { inputRecipe } from "./recipe";
|
|
16
17
|
import { createOverridable } from "./UiOverride";
|
|
17
18
|
|
|
19
|
+
const inputBase = inputRecipe();
|
|
20
|
+
const textareaBase = inputRecipe({ kind: "area" });
|
|
21
|
+
|
|
18
22
|
export type InputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "value" | "onChange"> & {
|
|
19
23
|
/** Visual input style. */
|
|
20
24
|
inputStyleType?: "bordered" | "borderless" | "underline";
|
|
@@ -72,19 +76,21 @@ const DefaultInput = ({
|
|
|
72
76
|
const statusClass =
|
|
73
77
|
inputStyleType === "bordered"
|
|
74
78
|
? status === "error"
|
|
75
|
-
? "
|
|
79
|
+
? "border-destructive"
|
|
76
80
|
: !firstFocus && status === "warning"
|
|
77
|
-
? "
|
|
81
|
+
? "border-warning"
|
|
78
82
|
: status === "success"
|
|
79
|
-
? "
|
|
83
|
+
? "border-success"
|
|
80
84
|
: ""
|
|
81
85
|
: "";
|
|
82
|
-
const inputType =
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
const inputType = cn(
|
|
87
|
+
inputBase,
|
|
88
|
+
inputStyleType === "borderless"
|
|
89
|
+
? "border-transparent bg-transparent"
|
|
90
|
+
: inputStyleType === "underline"
|
|
91
|
+
? "rounded-none border-0 border-b"
|
|
92
|
+
: "",
|
|
93
|
+
);
|
|
88
94
|
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
89
95
|
if (onPressEnter && e.key === "Enter") onPressEnter(e.currentTarget.value, e);
|
|
90
96
|
if (e.key === "Escape") {
|
|
@@ -100,8 +106,8 @@ const DefaultInput = ({
|
|
|
100
106
|
}, [value]);
|
|
101
107
|
|
|
102
108
|
return (
|
|
103
|
-
<div className={
|
|
104
|
-
{icon ? <div className={
|
|
109
|
+
<div className={cn("relative isolate flex items-center", className)}>
|
|
110
|
+
{icon ? <div className={cn("flex items-center justify-center", iconClassName)}>{icon}</div> : null}
|
|
105
111
|
<input
|
|
106
112
|
{...rest}
|
|
107
113
|
ref={inputRef}
|
|
@@ -116,15 +122,15 @@ const DefaultInput = ({
|
|
|
116
122
|
if (firstFocus && value) setFirstFocus(false);
|
|
117
123
|
}}
|
|
118
124
|
onKeyDown={handleKeyDown}
|
|
119
|
-
className={
|
|
120
|
-
`b-5 text-
|
|
125
|
+
className={cn(
|
|
126
|
+
`b-5 text-foreground outline-hidden duration-300 focus:border-primary focus:outline-hidden ${icon && ""}`,
|
|
121
127
|
inputType,
|
|
122
128
|
inputClassName,
|
|
123
129
|
)}
|
|
124
130
|
/>
|
|
125
131
|
<div
|
|
126
132
|
data-validate={!!validateResult}
|
|
127
|
-
className="absolute -bottom-4 whitespace-nowrap text-
|
|
133
|
+
className="absolute -bottom-4 whitespace-nowrap text-destructive text-xs duration-300"
|
|
128
134
|
>
|
|
129
135
|
{invalidMessage}
|
|
130
136
|
</div>
|
|
@@ -174,11 +180,11 @@ const DefaultTextArea = ({
|
|
|
174
180
|
: validateResult;
|
|
175
181
|
const statusClass =
|
|
176
182
|
status === "error"
|
|
177
|
-
? "
|
|
183
|
+
? "border-destructive"
|
|
178
184
|
: !firstFocus && status === "warning"
|
|
179
|
-
? "
|
|
185
|
+
? "border-warning"
|
|
180
186
|
: status === "success"
|
|
181
|
-
? "
|
|
187
|
+
? "border-success"
|
|
182
188
|
: "";
|
|
183
189
|
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
|
184
190
|
if (onPressEnter && e.key === "Enter") onPressEnter(e.currentTarget.value, e);
|
|
@@ -193,7 +199,7 @@ const DefaultTextArea = ({
|
|
|
193
199
|
}, []);
|
|
194
200
|
|
|
195
201
|
return (
|
|
196
|
-
<div className={
|
|
202
|
+
<div className={cn("relative mb-5", className)}>
|
|
197
203
|
<textarea
|
|
198
204
|
{...rest}
|
|
199
205
|
ref={inputRef}
|
|
@@ -208,14 +214,17 @@ const DefaultTextArea = ({
|
|
|
208
214
|
onBlur={(e) => {
|
|
209
215
|
if (firstFocus && value) setFirstFocus(false);
|
|
210
216
|
}}
|
|
211
|
-
className={
|
|
212
|
-
|
|
217
|
+
className={cn(
|
|
218
|
+
cn(
|
|
219
|
+
textareaBase,
|
|
220
|
+
"resize-none text-foreground outline-hidden duration-300 focus:border-primary focus:outline-hidden",
|
|
221
|
+
),
|
|
213
222
|
statusClass,
|
|
214
223
|
inputClassName,
|
|
215
224
|
)}
|
|
216
225
|
/>
|
|
217
226
|
{invalidMessage ? (
|
|
218
|
-
<div className="absolute -bottom-4 animate-fadeIn text-
|
|
227
|
+
<div className="absolute -bottom-4 animate-fadeIn text-destructive text-xs">{invalidMessage}</div>
|
|
219
228
|
) : null}
|
|
220
229
|
</div>
|
|
221
230
|
);
|
|
@@ -264,11 +273,11 @@ const DefaultPassword = ({
|
|
|
264
273
|
: validateResult;
|
|
265
274
|
const statusClass =
|
|
266
275
|
status === "error"
|
|
267
|
-
? "
|
|
276
|
+
? "border-destructive"
|
|
268
277
|
: !firstFocus && status === "warning"
|
|
269
|
-
? "
|
|
278
|
+
? "border-warning"
|
|
270
279
|
: status === "success"
|
|
271
|
-
? "
|
|
280
|
+
? "border-success"
|
|
272
281
|
: "";
|
|
273
282
|
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
274
283
|
if (onPressEnter && e.key === "Enter") onPressEnter(e.currentTarget.value, e);
|
|
@@ -283,10 +292,10 @@ const DefaultPassword = ({
|
|
|
283
292
|
}
|
|
284
293
|
}, []);
|
|
285
294
|
return (
|
|
286
|
-
<div className={
|
|
287
|
-
<div className={
|
|
295
|
+
<div className={cn("relative isolate pb-2", className)}>
|
|
296
|
+
<div className={cn("relative flex items-center justify-between", inputWrapperClassName)}>
|
|
288
297
|
{icon ? (
|
|
289
|
-
<div className={
|
|
298
|
+
<div className={cn("absolute inset-y-0 left-4 z-10 flex items-center justify-center", iconClassName)}>
|
|
290
299
|
{icon}
|
|
291
300
|
</div>
|
|
292
301
|
) : null}
|
|
@@ -305,8 +314,8 @@ const DefaultPassword = ({
|
|
|
305
314
|
}
|
|
306
315
|
onChange?.(e.target.value, e);
|
|
307
316
|
}}
|
|
308
|
-
className={
|
|
309
|
-
`
|
|
317
|
+
className={cn(
|
|
318
|
+
cn(inputBase, `text-foreground duration-300 focus:border-primary focus:outline-hidden ${icon && "pl-12"}`),
|
|
310
319
|
statusClass,
|
|
311
320
|
inputClassName,
|
|
312
321
|
)}
|
|
@@ -323,7 +332,7 @@ const DefaultPassword = ({
|
|
|
323
332
|
</div>
|
|
324
333
|
<div
|
|
325
334
|
data-validate={!!invalidMessage.length}
|
|
326
|
-
className="h-2 text-
|
|
335
|
+
className="h-2 text-destructive text-xs duration-300 data-[validate=false]:opacity-0 data-[validate=true]:opacity-100"
|
|
327
336
|
>
|
|
328
337
|
{invalidMessage}
|
|
329
338
|
</div>
|
|
@@ -376,18 +385,13 @@ const DefaultEmail = ({
|
|
|
376
385
|
: validateResult;
|
|
377
386
|
const statusClass =
|
|
378
387
|
status === "error"
|
|
379
|
-
? "
|
|
388
|
+
? "border-destructive"
|
|
380
389
|
: !firstFocus && status === "warning"
|
|
381
|
-
? "
|
|
390
|
+
? "border-warning"
|
|
382
391
|
: status === "success"
|
|
383
|
-
? "
|
|
392
|
+
? "border-success"
|
|
384
393
|
: "";
|
|
385
|
-
const inputType =
|
|
386
|
-
inputStyleType === "bordered"
|
|
387
|
-
? "input-bordered"
|
|
388
|
-
: inputStyleType === "borderless"
|
|
389
|
-
? "input"
|
|
390
|
-
: "input-bordered rounded-none";
|
|
394
|
+
const inputType = cn(inputBase, inputStyleType === "underline" ? "rounded-none" : "");
|
|
391
395
|
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
392
396
|
if (onPressEnter && e.key === "Enter") onPressEnter(e.currentTarget.value, e);
|
|
393
397
|
if (e.key === "Escape") {
|
|
@@ -405,10 +409,10 @@ const DefaultEmail = ({
|
|
|
405
409
|
}, []);
|
|
406
410
|
|
|
407
411
|
return (
|
|
408
|
-
<div className={
|
|
409
|
-
<div className={
|
|
412
|
+
<div className={cn("relative isolate mb-5", className)}>
|
|
413
|
+
<div className={cn("flex items-center", inputWrapperClassName)}>
|
|
410
414
|
{icon ? (
|
|
411
|
-
<div className={
|
|
415
|
+
<div className={cn("absolute inset-y-0 left-4 z-10 flex items-center justify-center", iconClassName)}>
|
|
412
416
|
{icon}
|
|
413
417
|
</div>
|
|
414
418
|
) : null}
|
|
@@ -427,10 +431,8 @@ const DefaultEmail = ({
|
|
|
427
431
|
}
|
|
428
432
|
onChange?.(e.target.value, e);
|
|
429
433
|
}}
|
|
430
|
-
className={
|
|
431
|
-
`
|
|
432
|
-
icon && "pl-12"
|
|
433
|
-
}`,
|
|
434
|
+
className={cn(
|
|
435
|
+
`text-foreground outline-hidden duration-300 focus:border-primary focus:outline-hidden ${icon && "pl-12"}`,
|
|
434
436
|
inputType,
|
|
435
437
|
statusClass,
|
|
436
438
|
inputClassName,
|
|
@@ -438,7 +440,7 @@ const DefaultEmail = ({
|
|
|
438
440
|
/>
|
|
439
441
|
</div>
|
|
440
442
|
{invalidMessage ? (
|
|
441
|
-
<div className="absolute -bottom-4 animate-fadeIn text-
|
|
443
|
+
<div className="absolute -bottom-4 animate-fadeIn text-destructive text-xs">{invalidMessage}</div>
|
|
442
444
|
) : null}
|
|
443
445
|
</div>
|
|
444
446
|
);
|
|
@@ -506,13 +508,13 @@ const DefaultNumber = ({
|
|
|
506
508
|
const statusClass =
|
|
507
509
|
validate !== undefined
|
|
508
510
|
? status === "error"
|
|
509
|
-
? "
|
|
511
|
+
? "border-destructive"
|
|
510
512
|
: !firstFocus && status === "warning"
|
|
511
|
-
? "
|
|
513
|
+
? "border-warning"
|
|
512
514
|
: status === "success"
|
|
513
|
-
? "
|
|
514
|
-
: "
|
|
515
|
-
: "
|
|
515
|
+
? "border-success"
|
|
516
|
+
: ""
|
|
517
|
+
: "";
|
|
516
518
|
|
|
517
519
|
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
518
520
|
const numberValue = parseFloat(e.currentTarget.value.replace(/[^\d-]/g, ""));
|
|
@@ -573,10 +575,10 @@ const DefaultNumber = ({
|
|
|
573
575
|
}, [value]);
|
|
574
576
|
|
|
575
577
|
return (
|
|
576
|
-
<div className={
|
|
577
|
-
<div className={
|
|
578
|
+
<div className={cn("relative isolate", className)}>
|
|
579
|
+
<div className={cn("flex items-center", inputWrapperClassName)}>
|
|
578
580
|
{icon ? (
|
|
579
|
-
<div className={
|
|
581
|
+
<div className={cn("absolute inset-y-0 left-4 z-10 flex items-center justify-center", iconClassName)}>
|
|
580
582
|
{icon}
|
|
581
583
|
</div>
|
|
582
584
|
) : null}
|
|
@@ -594,8 +596,8 @@ const DefaultNumber = ({
|
|
|
594
596
|
onChange(parser ? parseFloat(parsedValue) : parseFloat(e.target.value), e);
|
|
595
597
|
if (cacheKey) sessionStorage.setItem(cacheKey, parsedValue);
|
|
596
598
|
}}
|
|
597
|
-
className={
|
|
598
|
-
`
|
|
599
|
+
className={cn(
|
|
600
|
+
cn(inputBase, `text-foreground duration-300 focus:border-primary focus:outline-hidden ${icon && "pl-12"}`),
|
|
599
601
|
statusClass,
|
|
600
602
|
inputClassName,
|
|
601
603
|
)}
|
|
@@ -603,7 +605,7 @@ const DefaultNumber = ({
|
|
|
603
605
|
</div>
|
|
604
606
|
|
|
605
607
|
{invalidMessage ? (
|
|
606
|
-
<div className="absolute -bottom-4 animate-fadeIn text-
|
|
608
|
+
<div className="absolute -bottom-4 animate-fadeIn text-destructive text-xs">{invalidMessage}</div>
|
|
607
609
|
) : null}
|
|
608
610
|
</div>
|
|
609
611
|
);
|
|
@@ -621,7 +623,7 @@ const DefaultCheckbox = ({ checked, onChange, className, ...rest }: CheckboxProp
|
|
|
621
623
|
{...rest}
|
|
622
624
|
type="checkbox"
|
|
623
625
|
checked={checked}
|
|
624
|
-
className={
|
|
626
|
+
className={cn("checkbox", className)}
|
|
625
627
|
onChange={(e) => {
|
|
626
628
|
onChange(e.target.checked, e);
|
|
627
629
|
}}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { getEnv } from "akanjs/base";
|
|
3
|
-
import {
|
|
3
|
+
import { cn, DEFAULT_BOTTOM_INSET, debugFrame, type FrameSlotRegistration, usePathCtx } from "akanjs/client";
|
|
4
4
|
import { type ReactNode, useLayoutEffect, useRef, useState } from "react";
|
|
5
5
|
|
|
6
6
|
import { Portal } from "../Portal";
|
|
@@ -102,7 +102,7 @@ export const BottomInset = ({
|
|
|
102
102
|
ref={contentRef}
|
|
103
103
|
data-akan-frame-slot="bottomInset"
|
|
104
104
|
data-akan-frame-role={frameRole}
|
|
105
|
-
className={
|
|
105
|
+
className={cn("pointer-events-auto w-full", className)}
|
|
106
106
|
>
|
|
107
107
|
{children}
|
|
108
108
|
</div>
|
package/ui/Layout/BottomTab.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { cn, usePage } from "akanjs/client";
|
|
3
3
|
import { useEffect, useState } from "react";
|
|
4
4
|
|
|
5
5
|
import { Link } from "../Link";
|
|
@@ -47,8 +47,8 @@ export const BottomTab = ({ className, tabs, height = 64 }: BottomTabProps) => {
|
|
|
47
47
|
frameSource="bottomTab"
|
|
48
48
|
>
|
|
49
49
|
<div
|
|
50
|
-
className={
|
|
51
|
-
`flex size-full items-center justify-around rounded-t-xl border border-
|
|
50
|
+
className={cn(
|
|
51
|
+
`flex size-full items-center justify-around rounded-t-xl border border-muted border-b-0 bg-background text-foreground`,
|
|
52
52
|
className,
|
|
53
53
|
)}
|
|
54
54
|
>
|
|
@@ -61,10 +61,10 @@ export const BottomTab = ({ className, tabs, height = 64 }: BottomTabProps) => {
|
|
|
61
61
|
isActiveTab(tab.href) ? "" : "opacity-60"
|
|
62
62
|
}`}
|
|
63
63
|
>
|
|
64
|
-
<div className="
|
|
64
|
+
<div className="relative inline-flex w-max">
|
|
65
65
|
{isActiveTab(tab.href) ? (tab.activeIcon ?? tab.icon) : tab.icon}
|
|
66
66
|
{tab.notiCount && tab.notiCount > 0 ? (
|
|
67
|
-
<div className="
|
|
67
|
+
<div className="absolute top-0 right-0 z-[1] flex size-2 translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full bg-secondary text-[10px] text-background"></div>
|
|
68
68
|
) : null}
|
|
69
69
|
</div>
|
|
70
70
|
<span>{tab.name}</span>
|
package/ui/Layout/Header.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { cn } from "akanjs/client";
|
|
3
3
|
import { type ReactNode, useEffect, useRef, useState } from "react";
|
|
4
4
|
|
|
5
5
|
export interface HeaderProps {
|
|
@@ -25,10 +25,10 @@ export const Header = ({ className, type, children, height = 40 }: HeaderProps)
|
|
|
25
25
|
}, []);
|
|
26
26
|
return (
|
|
27
27
|
<div
|
|
28
|
-
className={
|
|
28
|
+
className={cn(
|
|
29
29
|
`fixed top-0 z-[9] flex duration-300 ${
|
|
30
30
|
!visible ? "md:-translate-y-full" : ""
|
|
31
|
-
} w-full bg-
|
|
31
|
+
} w-full bg-background shadow-sm backdrop-blur-lg`,
|
|
32
32
|
className,
|
|
33
33
|
)}
|
|
34
34
|
>
|
package/ui/Layout/LeftSider.tsx
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { cn } from "akanjs/client";
|
|
3
3
|
import type { ReactNode } from "react";
|
|
4
4
|
import { BiX } from "react-icons/bi";
|
|
5
|
+
import { buttonRecipe } from "../Button";
|
|
5
6
|
|
|
6
7
|
export interface LeftSiderProps {
|
|
7
8
|
className?: string;
|
|
@@ -13,16 +14,16 @@ export interface LeftSiderProps {
|
|
|
13
14
|
export const LeftSider = ({ className, children, open, width, onCancel }: LeftSiderProps) => {
|
|
14
15
|
return (
|
|
15
16
|
<div
|
|
16
|
-
className={
|
|
17
|
-
"absolute top-0 border-
|
|
18
|
-
|
|
17
|
+
className={cn(
|
|
18
|
+
"absolute top-0 border-muted border-r bg-background transition-all duration-150",
|
|
19
|
+
open ? "translate-x-0" : "translate-x-[-100%]",
|
|
19
20
|
className,
|
|
20
21
|
)}
|
|
21
22
|
style={{ width }}
|
|
22
23
|
>
|
|
23
24
|
{children}
|
|
24
25
|
<button
|
|
25
|
-
className="
|
|
26
|
+
className={buttonRecipe({ variant: "ghost", size: "icon" }, "absolute top-0 right-0")}
|
|
26
27
|
onClick={() => {
|
|
27
28
|
onCancel();
|
|
28
29
|
}}
|
package/ui/Layout/Navbar.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { getEnv } from "akanjs/base";
|
|
3
|
-
import {
|
|
3
|
+
import { cn, DEFAULT_TOP_INSET, debugFrame, type TransitionType, usePathCtx } from "akanjs/client";
|
|
4
4
|
import { type ReactNode, useLayoutEffect } from "react";
|
|
5
5
|
import { BiChevronLeft, BiX } from "react-icons/bi";
|
|
6
6
|
|
|
@@ -44,17 +44,7 @@ export const Navbar = ({ back = false, className, height, children, title, left,
|
|
|
44
44
|
return (
|
|
45
45
|
<>
|
|
46
46
|
<Portal id={`topInsetContent${suffix}`}>
|
|
47
|
-
<div
|
|
48
|
-
className={clsx(
|
|
49
|
-
"flex size-full items-center px-5",
|
|
50
|
-
{
|
|
51
|
-
"pl-14": back,
|
|
52
|
-
},
|
|
53
|
-
className,
|
|
54
|
-
)}
|
|
55
|
-
>
|
|
56
|
-
{children}
|
|
57
|
-
</div>
|
|
47
|
+
<div className={cn("flex size-full items-center px-5", back && "pl-14", className)}>{children}</div>
|
|
58
48
|
</Portal>
|
|
59
49
|
{back ? (
|
|
60
50
|
<Portal id={`topLeftActionContent${suffix}`}>
|
package/ui/Layout/RightSider.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { cn } from "akanjs/client";
|
|
3
3
|
import type { ReactNode } from "react";
|
|
4
4
|
import { AiOutlineClose } from "react-icons/ai";
|
|
5
5
|
|
|
@@ -14,9 +14,10 @@ export interface RightSiderProps {
|
|
|
14
14
|
export const RightSider = ({ className, children, open, title, width, onCancel }: RightSiderProps) => {
|
|
15
15
|
return (
|
|
16
16
|
<div
|
|
17
|
-
className={
|
|
18
|
-
"group absolute top-0 right-0 overflow-y-auto border-
|
|
19
|
-
|
|
17
|
+
className={cn(
|
|
18
|
+
"group absolute top-0 right-0 overflow-y-auto border-muted border-l bg-background pt-14 transition-all duration-150",
|
|
19
|
+
open && "translate-x-0",
|
|
20
|
+
!open && "translate-x-[100%]",
|
|
20
21
|
className,
|
|
21
22
|
)}
|
|
22
23
|
style={{ width }}
|
|
@@ -24,10 +25,11 @@ export const RightSider = ({ className, children, open, title, width, onCancel }
|
|
|
24
25
|
{children}
|
|
25
26
|
<div className="absolute top-2 left-4 flex items-center gap-4 pt-2 text-xl">
|
|
26
27
|
<div
|
|
27
|
-
className={
|
|
28
|
-
"
|
|
29
|
-
"opacity-
|
|
30
|
-
|
|
28
|
+
className={cn(
|
|
29
|
+
"cursor-pointer border-muted bg-background transition-all duration-150",
|
|
30
|
+
open && "opacity-100",
|
|
31
|
+
!open && "opacity-0",
|
|
32
|
+
)}
|
|
31
33
|
onClick={() => {
|
|
32
34
|
onCancel();
|
|
33
35
|
}}
|
package/ui/Layout/Sider.tsx
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { cn } from "akanjs/client";
|
|
3
3
|
import { st } from "akanjs/store";
|
|
4
4
|
import { animated } from "akanjs/ui";
|
|
5
5
|
import { type ReactNode, useEffect, useState } from "react";
|
|
6
6
|
import { AiOutlineMenu } from "react-icons/ai";
|
|
7
7
|
import { BiX } from "react-icons/bi";
|
|
8
8
|
import { useSpring } from "react-spring";
|
|
9
|
+
import { buttonRecipe } from "../Button";
|
|
9
10
|
|
|
10
11
|
export interface SiderProps {
|
|
11
12
|
className?: string;
|
|
@@ -32,7 +33,7 @@ export const Sider = ({ className, bgClassName, children }: SiderProps) => {
|
|
|
32
33
|
return (
|
|
33
34
|
<>
|
|
34
35
|
<button
|
|
35
|
-
className="
|
|
36
|
+
className={buttonRecipe({ variant: "ghost" })}
|
|
36
37
|
onClick={() => {
|
|
37
38
|
setIsOpen(true);
|
|
38
39
|
}}
|
|
@@ -43,7 +44,7 @@ export const Sider = ({ className, bgClassName, children }: SiderProps) => {
|
|
|
43
44
|
{isOpen ? (
|
|
44
45
|
<animated.div
|
|
45
46
|
style={overlayAnimation}
|
|
46
|
-
className={
|
|
47
|
+
className={cn("fixed inset-0 z-40 h-screen w-screen", bgClassName)}
|
|
47
48
|
onClick={() => {
|
|
48
49
|
setIsOpen(false);
|
|
49
50
|
}}
|
|
@@ -52,7 +53,7 @@ export const Sider = ({ className, bgClassName, children }: SiderProps) => {
|
|
|
52
53
|
|
|
53
54
|
<animated.div
|
|
54
55
|
style={siderAnimation}
|
|
55
|
-
className={
|
|
56
|
+
className={cn("fixed top-0 left-0 z-50 h-full w-3/4 bg-muted p-4 text-foreground md:w-80", className)}
|
|
56
57
|
>
|
|
57
58
|
<button
|
|
58
59
|
className="absolute top-4 left-4 text-lg"
|
package/ui/Layout/Template.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { cn } from "akanjs/client";
|
|
2
2
|
|
|
3
3
|
export interface TemplateProps {
|
|
4
4
|
/** Additional classes merged with the default vertical form/template spacing. */
|
|
@@ -7,5 +7,5 @@ export interface TemplateProps {
|
|
|
7
7
|
children?: React.ReactNode;
|
|
8
8
|
}
|
|
9
9
|
export const Template = ({ className, children }: TemplateProps) => {
|
|
10
|
-
return <div className={
|
|
10
|
+
return <div className={cn("flex w-full flex-col gap-6 p-2", className)}>{children}</div>;
|
|
11
11
|
};
|
package/ui/Layout/TopInset.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { getEnv } from "akanjs/base";
|
|
3
|
-
import {
|
|
3
|
+
import { cn, DEFAULT_TOP_INSET, debugFrame, usePathCtx } from "akanjs/client";
|
|
4
4
|
import { type ReactNode, useLayoutEffect } from "react";
|
|
5
5
|
|
|
6
6
|
import { Portal } from "../Portal";
|
|
@@ -34,7 +34,7 @@ export const TopInset = ({ className, children, estimatedHeight = DEFAULT_TOP_IN
|
|
|
34
34
|
|
|
35
35
|
return (
|
|
36
36
|
<Portal id={`topInsetContent${suffix}`}>
|
|
37
|
-
<div data-akan-frame-slot="topInset" data-akan-frame-role="topChrome" className={
|
|
37
|
+
<div data-akan-frame-slot="topInset" data-akan-frame-role="topChrome" className={cn("size-full", className)}>
|
|
38
38
|
{children}
|
|
39
39
|
</div>
|
|
40
40
|
</Portal>
|
package/ui/Layout/Unit.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { cn } from "akanjs/client";
|
|
2
2
|
|
|
3
3
|
import { Link } from "../Link";
|
|
4
4
|
|
|
@@ -13,7 +13,7 @@ export interface UnitProps {
|
|
|
13
13
|
export const Unit = ({ className, children, href }: UnitProps) => {
|
|
14
14
|
return (
|
|
15
15
|
<Link href={href}>
|
|
16
|
-
<div className={
|
|
16
|
+
<div className={cn("flex w-full flex-col gap-2 p-4", !!href && "cursor-pointer", className)}>{children}</div>
|
|
17
17
|
</Link>
|
|
18
18
|
);
|
|
19
19
|
};
|
package/ui/Layout/View.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { cn } from "akanjs/client";
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
3
|
|
|
4
4
|
export interface ViewProps {
|
|
@@ -8,5 +8,5 @@ export interface ViewProps {
|
|
|
8
8
|
children: ReactNode;
|
|
9
9
|
}
|
|
10
10
|
export const View = ({ className, children }: ViewProps) => {
|
|
11
|
-
return <div className={
|
|
11
|
+
return <div className={cn("flex size-full max-w-5xl flex-col gap-6 px-2", className)}>{children}</div>;
|
|
12
12
|
};
|
package/ui/Layout/Zone.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { cn } from "akanjs/client";
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
3
|
|
|
4
4
|
export interface ZoneProps {
|
|
@@ -6,5 +6,5 @@ export interface ZoneProps {
|
|
|
6
6
|
children: ReactNode;
|
|
7
7
|
}
|
|
8
8
|
export const Zone = ({ className, children }: ZoneProps) => {
|
|
9
|
-
return <div className={
|
|
9
|
+
return <div className={cn("flex size-full max-w-5xl flex-col gap-6 px-2", className)}>{children}</div>;
|
|
10
10
|
};
|
package/ui/Link/Back.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { cn, router } from "akanjs/client";
|
|
3
3
|
import type { ReactNode } from "react";
|
|
4
4
|
|
|
5
5
|
interface BackProps {
|
|
@@ -8,7 +8,7 @@ interface BackProps {
|
|
|
8
8
|
}
|
|
9
9
|
export default function Back({ className, children }: BackProps) {
|
|
10
10
|
return (
|
|
11
|
-
<div className={
|
|
11
|
+
<div className={cn("cursor-pointer", className)} onClick={() => router.back()}>
|
|
12
12
|
{children}
|
|
13
13
|
</div>
|
|
14
14
|
);
|
package/ui/Link/Close.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { cn } from "akanjs/client";
|
|
3
3
|
import type { ReactNode } from "react";
|
|
4
4
|
|
|
5
5
|
interface CloseProps {
|
|
@@ -9,7 +9,7 @@ interface CloseProps {
|
|
|
9
9
|
export default function Close({ className, children }: CloseProps) {
|
|
10
10
|
return (
|
|
11
11
|
<div
|
|
12
|
-
className={
|
|
12
|
+
className={cn("cursor-pointer", className)}
|
|
13
13
|
onClick={() => {
|
|
14
14
|
window.close();
|
|
15
15
|
}}
|
package/ui/Link/CsrLink.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { cn, getPathInfo, router, usePage, usePathCtx } from "akanjs/client";
|
|
4
4
|
import { loadCapacitorBrowser } from "akanjs/client/capacitor";
|
|
5
5
|
import { st } from "akanjs/store";
|
|
6
6
|
|
|
@@ -23,9 +23,11 @@ export default function CsrLink({
|
|
|
23
23
|
const { path, hash } = getPathInfo(href, lang, prefix ?? "");
|
|
24
24
|
return (
|
|
25
25
|
<a
|
|
26
|
-
className={
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
className={cn(
|
|
27
|
+
"cursor-pointer",
|
|
28
|
+
className,
|
|
29
|
+
(activeExact ? currentPath === path : currentPath.startsWith(path)) && (activeClassName ?? ""),
|
|
30
|
+
)}
|
|
29
31
|
onClick={() => {
|
|
30
32
|
const isExternal = href.startsWith("http") || href.startsWith("mailto:") || href.startsWith("tel:");
|
|
31
33
|
const isHash = href.startsWith("#");
|
package/ui/Link/Lang.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import { cn, router } from "akanjs/client";
|
|
3
3
|
import type { ReactNode } from "react";
|
|
4
4
|
|
|
5
5
|
interface LangProps {
|
|
@@ -9,7 +9,7 @@ interface LangProps {
|
|
|
9
9
|
}
|
|
10
10
|
export default function Lang({ className, lang, children }: LangProps) {
|
|
11
11
|
return (
|
|
12
|
-
<div className={
|
|
12
|
+
<div className={cn("cursor-pointer", className)} onClick={() => router.setLang(lang)}>
|
|
13
13
|
{children}
|
|
14
14
|
</div>
|
|
15
15
|
);
|