@idevconn/create-icore 0.10.1 → 0.10.2
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/dist/cli.js +128 -8
- package/dist/index.cjs +128 -8
- package/dist/index.js +128 -8
- package/package.json +1 -1
- package/templates/apps/templates/client-antd/src/components/layout/LayoutHeader.tsx +2 -2
- package/templates/apps/templates/client-mui/src/components/layout/LayoutHeader.tsx +1 -1
- package/templates/apps/templates/client-shadcn/src/components/layout/LayoutHeader.tsx +2 -2
- package/templates/apps/templates/client-shadcn/src/components/layout/LayoutSider.tsx +7 -3
- package/templates/apps/templates/client-shadcn/src/routes/index.tsx +2 -2
- package/templates/apps/templates/client-shadcn/vite.config.mts +18 -1
package/dist/cli.js
CHANGED
|
@@ -410,6 +410,7 @@ async function rewriteRootPackageJson(targetDir, opts) {
|
|
|
410
410
|
const pkg = JSON.parse(raw);
|
|
411
411
|
pkg["name"] = opts.projectName;
|
|
412
412
|
pkg["version"] = "0.0.1";
|
|
413
|
+
pkg["icoreVersion"] = true ? "0.10.2" : "unknown";
|
|
413
414
|
pkg["private"] = true;
|
|
414
415
|
delete pkg.description;
|
|
415
416
|
const transportDeps = TRANSPORT_DEPS[opts.transport];
|
|
@@ -677,6 +678,7 @@ var AUTH_ONLY_PATHS = [
|
|
|
677
678
|
"apps/api/src/app/abilities",
|
|
678
679
|
"libs/shared/src/abilities",
|
|
679
680
|
"apps/client/src/components/auth",
|
|
681
|
+
"apps/client/src/components/AccessDeniedPage.tsx",
|
|
680
682
|
"apps/client/src/routes/login.tsx",
|
|
681
683
|
"apps/client/src/routes/auth.callback.tsx",
|
|
682
684
|
"apps/client/src/routes/auth.oauth.callback.tsx",
|
|
@@ -813,6 +815,121 @@ export * from './lib/draft/index.js';
|
|
|
813
815
|
export * from './lib/landing/LandingPage.js';
|
|
814
816
|
export * from './lib/stores/theme.store.js';
|
|
815
817
|
`;
|
|
818
|
+
var SHADCN_PAGE_LAYOUT_TSX = `import type { ReactNode } from 'react';
|
|
819
|
+
import { useTranslation } from 'react-i18next';
|
|
820
|
+
import { useDraft, useLoading } from '@icore/template-shared';
|
|
821
|
+
|
|
822
|
+
interface PageLayoutProps {
|
|
823
|
+
title: string;
|
|
824
|
+
description?: string;
|
|
825
|
+
actions?: ReactNode;
|
|
826
|
+
children: ReactNode;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
export function PageLayout({ title, description, actions, children }: PageLayoutProps) {
|
|
830
|
+
const { t } = useTranslation();
|
|
831
|
+
const isLoading = useLoading();
|
|
832
|
+
|
|
833
|
+
useDraft(false);
|
|
834
|
+
|
|
835
|
+
return (
|
|
836
|
+
<div className="p-4 md:p-6 space-y-4">
|
|
837
|
+
<div className="flex items-start justify-between gap-3">
|
|
838
|
+
<div>
|
|
839
|
+
<h1 className="text-xl font-semibold text-foreground">{title}</h1>
|
|
840
|
+
{description && <p className="text-sm text-muted-foreground mt-1">{description}</p>}
|
|
841
|
+
</div>
|
|
842
|
+
{actions && <div>{actions}</div>}
|
|
843
|
+
</div>
|
|
844
|
+
|
|
845
|
+
{isLoading && (
|
|
846
|
+
<div
|
|
847
|
+
role="status"
|
|
848
|
+
aria-label={t('common.loading')}
|
|
849
|
+
className="fixed inset-0 z-50 flex items-center justify-center bg-background/60 backdrop-blur-sm"
|
|
850
|
+
>
|
|
851
|
+
<div className="h-8 w-8 animate-spin rounded-full border-2 border-primary border-t-transparent" />
|
|
852
|
+
</div>
|
|
853
|
+
)}
|
|
854
|
+
|
|
855
|
+
{children}
|
|
856
|
+
</div>
|
|
857
|
+
);
|
|
858
|
+
}
|
|
859
|
+
`;
|
|
860
|
+
var ANTD_PAGE_LAYOUT_TSX = `import type { ReactNode } from 'react';
|
|
861
|
+
import { Descriptions, Spin } from 'antd';
|
|
862
|
+
import { useDraft, useLoading } from '@icore/template-shared';
|
|
863
|
+
|
|
864
|
+
export interface PageLayoutProps {
|
|
865
|
+
title: ReactNode;
|
|
866
|
+
description?: ReactNode;
|
|
867
|
+
extra?: ReactNode;
|
|
868
|
+
children?: ReactNode;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
export function PageLayout({ title, description, extra, children }: PageLayoutProps) {
|
|
872
|
+
useDraft(false);
|
|
873
|
+
const loading = useLoading();
|
|
874
|
+
|
|
875
|
+
return (
|
|
876
|
+
<div style={{ padding: 24 }}>
|
|
877
|
+
<Descriptions title={title} extra={extra} style={{ marginBottom: 16 }}>
|
|
878
|
+
{description ? <Descriptions.Item>{description}</Descriptions.Item> : null}
|
|
879
|
+
</Descriptions>
|
|
880
|
+
<Spin spinning={loading}>
|
|
881
|
+
<div>{children}</div>
|
|
882
|
+
</Spin>
|
|
883
|
+
</div>
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
`;
|
|
887
|
+
var MUI_PAGE_LAYOUT_TSX = `import type { ReactNode } from 'react';
|
|
888
|
+
import { Box, LinearProgress, Stack, Typography } from '@mui/material';
|
|
889
|
+
import { useDraft, useLoading } from '@icore/template-shared';
|
|
890
|
+
|
|
891
|
+
export interface PageLayoutProps {
|
|
892
|
+
title: ReactNode;
|
|
893
|
+
description?: ReactNode;
|
|
894
|
+
extra?: ReactNode;
|
|
895
|
+
children?: ReactNode;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
export function PageLayout({ title, description, extra, children }: PageLayoutProps) {
|
|
899
|
+
useDraft(false);
|
|
900
|
+
const loading = useLoading();
|
|
901
|
+
|
|
902
|
+
return (
|
|
903
|
+
<Box sx={{ p: 3 }}>
|
|
904
|
+
<Stack
|
|
905
|
+
direction="row"
|
|
906
|
+
justifyContent="space-between"
|
|
907
|
+
alignItems="flex-start"
|
|
908
|
+
spacing={2}
|
|
909
|
+
mb={3}
|
|
910
|
+
>
|
|
911
|
+
<Box>
|
|
912
|
+
<Typography variant="h4" component="h1">
|
|
913
|
+
{title}
|
|
914
|
+
</Typography>
|
|
915
|
+
{description ? (
|
|
916
|
+
<Typography variant="body2" color="text.secondary" mt={0.5}>
|
|
917
|
+
{description}
|
|
918
|
+
</Typography>
|
|
919
|
+
) : null}
|
|
920
|
+
</Box>
|
|
921
|
+
{extra ? (
|
|
922
|
+
<Stack direction="row" spacing={1}>
|
|
923
|
+
{extra}
|
|
924
|
+
</Stack>
|
|
925
|
+
) : null}
|
|
926
|
+
</Stack>
|
|
927
|
+
{loading ? <LinearProgress sx={{ mb: 2 }} /> : null}
|
|
928
|
+
<Box>{children}</Box>
|
|
929
|
+
</Box>
|
|
930
|
+
);
|
|
931
|
+
}
|
|
932
|
+
`;
|
|
816
933
|
var SHADCN_MAIN_TSX = `import './globals.css';
|
|
817
934
|
import { StrictMode } from 'react';
|
|
818
935
|
import { createRoot } from 'react-dom/client';
|
|
@@ -913,7 +1030,7 @@ export const Route = createFileRoute('/')({
|
|
|
913
1030
|
),
|
|
914
1031
|
});
|
|
915
1032
|
`;
|
|
916
|
-
var SHADCN_LAYOUT_HEADER_TSX = `import { setStoredLocale, type IcoreLocale } from '@icore/template-shared';
|
|
1033
|
+
var SHADCN_LAYOUT_HEADER_TSX = `import { setStoredLocale, type IcoreLocale, i18next } from '@icore/template-shared';
|
|
917
1034
|
import { ThemeToggle } from '../ThemeToggle';
|
|
918
1035
|
|
|
919
1036
|
const LOCALES: { code: IcoreLocale; label: string }[] = [
|
|
@@ -925,7 +1042,7 @@ const LOCALES: { code: IcoreLocale; label: string }[] = [
|
|
|
925
1042
|
export function LayoutHeader() {
|
|
926
1043
|
function handleLocale(code: IcoreLocale) {
|
|
927
1044
|
setStoredLocale(code);
|
|
928
|
-
|
|
1045
|
+
void i18next.changeLanguage(code);
|
|
929
1046
|
}
|
|
930
1047
|
|
|
931
1048
|
return (
|
|
@@ -1059,7 +1176,7 @@ export const Route = createFileRoute('/')({
|
|
|
1059
1176
|
});
|
|
1060
1177
|
`;
|
|
1061
1178
|
var ANTD_LAYOUT_HEADER_TSX = `import { Button, Layout, Space } from 'antd';
|
|
1062
|
-
import { setStoredLocale, type IcoreLocale } from '@icore/template-shared';
|
|
1179
|
+
import { setStoredLocale, type IcoreLocale, i18next } from '@icore/template-shared';
|
|
1063
1180
|
import { ThemeToggle } from '../ThemeToggle';
|
|
1064
1181
|
|
|
1065
1182
|
const APP_VERSION = (import.meta.env.VITE_APP_VERSION as string | undefined) ?? '0.0.0-dev';
|
|
@@ -1073,7 +1190,7 @@ const LOCALES: { code: IcoreLocale; label: string }[] = [
|
|
|
1073
1190
|
export function LayoutHeader() {
|
|
1074
1191
|
function handleLocale(code: IcoreLocale) {
|
|
1075
1192
|
setStoredLocale(code);
|
|
1076
|
-
|
|
1193
|
+
void i18next.changeLanguage(code);
|
|
1077
1194
|
}
|
|
1078
1195
|
|
|
1079
1196
|
return (
|
|
@@ -1245,7 +1362,7 @@ export function LayoutHeader() {
|
|
|
1245
1362
|
|
|
1246
1363
|
function handleLocale(code: IcoreLocale) {
|
|
1247
1364
|
setStoredLocale(code);
|
|
1248
|
-
|
|
1365
|
+
void i18n.changeLanguage(code);
|
|
1249
1366
|
}
|
|
1250
1367
|
|
|
1251
1368
|
return (
|
|
@@ -1289,19 +1406,22 @@ var UI_VARIANTS = {
|
|
|
1289
1406
|
"apps/client/src/main.tsx": SHADCN_MAIN_TSX,
|
|
1290
1407
|
"apps/client/src/routes/_dashboard.tsx": SHADCN_DASHBOARD_TSX,
|
|
1291
1408
|
"apps/client/src/routes/index.tsx": SHADCN_INDEX_TSX,
|
|
1292
|
-
"apps/client/src/components/layout/LayoutHeader.tsx": SHADCN_LAYOUT_HEADER_TSX
|
|
1409
|
+
"apps/client/src/components/layout/LayoutHeader.tsx": SHADCN_LAYOUT_HEADER_TSX,
|
|
1410
|
+
"apps/client/src/components/PageLayout.tsx": SHADCN_PAGE_LAYOUT_TSX
|
|
1293
1411
|
},
|
|
1294
1412
|
antd: {
|
|
1295
1413
|
"apps/client/src/main.tsx": ANTD_MAIN_TSX,
|
|
1296
1414
|
"apps/client/src/routes/_dashboard.tsx": ANTD_DASHBOARD_TSX,
|
|
1297
1415
|
"apps/client/src/routes/index.tsx": ANTD_INDEX_TSX,
|
|
1298
|
-
"apps/client/src/components/layout/LayoutHeader.tsx": ANTD_LAYOUT_HEADER_TSX
|
|
1416
|
+
"apps/client/src/components/layout/LayoutHeader.tsx": ANTD_LAYOUT_HEADER_TSX,
|
|
1417
|
+
"apps/client/src/components/PageLayout.tsx": ANTD_PAGE_LAYOUT_TSX
|
|
1299
1418
|
},
|
|
1300
1419
|
mui: {
|
|
1301
1420
|
"apps/client/src/main.tsx": MUI_MAIN_TSX,
|
|
1302
1421
|
"apps/client/src/routes/_dashboard.tsx": MUI_DASHBOARD_TSX,
|
|
1303
1422
|
"apps/client/src/routes/index.tsx": MUI_INDEX_TSX,
|
|
1304
|
-
"apps/client/src/components/layout/LayoutHeader.tsx": MUI_LAYOUT_HEADER_TSX
|
|
1423
|
+
"apps/client/src/components/layout/LayoutHeader.tsx": MUI_LAYOUT_HEADER_TSX,
|
|
1424
|
+
"apps/client/src/components/PageLayout.tsx": MUI_PAGE_LAYOUT_TSX
|
|
1305
1425
|
}
|
|
1306
1426
|
};
|
|
1307
1427
|
async function applyAuthNoneVariants(targetDir, ui) {
|
package/dist/index.cjs
CHANGED
|
@@ -121,6 +121,7 @@ async function rewriteRootPackageJson(targetDir, opts) {
|
|
|
121
121
|
const pkg = JSON.parse(raw);
|
|
122
122
|
pkg["name"] = opts.projectName;
|
|
123
123
|
pkg["version"] = "0.0.1";
|
|
124
|
+
pkg["icoreVersion"] = typeof ICORE_OWN_VERSION !== "undefined" ? ICORE_OWN_VERSION : "unknown";
|
|
124
125
|
pkg["private"] = true;
|
|
125
126
|
delete pkg.description;
|
|
126
127
|
const transportDeps = TRANSPORT_DEPS[opts.transport];
|
|
@@ -388,6 +389,7 @@ var AUTH_ONLY_PATHS = [
|
|
|
388
389
|
"apps/api/src/app/abilities",
|
|
389
390
|
"libs/shared/src/abilities",
|
|
390
391
|
"apps/client/src/components/auth",
|
|
392
|
+
"apps/client/src/components/AccessDeniedPage.tsx",
|
|
391
393
|
"apps/client/src/routes/login.tsx",
|
|
392
394
|
"apps/client/src/routes/auth.callback.tsx",
|
|
393
395
|
"apps/client/src/routes/auth.oauth.callback.tsx",
|
|
@@ -524,6 +526,121 @@ export * from './lib/draft/index.js';
|
|
|
524
526
|
export * from './lib/landing/LandingPage.js';
|
|
525
527
|
export * from './lib/stores/theme.store.js';
|
|
526
528
|
`;
|
|
529
|
+
var SHADCN_PAGE_LAYOUT_TSX = `import type { ReactNode } from 'react';
|
|
530
|
+
import { useTranslation } from 'react-i18next';
|
|
531
|
+
import { useDraft, useLoading } from '@icore/template-shared';
|
|
532
|
+
|
|
533
|
+
interface PageLayoutProps {
|
|
534
|
+
title: string;
|
|
535
|
+
description?: string;
|
|
536
|
+
actions?: ReactNode;
|
|
537
|
+
children: ReactNode;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
export function PageLayout({ title, description, actions, children }: PageLayoutProps) {
|
|
541
|
+
const { t } = useTranslation();
|
|
542
|
+
const isLoading = useLoading();
|
|
543
|
+
|
|
544
|
+
useDraft(false);
|
|
545
|
+
|
|
546
|
+
return (
|
|
547
|
+
<div className="p-4 md:p-6 space-y-4">
|
|
548
|
+
<div className="flex items-start justify-between gap-3">
|
|
549
|
+
<div>
|
|
550
|
+
<h1 className="text-xl font-semibold text-foreground">{title}</h1>
|
|
551
|
+
{description && <p className="text-sm text-muted-foreground mt-1">{description}</p>}
|
|
552
|
+
</div>
|
|
553
|
+
{actions && <div>{actions}</div>}
|
|
554
|
+
</div>
|
|
555
|
+
|
|
556
|
+
{isLoading && (
|
|
557
|
+
<div
|
|
558
|
+
role="status"
|
|
559
|
+
aria-label={t('common.loading')}
|
|
560
|
+
className="fixed inset-0 z-50 flex items-center justify-center bg-background/60 backdrop-blur-sm"
|
|
561
|
+
>
|
|
562
|
+
<div className="h-8 w-8 animate-spin rounded-full border-2 border-primary border-t-transparent" />
|
|
563
|
+
</div>
|
|
564
|
+
)}
|
|
565
|
+
|
|
566
|
+
{children}
|
|
567
|
+
</div>
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
`;
|
|
571
|
+
var ANTD_PAGE_LAYOUT_TSX = `import type { ReactNode } from 'react';
|
|
572
|
+
import { Descriptions, Spin } from 'antd';
|
|
573
|
+
import { useDraft, useLoading } from '@icore/template-shared';
|
|
574
|
+
|
|
575
|
+
export interface PageLayoutProps {
|
|
576
|
+
title: ReactNode;
|
|
577
|
+
description?: ReactNode;
|
|
578
|
+
extra?: ReactNode;
|
|
579
|
+
children?: ReactNode;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
export function PageLayout({ title, description, extra, children }: PageLayoutProps) {
|
|
583
|
+
useDraft(false);
|
|
584
|
+
const loading = useLoading();
|
|
585
|
+
|
|
586
|
+
return (
|
|
587
|
+
<div style={{ padding: 24 }}>
|
|
588
|
+
<Descriptions title={title} extra={extra} style={{ marginBottom: 16 }}>
|
|
589
|
+
{description ? <Descriptions.Item>{description}</Descriptions.Item> : null}
|
|
590
|
+
</Descriptions>
|
|
591
|
+
<Spin spinning={loading}>
|
|
592
|
+
<div>{children}</div>
|
|
593
|
+
</Spin>
|
|
594
|
+
</div>
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
`;
|
|
598
|
+
var MUI_PAGE_LAYOUT_TSX = `import type { ReactNode } from 'react';
|
|
599
|
+
import { Box, LinearProgress, Stack, Typography } from '@mui/material';
|
|
600
|
+
import { useDraft, useLoading } from '@icore/template-shared';
|
|
601
|
+
|
|
602
|
+
export interface PageLayoutProps {
|
|
603
|
+
title: ReactNode;
|
|
604
|
+
description?: ReactNode;
|
|
605
|
+
extra?: ReactNode;
|
|
606
|
+
children?: ReactNode;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
export function PageLayout({ title, description, extra, children }: PageLayoutProps) {
|
|
610
|
+
useDraft(false);
|
|
611
|
+
const loading = useLoading();
|
|
612
|
+
|
|
613
|
+
return (
|
|
614
|
+
<Box sx={{ p: 3 }}>
|
|
615
|
+
<Stack
|
|
616
|
+
direction="row"
|
|
617
|
+
justifyContent="space-between"
|
|
618
|
+
alignItems="flex-start"
|
|
619
|
+
spacing={2}
|
|
620
|
+
mb={3}
|
|
621
|
+
>
|
|
622
|
+
<Box>
|
|
623
|
+
<Typography variant="h4" component="h1">
|
|
624
|
+
{title}
|
|
625
|
+
</Typography>
|
|
626
|
+
{description ? (
|
|
627
|
+
<Typography variant="body2" color="text.secondary" mt={0.5}>
|
|
628
|
+
{description}
|
|
629
|
+
</Typography>
|
|
630
|
+
) : null}
|
|
631
|
+
</Box>
|
|
632
|
+
{extra ? (
|
|
633
|
+
<Stack direction="row" spacing={1}>
|
|
634
|
+
{extra}
|
|
635
|
+
</Stack>
|
|
636
|
+
) : null}
|
|
637
|
+
</Stack>
|
|
638
|
+
{loading ? <LinearProgress sx={{ mb: 2 }} /> : null}
|
|
639
|
+
<Box>{children}</Box>
|
|
640
|
+
</Box>
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
`;
|
|
527
644
|
var SHADCN_MAIN_TSX = `import './globals.css';
|
|
528
645
|
import { StrictMode } from 'react';
|
|
529
646
|
import { createRoot } from 'react-dom/client';
|
|
@@ -624,7 +741,7 @@ export const Route = createFileRoute('/')({
|
|
|
624
741
|
),
|
|
625
742
|
});
|
|
626
743
|
`;
|
|
627
|
-
var SHADCN_LAYOUT_HEADER_TSX = `import { setStoredLocale, type IcoreLocale } from '@icore/template-shared';
|
|
744
|
+
var SHADCN_LAYOUT_HEADER_TSX = `import { setStoredLocale, type IcoreLocale, i18next } from '@icore/template-shared';
|
|
628
745
|
import { ThemeToggle } from '../ThemeToggle';
|
|
629
746
|
|
|
630
747
|
const LOCALES: { code: IcoreLocale; label: string }[] = [
|
|
@@ -636,7 +753,7 @@ const LOCALES: { code: IcoreLocale; label: string }[] = [
|
|
|
636
753
|
export function LayoutHeader() {
|
|
637
754
|
function handleLocale(code: IcoreLocale) {
|
|
638
755
|
setStoredLocale(code);
|
|
639
|
-
|
|
756
|
+
void i18next.changeLanguage(code);
|
|
640
757
|
}
|
|
641
758
|
|
|
642
759
|
return (
|
|
@@ -770,7 +887,7 @@ export const Route = createFileRoute('/')({
|
|
|
770
887
|
});
|
|
771
888
|
`;
|
|
772
889
|
var ANTD_LAYOUT_HEADER_TSX = `import { Button, Layout, Space } from 'antd';
|
|
773
|
-
import { setStoredLocale, type IcoreLocale } from '@icore/template-shared';
|
|
890
|
+
import { setStoredLocale, type IcoreLocale, i18next } from '@icore/template-shared';
|
|
774
891
|
import { ThemeToggle } from '../ThemeToggle';
|
|
775
892
|
|
|
776
893
|
const APP_VERSION = (import.meta.env.VITE_APP_VERSION as string | undefined) ?? '0.0.0-dev';
|
|
@@ -784,7 +901,7 @@ const LOCALES: { code: IcoreLocale; label: string }[] = [
|
|
|
784
901
|
export function LayoutHeader() {
|
|
785
902
|
function handleLocale(code: IcoreLocale) {
|
|
786
903
|
setStoredLocale(code);
|
|
787
|
-
|
|
904
|
+
void i18next.changeLanguage(code);
|
|
788
905
|
}
|
|
789
906
|
|
|
790
907
|
return (
|
|
@@ -956,7 +1073,7 @@ export function LayoutHeader() {
|
|
|
956
1073
|
|
|
957
1074
|
function handleLocale(code: IcoreLocale) {
|
|
958
1075
|
setStoredLocale(code);
|
|
959
|
-
|
|
1076
|
+
void i18n.changeLanguage(code);
|
|
960
1077
|
}
|
|
961
1078
|
|
|
962
1079
|
return (
|
|
@@ -1000,19 +1117,22 @@ var UI_VARIANTS = {
|
|
|
1000
1117
|
"apps/client/src/main.tsx": SHADCN_MAIN_TSX,
|
|
1001
1118
|
"apps/client/src/routes/_dashboard.tsx": SHADCN_DASHBOARD_TSX,
|
|
1002
1119
|
"apps/client/src/routes/index.tsx": SHADCN_INDEX_TSX,
|
|
1003
|
-
"apps/client/src/components/layout/LayoutHeader.tsx": SHADCN_LAYOUT_HEADER_TSX
|
|
1120
|
+
"apps/client/src/components/layout/LayoutHeader.tsx": SHADCN_LAYOUT_HEADER_TSX,
|
|
1121
|
+
"apps/client/src/components/PageLayout.tsx": SHADCN_PAGE_LAYOUT_TSX
|
|
1004
1122
|
},
|
|
1005
1123
|
antd: {
|
|
1006
1124
|
"apps/client/src/main.tsx": ANTD_MAIN_TSX,
|
|
1007
1125
|
"apps/client/src/routes/_dashboard.tsx": ANTD_DASHBOARD_TSX,
|
|
1008
1126
|
"apps/client/src/routes/index.tsx": ANTD_INDEX_TSX,
|
|
1009
|
-
"apps/client/src/components/layout/LayoutHeader.tsx": ANTD_LAYOUT_HEADER_TSX
|
|
1127
|
+
"apps/client/src/components/layout/LayoutHeader.tsx": ANTD_LAYOUT_HEADER_TSX,
|
|
1128
|
+
"apps/client/src/components/PageLayout.tsx": ANTD_PAGE_LAYOUT_TSX
|
|
1010
1129
|
},
|
|
1011
1130
|
mui: {
|
|
1012
1131
|
"apps/client/src/main.tsx": MUI_MAIN_TSX,
|
|
1013
1132
|
"apps/client/src/routes/_dashboard.tsx": MUI_DASHBOARD_TSX,
|
|
1014
1133
|
"apps/client/src/routes/index.tsx": MUI_INDEX_TSX,
|
|
1015
|
-
"apps/client/src/components/layout/LayoutHeader.tsx": MUI_LAYOUT_HEADER_TSX
|
|
1134
|
+
"apps/client/src/components/layout/LayoutHeader.tsx": MUI_LAYOUT_HEADER_TSX,
|
|
1135
|
+
"apps/client/src/components/PageLayout.tsx": MUI_PAGE_LAYOUT_TSX
|
|
1016
1136
|
}
|
|
1017
1137
|
};
|
|
1018
1138
|
async function applyAuthNoneVariants(targetDir, ui) {
|
package/dist/index.js
CHANGED
|
@@ -78,6 +78,7 @@ async function rewriteRootPackageJson(targetDir, opts) {
|
|
|
78
78
|
const pkg = JSON.parse(raw);
|
|
79
79
|
pkg["name"] = opts.projectName;
|
|
80
80
|
pkg["version"] = "0.0.1";
|
|
81
|
+
pkg["icoreVersion"] = typeof ICORE_OWN_VERSION !== "undefined" ? ICORE_OWN_VERSION : "unknown";
|
|
81
82
|
pkg["private"] = true;
|
|
82
83
|
delete pkg.description;
|
|
83
84
|
const transportDeps = TRANSPORT_DEPS[opts.transport];
|
|
@@ -345,6 +346,7 @@ var AUTH_ONLY_PATHS = [
|
|
|
345
346
|
"apps/api/src/app/abilities",
|
|
346
347
|
"libs/shared/src/abilities",
|
|
347
348
|
"apps/client/src/components/auth",
|
|
349
|
+
"apps/client/src/components/AccessDeniedPage.tsx",
|
|
348
350
|
"apps/client/src/routes/login.tsx",
|
|
349
351
|
"apps/client/src/routes/auth.callback.tsx",
|
|
350
352
|
"apps/client/src/routes/auth.oauth.callback.tsx",
|
|
@@ -481,6 +483,121 @@ export * from './lib/draft/index.js';
|
|
|
481
483
|
export * from './lib/landing/LandingPage.js';
|
|
482
484
|
export * from './lib/stores/theme.store.js';
|
|
483
485
|
`;
|
|
486
|
+
var SHADCN_PAGE_LAYOUT_TSX = `import type { ReactNode } from 'react';
|
|
487
|
+
import { useTranslation } from 'react-i18next';
|
|
488
|
+
import { useDraft, useLoading } from '@icore/template-shared';
|
|
489
|
+
|
|
490
|
+
interface PageLayoutProps {
|
|
491
|
+
title: string;
|
|
492
|
+
description?: string;
|
|
493
|
+
actions?: ReactNode;
|
|
494
|
+
children: ReactNode;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
export function PageLayout({ title, description, actions, children }: PageLayoutProps) {
|
|
498
|
+
const { t } = useTranslation();
|
|
499
|
+
const isLoading = useLoading();
|
|
500
|
+
|
|
501
|
+
useDraft(false);
|
|
502
|
+
|
|
503
|
+
return (
|
|
504
|
+
<div className="p-4 md:p-6 space-y-4">
|
|
505
|
+
<div className="flex items-start justify-between gap-3">
|
|
506
|
+
<div>
|
|
507
|
+
<h1 className="text-xl font-semibold text-foreground">{title}</h1>
|
|
508
|
+
{description && <p className="text-sm text-muted-foreground mt-1">{description}</p>}
|
|
509
|
+
</div>
|
|
510
|
+
{actions && <div>{actions}</div>}
|
|
511
|
+
</div>
|
|
512
|
+
|
|
513
|
+
{isLoading && (
|
|
514
|
+
<div
|
|
515
|
+
role="status"
|
|
516
|
+
aria-label={t('common.loading')}
|
|
517
|
+
className="fixed inset-0 z-50 flex items-center justify-center bg-background/60 backdrop-blur-sm"
|
|
518
|
+
>
|
|
519
|
+
<div className="h-8 w-8 animate-spin rounded-full border-2 border-primary border-t-transparent" />
|
|
520
|
+
</div>
|
|
521
|
+
)}
|
|
522
|
+
|
|
523
|
+
{children}
|
|
524
|
+
</div>
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
`;
|
|
528
|
+
var ANTD_PAGE_LAYOUT_TSX = `import type { ReactNode } from 'react';
|
|
529
|
+
import { Descriptions, Spin } from 'antd';
|
|
530
|
+
import { useDraft, useLoading } from '@icore/template-shared';
|
|
531
|
+
|
|
532
|
+
export interface PageLayoutProps {
|
|
533
|
+
title: ReactNode;
|
|
534
|
+
description?: ReactNode;
|
|
535
|
+
extra?: ReactNode;
|
|
536
|
+
children?: ReactNode;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
export function PageLayout({ title, description, extra, children }: PageLayoutProps) {
|
|
540
|
+
useDraft(false);
|
|
541
|
+
const loading = useLoading();
|
|
542
|
+
|
|
543
|
+
return (
|
|
544
|
+
<div style={{ padding: 24 }}>
|
|
545
|
+
<Descriptions title={title} extra={extra} style={{ marginBottom: 16 }}>
|
|
546
|
+
{description ? <Descriptions.Item>{description}</Descriptions.Item> : null}
|
|
547
|
+
</Descriptions>
|
|
548
|
+
<Spin spinning={loading}>
|
|
549
|
+
<div>{children}</div>
|
|
550
|
+
</Spin>
|
|
551
|
+
</div>
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
`;
|
|
555
|
+
var MUI_PAGE_LAYOUT_TSX = `import type { ReactNode } from 'react';
|
|
556
|
+
import { Box, LinearProgress, Stack, Typography } from '@mui/material';
|
|
557
|
+
import { useDraft, useLoading } from '@icore/template-shared';
|
|
558
|
+
|
|
559
|
+
export interface PageLayoutProps {
|
|
560
|
+
title: ReactNode;
|
|
561
|
+
description?: ReactNode;
|
|
562
|
+
extra?: ReactNode;
|
|
563
|
+
children?: ReactNode;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
export function PageLayout({ title, description, extra, children }: PageLayoutProps) {
|
|
567
|
+
useDraft(false);
|
|
568
|
+
const loading = useLoading();
|
|
569
|
+
|
|
570
|
+
return (
|
|
571
|
+
<Box sx={{ p: 3 }}>
|
|
572
|
+
<Stack
|
|
573
|
+
direction="row"
|
|
574
|
+
justifyContent="space-between"
|
|
575
|
+
alignItems="flex-start"
|
|
576
|
+
spacing={2}
|
|
577
|
+
mb={3}
|
|
578
|
+
>
|
|
579
|
+
<Box>
|
|
580
|
+
<Typography variant="h4" component="h1">
|
|
581
|
+
{title}
|
|
582
|
+
</Typography>
|
|
583
|
+
{description ? (
|
|
584
|
+
<Typography variant="body2" color="text.secondary" mt={0.5}>
|
|
585
|
+
{description}
|
|
586
|
+
</Typography>
|
|
587
|
+
) : null}
|
|
588
|
+
</Box>
|
|
589
|
+
{extra ? (
|
|
590
|
+
<Stack direction="row" spacing={1}>
|
|
591
|
+
{extra}
|
|
592
|
+
</Stack>
|
|
593
|
+
) : null}
|
|
594
|
+
</Stack>
|
|
595
|
+
{loading ? <LinearProgress sx={{ mb: 2 }} /> : null}
|
|
596
|
+
<Box>{children}</Box>
|
|
597
|
+
</Box>
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
`;
|
|
484
601
|
var SHADCN_MAIN_TSX = `import './globals.css';
|
|
485
602
|
import { StrictMode } from 'react';
|
|
486
603
|
import { createRoot } from 'react-dom/client';
|
|
@@ -581,7 +698,7 @@ export const Route = createFileRoute('/')({
|
|
|
581
698
|
),
|
|
582
699
|
});
|
|
583
700
|
`;
|
|
584
|
-
var SHADCN_LAYOUT_HEADER_TSX = `import { setStoredLocale, type IcoreLocale } from '@icore/template-shared';
|
|
701
|
+
var SHADCN_LAYOUT_HEADER_TSX = `import { setStoredLocale, type IcoreLocale, i18next } from '@icore/template-shared';
|
|
585
702
|
import { ThemeToggle } from '../ThemeToggle';
|
|
586
703
|
|
|
587
704
|
const LOCALES: { code: IcoreLocale; label: string }[] = [
|
|
@@ -593,7 +710,7 @@ const LOCALES: { code: IcoreLocale; label: string }[] = [
|
|
|
593
710
|
export function LayoutHeader() {
|
|
594
711
|
function handleLocale(code: IcoreLocale) {
|
|
595
712
|
setStoredLocale(code);
|
|
596
|
-
|
|
713
|
+
void i18next.changeLanguage(code);
|
|
597
714
|
}
|
|
598
715
|
|
|
599
716
|
return (
|
|
@@ -727,7 +844,7 @@ export const Route = createFileRoute('/')({
|
|
|
727
844
|
});
|
|
728
845
|
`;
|
|
729
846
|
var ANTD_LAYOUT_HEADER_TSX = `import { Button, Layout, Space } from 'antd';
|
|
730
|
-
import { setStoredLocale, type IcoreLocale } from '@icore/template-shared';
|
|
847
|
+
import { setStoredLocale, type IcoreLocale, i18next } from '@icore/template-shared';
|
|
731
848
|
import { ThemeToggle } from '../ThemeToggle';
|
|
732
849
|
|
|
733
850
|
const APP_VERSION = (import.meta.env.VITE_APP_VERSION as string | undefined) ?? '0.0.0-dev';
|
|
@@ -741,7 +858,7 @@ const LOCALES: { code: IcoreLocale; label: string }[] = [
|
|
|
741
858
|
export function LayoutHeader() {
|
|
742
859
|
function handleLocale(code: IcoreLocale) {
|
|
743
860
|
setStoredLocale(code);
|
|
744
|
-
|
|
861
|
+
void i18next.changeLanguage(code);
|
|
745
862
|
}
|
|
746
863
|
|
|
747
864
|
return (
|
|
@@ -913,7 +1030,7 @@ export function LayoutHeader() {
|
|
|
913
1030
|
|
|
914
1031
|
function handleLocale(code: IcoreLocale) {
|
|
915
1032
|
setStoredLocale(code);
|
|
916
|
-
|
|
1033
|
+
void i18n.changeLanguage(code);
|
|
917
1034
|
}
|
|
918
1035
|
|
|
919
1036
|
return (
|
|
@@ -957,19 +1074,22 @@ var UI_VARIANTS = {
|
|
|
957
1074
|
"apps/client/src/main.tsx": SHADCN_MAIN_TSX,
|
|
958
1075
|
"apps/client/src/routes/_dashboard.tsx": SHADCN_DASHBOARD_TSX,
|
|
959
1076
|
"apps/client/src/routes/index.tsx": SHADCN_INDEX_TSX,
|
|
960
|
-
"apps/client/src/components/layout/LayoutHeader.tsx": SHADCN_LAYOUT_HEADER_TSX
|
|
1077
|
+
"apps/client/src/components/layout/LayoutHeader.tsx": SHADCN_LAYOUT_HEADER_TSX,
|
|
1078
|
+
"apps/client/src/components/PageLayout.tsx": SHADCN_PAGE_LAYOUT_TSX
|
|
961
1079
|
},
|
|
962
1080
|
antd: {
|
|
963
1081
|
"apps/client/src/main.tsx": ANTD_MAIN_TSX,
|
|
964
1082
|
"apps/client/src/routes/_dashboard.tsx": ANTD_DASHBOARD_TSX,
|
|
965
1083
|
"apps/client/src/routes/index.tsx": ANTD_INDEX_TSX,
|
|
966
|
-
"apps/client/src/components/layout/LayoutHeader.tsx": ANTD_LAYOUT_HEADER_TSX
|
|
1084
|
+
"apps/client/src/components/layout/LayoutHeader.tsx": ANTD_LAYOUT_HEADER_TSX,
|
|
1085
|
+
"apps/client/src/components/PageLayout.tsx": ANTD_PAGE_LAYOUT_TSX
|
|
967
1086
|
},
|
|
968
1087
|
mui: {
|
|
969
1088
|
"apps/client/src/main.tsx": MUI_MAIN_TSX,
|
|
970
1089
|
"apps/client/src/routes/_dashboard.tsx": MUI_DASHBOARD_TSX,
|
|
971
1090
|
"apps/client/src/routes/index.tsx": MUI_INDEX_TSX,
|
|
972
|
-
"apps/client/src/components/layout/LayoutHeader.tsx": MUI_LAYOUT_HEADER_TSX
|
|
1091
|
+
"apps/client/src/components/layout/LayoutHeader.tsx": MUI_LAYOUT_HEADER_TSX,
|
|
1092
|
+
"apps/client/src/components/PageLayout.tsx": MUI_PAGE_LAYOUT_TSX
|
|
973
1093
|
}
|
|
974
1094
|
};
|
|
975
1095
|
async function applyAuthNoneVariants(targetDir, ui) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idevconn/create-icore",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"description": "Bootstrap a new project from the iCore scaffold (Nx + NestJS + React + Vite + shadcn/Tailwind, swappable auth + storage providers).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "iDEVconn",
|
|
@@ -13,13 +13,13 @@ const LOCALES: { code: IcoreLocale; label: string }[] = [
|
|
|
13
13
|
];
|
|
14
14
|
|
|
15
15
|
export function LayoutHeader() {
|
|
16
|
-
const { t } = useTranslation();
|
|
16
|
+
const { t, i18n } = useTranslation();
|
|
17
17
|
const navigate = useNavigate();
|
|
18
18
|
const user = useAuthStore((s) => s.user);
|
|
19
19
|
|
|
20
20
|
function handleLocale(code: IcoreLocale) {
|
|
21
21
|
setStoredLocale(code);
|
|
22
|
-
|
|
22
|
+
void i18n.changeLanguage(code);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
function handleLogout() {
|
|
@@ -12,14 +12,14 @@ const LOCALES: { code: IcoreLocale; label: string }[] = [
|
|
|
12
12
|
];
|
|
13
13
|
|
|
14
14
|
export function LayoutHeader() {
|
|
15
|
-
const { t } = useTranslation();
|
|
15
|
+
const { t, i18n } = useTranslation();
|
|
16
16
|
const navigate = useNavigate();
|
|
17
17
|
const user = useAuthStore((s) => s.user);
|
|
18
18
|
const logout = useAuthStore((s) => s.logout);
|
|
19
19
|
|
|
20
20
|
function handleLocale(code: IcoreLocale) {
|
|
21
21
|
setStoredLocale(code);
|
|
22
|
-
|
|
22
|
+
void i18n.changeLanguage(code);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
function handleLogout() {
|
|
@@ -16,7 +16,7 @@ export function LayoutSider() {
|
|
|
16
16
|
|
|
17
17
|
return (
|
|
18
18
|
<aside
|
|
19
|
-
className={`relative flex flex-col border-
|
|
19
|
+
className={`relative flex flex-col border-e border-[--color-border] bg-[--color-card] transition-all duration-200 ${
|
|
20
20
|
collapsed ? 'w-14' : 'w-52'
|
|
21
21
|
}`}
|
|
22
22
|
>
|
|
@@ -41,9 +41,13 @@ export function LayoutSider() {
|
|
|
41
41
|
type="button"
|
|
42
42
|
onClick={() => setCollapsed((c) => !c)}
|
|
43
43
|
aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
|
|
44
|
-
className="absolute -
|
|
44
|
+
className="absolute -end-3 top-5 z-10 flex h-6 w-6 cursor-pointer items-center justify-center rounded-full border border-[--color-border] bg-[--color-card] text-[--color-muted-foreground] shadow-sm hover:text-[--color-foreground] transition-colors"
|
|
45
45
|
>
|
|
46
|
-
{collapsed ?
|
|
46
|
+
{collapsed ? (
|
|
47
|
+
<ChevronRight size={12} className="rtl:scale-x-[-1]" />
|
|
48
|
+
) : (
|
|
49
|
+
<ChevronLeft size={12} className="rtl:scale-x-[-1]" />
|
|
50
|
+
)}
|
|
47
51
|
</button>
|
|
48
52
|
</aside>
|
|
49
53
|
);
|
|
@@ -4,12 +4,12 @@ import { LandingPage } from '@icore/template-shared';
|
|
|
4
4
|
// All version strings are injected at build time by vite.config.mts
|
|
5
5
|
// (reads root package.json via fs.readFileSync so they stay accurate
|
|
6
6
|
// even when workspace packages are bumped independently).
|
|
7
|
-
const
|
|
7
|
+
const ICORE_VERSION = (import.meta.env.VITE_ICORE_VERSION as string | undefined) ?? '0.0.0-dev';
|
|
8
8
|
|
|
9
9
|
export const Route = createFileRoute('/')({
|
|
10
10
|
component: () => (
|
|
11
11
|
<LandingPage
|
|
12
|
-
coreVersion={
|
|
12
|
+
coreVersion={ICORE_VERSION}
|
|
13
13
|
uiLibrary="shadcn"
|
|
14
14
|
deps={[
|
|
15
15
|
{ name: 'react', version: (import.meta.env.VITE_DEP_REACT as string) ?? '?' },
|
|
@@ -19,12 +19,26 @@ import {
|
|
|
19
19
|
const rootPackageJsonPath = new URL('../../../package.json', import.meta.url);
|
|
20
20
|
const rootPackageJson = JSON.parse(fs.readFileSync(rootPackageJsonPath, 'utf-8')) as {
|
|
21
21
|
version: string;
|
|
22
|
+
icoreVersion?: string;
|
|
23
|
+
dependencies?: Record<string, string>;
|
|
24
|
+
devDependencies?: Record<string, string>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const selfPackageJson = JSON.parse(
|
|
28
|
+
fs.readFileSync(new URL('./package.json', import.meta.url), 'utf-8'),
|
|
29
|
+
) as {
|
|
22
30
|
dependencies?: Record<string, string>;
|
|
23
31
|
devDependencies?: Record<string, string>;
|
|
24
32
|
};
|
|
25
33
|
|
|
26
34
|
function depVersion(name: string): string {
|
|
27
|
-
return
|
|
35
|
+
return (
|
|
36
|
+
rootPackageJson.dependencies?.[name] ??
|
|
37
|
+
rootPackageJson.devDependencies?.[name] ??
|
|
38
|
+
selfPackageJson.dependencies?.[name] ??
|
|
39
|
+
selfPackageJson.devDependencies?.[name] ??
|
|
40
|
+
'?'
|
|
41
|
+
);
|
|
28
42
|
}
|
|
29
43
|
|
|
30
44
|
export default defineConfig(() => ({
|
|
@@ -37,6 +51,9 @@ export default defineConfig(() => ({
|
|
|
37
51
|
},
|
|
38
52
|
define: {
|
|
39
53
|
...commonDefines(rootPackageJson),
|
|
54
|
+
'import.meta.env.VITE_ICORE_VERSION': JSON.stringify(
|
|
55
|
+
rootPackageJson.icoreVersion ?? rootPackageJson.version,
|
|
56
|
+
),
|
|
40
57
|
'import.meta.env.VITE_DEP_TAILWINDCSS': JSON.stringify(depVersion('tailwindcss')),
|
|
41
58
|
},
|
|
42
59
|
plugins: [
|