@carefully-built/widgets 0.1.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/README.md +11 -0
- package/dist/index.d.mts +87 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +123 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# @carefully-built/widgets
|
|
2
|
+
|
|
3
|
+
Reusable dashboard and detail widgets for Carefully Built SaaS apps.
|
|
4
|
+
|
|
5
|
+
## Components
|
|
6
|
+
|
|
7
|
+
- `WidgetEmptyState`: dashed empty-state panel with optional action.
|
|
8
|
+
- `EntityInfoWidget`: compact bordered info widget with icon, title, actions, content, and empty-state support.
|
|
9
|
+
- `DashboardWidget`: dashboard card shell that keeps icon/title visible while loading and skeletonizes only the value/body.
|
|
10
|
+
|
|
11
|
+
Use this package when a new app needs the same SaaS widget chrome without rewriting loading, empty, title, icon, and action behavior.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { LucideIcon } from "lucide-react";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/widget-empty-state.d.ts
|
|
5
|
+
interface WidgetEmptyStateAction {
|
|
6
|
+
readonly label: string;
|
|
7
|
+
readonly href?: string;
|
|
8
|
+
readonly onClick?: () => void;
|
|
9
|
+
readonly target?: "_blank" | "_self" | "_parent" | "_top";
|
|
10
|
+
readonly rel?: string;
|
|
11
|
+
readonly icon?: ReactNode;
|
|
12
|
+
readonly disabled?: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface WidgetEmptyStateConfig {
|
|
15
|
+
readonly title: string;
|
|
16
|
+
readonly description: string;
|
|
17
|
+
readonly icon?: LucideIcon;
|
|
18
|
+
readonly minHeightClassName?: string;
|
|
19
|
+
readonly className?: string;
|
|
20
|
+
readonly action?: WidgetEmptyStateAction;
|
|
21
|
+
}
|
|
22
|
+
interface WidgetEmptyStateProps extends WidgetEmptyStateConfig {
|
|
23
|
+
readonly icon: LucideIcon;
|
|
24
|
+
}
|
|
25
|
+
declare function WidgetEmptyState({
|
|
26
|
+
icon: Icon,
|
|
27
|
+
title,
|
|
28
|
+
description,
|
|
29
|
+
minHeightClassName,
|
|
30
|
+
className,
|
|
31
|
+
action
|
|
32
|
+
}: WidgetEmptyStateProps): React.ReactElement;
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/dashboard-widget.d.ts
|
|
35
|
+
interface DashboardWidgetProps {
|
|
36
|
+
readonly icon: LucideIcon;
|
|
37
|
+
readonly title: string;
|
|
38
|
+
readonly value?: ReactNode;
|
|
39
|
+
readonly actions?: ReactNode;
|
|
40
|
+
readonly children?: ReactNode;
|
|
41
|
+
readonly className?: string;
|
|
42
|
+
readonly contentClassName?: string;
|
|
43
|
+
readonly isLoading?: boolean;
|
|
44
|
+
readonly loadingFallback?: ReactNode;
|
|
45
|
+
readonly isEmpty?: boolean;
|
|
46
|
+
readonly emptyState?: WidgetEmptyStateConfig;
|
|
47
|
+
}
|
|
48
|
+
declare function DashboardWidget({
|
|
49
|
+
icon,
|
|
50
|
+
title,
|
|
51
|
+
value,
|
|
52
|
+
actions,
|
|
53
|
+
children,
|
|
54
|
+
className,
|
|
55
|
+
contentClassName,
|
|
56
|
+
isLoading,
|
|
57
|
+
loadingFallback,
|
|
58
|
+
isEmpty,
|
|
59
|
+
emptyState
|
|
60
|
+
}: DashboardWidgetProps): React.ReactElement;
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/entity-info-widget.d.ts
|
|
63
|
+
interface EntityInfoWidgetProps {
|
|
64
|
+
readonly icon: LucideIcon;
|
|
65
|
+
readonly name: string;
|
|
66
|
+
readonly children: ReactNode;
|
|
67
|
+
readonly className?: string;
|
|
68
|
+
readonly contentClassName?: string;
|
|
69
|
+
readonly nameActions?: ReactNode;
|
|
70
|
+
readonly headerActions?: ReactNode;
|
|
71
|
+
readonly isEmpty?: boolean;
|
|
72
|
+
readonly emptyState?: WidgetEmptyStateConfig;
|
|
73
|
+
}
|
|
74
|
+
declare function EntityInfoWidget({
|
|
75
|
+
icon: Icon,
|
|
76
|
+
name,
|
|
77
|
+
children,
|
|
78
|
+
className,
|
|
79
|
+
contentClassName,
|
|
80
|
+
nameActions,
|
|
81
|
+
headerActions,
|
|
82
|
+
isEmpty,
|
|
83
|
+
emptyState
|
|
84
|
+
}: EntityInfoWidgetProps): React.ReactElement;
|
|
85
|
+
//#endregion
|
|
86
|
+
export { DashboardWidget, type DashboardWidgetProps, EntityInfoWidget, type EntityInfoWidgetProps, WidgetEmptyState, type WidgetEmptyStateAction, type WidgetEmptyStateConfig, type WidgetEmptyStateProps };
|
|
87
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/widget-empty-state.tsx","../src/dashboard-widget.tsx","../src/entity-info-widget.tsx"],"sourcesContent":[],"mappings":";;;;UAOiB,sBAAA;;EAAA,SAAA,IAAA,CAAA,EAAA,MAAA;EAUA,SAAA,OAAA,CAAA,EAAA,GAAA,GAAsB,IAAA;EAStB,SAAA,MAAA,CAAA,EAAA,QAAsB,GAAA,OACtB,GAAA,SAD8B,GAAA,MAAA;EAI/B,SAAA,GAAA,CAAA,EAAA,MAAgB;EACxB,SAAA,IAAA,CAAA,EAlBU,SAkBV;EACN,SAAA,QAAA,CAAA,EAAA,OAAA;;AAEA,UAjBe,sBAAA,CAiBf;EACA,SAAA,KAAA,EAAA,MAAA;EACA,SAAA,WAAA,EAAA,MAAA;EACC,SAAA,IAAA,CAAA,EAjBe,UAiBf;EAAwB,SAAM,kBAAA,CAAA,EAAA,MAAA;EAAY,SAAA,SAAA,CAAA,EAAA,MAAA;oBAdzB;;UAGH,qBAAA,SAA8B;EChB9B,SAAA,IAAA,EDiBA,UCjBoB;;AAGlB,iBDiBH,gBAAA,CCjBG;EAAA,IAAA,EDkBX,IClBW;EAAA,KAAA;EAAA,WAAA;EAAA,kBAAA;EAAA,SAAA;EAAA;AAAA,CAAA,EDwBhB,qBCxBgB,CAAA,EDwBQ,KAAA,CAAM,YCxBd;;;UAHF,oBAAA;EDHA,SAAA,IAAA,ECIA,UDJsB;EAUtB,SAAA,KAAA,EAAA,MAAA;EASA,SAAA,KAAA,CAAA,ECbE,SDaoB;EAIvB,SAAA,OAAA,CAAA,EChBK,SDgBW;EACxB,SAAA,QAAA,CAAA,EChBc,SDgBd;EACN,SAAA,SAAA,CAAA,EAAA,MAAA;EACA,SAAA,gBAAA,CAAA,EAAA,MAAA;EACA,SAAA,SAAA,CAAA,EAAA,OAAA;EACA,SAAA,eAAA,CAAA,EChB2B,SDgB3B;EACA,SAAA,OAAA,CAAA,EAAA,OAAA;EACC,SAAA,UAAA,CAAA,EChBqB,sBDgBrB;;AAA0C,iBCb7B,eAAA,CDa6B;EAAA,IAAA;EAAA,KAAA;EAAA,KAAA;EAAA,OAAA;EAAA,QAAA;EAAA,SAAA;EAAA,gBAAA;EAAA,SAAA;EAAA,eAAA;EAAA,OAAA;EAAA;AAAA,CAAA,ECD1C,oBDC0C,CAAA,ECDnB,KAAA,CAAM,YDCa;;;UE3B5B,qBAAA;EFHA,SAAA,IAAA,EEIA,UFJsB;EAUtB,SAAA,IAAA,EAAA,MAAA;EASA,SAAA,QAAA,EEbI,SFakB;EAIvB,SAAA,SAAA,CAAgB,EAAA,MAAA;EACxB,SAAA,gBAAA,CAAA,EAAA,MAAA;EACN,SAAA,WAAA,CAAA,EEhBuB,SFgBvB;EACA,SAAA,aAAA,CAAA,EEhByB,SFgBzB;EACA,SAAA,OAAA,CAAA,EAAA,OAAA;EACA,SAAA,UAAA,CAAA,EEhBsB,sBFgBtB;;AAEC,iBEfa,gBAAA,CFeb;EAAA,IAAA,EEdK,IFcL;EAAA,IAAA;EAAA,QAAA;EAAA,SAAA;EAAA,gBAAA;EAAA,WAAA;EAAA,aAAA;EAAA,OAAA;EAAA;AAAA,CAAA,EELA,qBFKA,CAAA,EELwB,KAAA,CAAM,YFK9B"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { Button, Skeleton, cn } from "@carefully-built/ui";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
//#region src/widget-empty-state.tsx
|
|
5
|
+
function WidgetEmptyState({ icon: Icon, title, description, minHeightClassName, className, action }) {
|
|
6
|
+
return /* @__PURE__ */ jsx("div", {
|
|
7
|
+
className: cn("flex h-full w-full items-center justify-center rounded-[16px] border border-dashed border-border/70 px-4 py-8 text-center", minHeightClassName ?? "min-h-[248px]", className),
|
|
8
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
9
|
+
className: "max-w-[280px] space-y-2",
|
|
10
|
+
children: [
|
|
11
|
+
/* @__PURE__ */ jsx("div", {
|
|
12
|
+
className: "text-muted-foreground flex justify-center",
|
|
13
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
14
|
+
className: "size-5",
|
|
15
|
+
strokeWidth: 1.75
|
|
16
|
+
})
|
|
17
|
+
}),
|
|
18
|
+
/* @__PURE__ */ jsx("p", {
|
|
19
|
+
className: "text-foreground text-sm font-medium",
|
|
20
|
+
children: title
|
|
21
|
+
}),
|
|
22
|
+
/* @__PURE__ */ jsx("p", {
|
|
23
|
+
className: "text-muted-foreground text-xs leading-5",
|
|
24
|
+
children: description
|
|
25
|
+
}),
|
|
26
|
+
action ? action.href ? /* @__PURE__ */ jsx(Button, {
|
|
27
|
+
asChild: true,
|
|
28
|
+
variant: "outline",
|
|
29
|
+
size: "sm",
|
|
30
|
+
className: "mt-4",
|
|
31
|
+
children: /* @__PURE__ */ jsxs("a", {
|
|
32
|
+
href: action.href,
|
|
33
|
+
target: action.target ?? "_self",
|
|
34
|
+
rel: action.rel,
|
|
35
|
+
children: [action.icon ? /* @__PURE__ */ jsx("span", {
|
|
36
|
+
className: "inline-flex items-center",
|
|
37
|
+
children: action.icon
|
|
38
|
+
}) : null, action.label]
|
|
39
|
+
})
|
|
40
|
+
}) : /* @__PURE__ */ jsxs(Button, {
|
|
41
|
+
type: "button",
|
|
42
|
+
variant: "outline",
|
|
43
|
+
size: "sm",
|
|
44
|
+
className: "mt-4",
|
|
45
|
+
onClick: action.onClick,
|
|
46
|
+
disabled: action.disabled,
|
|
47
|
+
children: [action.icon ? /* @__PURE__ */ jsx("span", {
|
|
48
|
+
className: "inline-flex items-center",
|
|
49
|
+
children: action.icon
|
|
50
|
+
}) : null, action.label]
|
|
51
|
+
}) : null
|
|
52
|
+
]
|
|
53
|
+
})
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/entity-info-widget.tsx
|
|
59
|
+
function EntityInfoWidget({ icon: Icon, name, children, className, contentClassName, nameActions, headerActions, isEmpty = false, emptyState }) {
|
|
60
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
61
|
+
className: cn("border-border flex min-w-0 flex-col gap-3 rounded-[12px] border bg-background p-1.5", className),
|
|
62
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
63
|
+
className: "flex min-w-0 flex-wrap items-center justify-between gap-3 px-0.5 sm:flex-nowrap",
|
|
64
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
65
|
+
className: "text-muted-foreground flex min-w-0 items-center gap-[3px] text-[13px]",
|
|
66
|
+
children: [
|
|
67
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
68
|
+
className: "size-3.5 shrink-0",
|
|
69
|
+
strokeWidth: 1.75
|
|
70
|
+
}),
|
|
71
|
+
/* @__PURE__ */ jsx("span", {
|
|
72
|
+
className: "truncate",
|
|
73
|
+
children: name
|
|
74
|
+
}),
|
|
75
|
+
nameActions ? /* @__PURE__ */ jsx("span", {
|
|
76
|
+
className: "ml-1 shrink-0",
|
|
77
|
+
children: nameActions
|
|
78
|
+
}) : null
|
|
79
|
+
]
|
|
80
|
+
}), headerActions ? /* @__PURE__ */ jsx("div", {
|
|
81
|
+
className: "flex min-w-0 max-w-full items-center gap-2 sm:shrink-0",
|
|
82
|
+
children: headerActions
|
|
83
|
+
}) : null]
|
|
84
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
85
|
+
className: cn("min-w-0", contentClassName),
|
|
86
|
+
children: isEmpty && emptyState ? /* @__PURE__ */ jsx(WidgetEmptyState, {
|
|
87
|
+
icon: emptyState.icon ?? Icon,
|
|
88
|
+
title: emptyState.title,
|
|
89
|
+
description: emptyState.description,
|
|
90
|
+
minHeightClassName: emptyState.minHeightClassName,
|
|
91
|
+
className: emptyState.className,
|
|
92
|
+
action: emptyState.action
|
|
93
|
+
}) : children
|
|
94
|
+
})]
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/dashboard-widget.tsx
|
|
100
|
+
function DashboardWidget({ icon, title, value, actions, children, className, contentClassName, isLoading = false, loadingFallback, isEmpty = false, emptyState }) {
|
|
101
|
+
const shouldRenderEmptyState = !isLoading && value === void 0 && isEmpty;
|
|
102
|
+
let defaultContentClassName = "pt-1";
|
|
103
|
+
if (value !== void 0) defaultContentClassName = "px-0.5 pt-2 pb-0.5";
|
|
104
|
+
else if (shouldRenderEmptyState) defaultContentClassName = "flex min-h-0 flex-1 pt-1";
|
|
105
|
+
return /* @__PURE__ */ jsx(EntityInfoWidget, {
|
|
106
|
+
icon,
|
|
107
|
+
name: title,
|
|
108
|
+
className: cn("h-full min-w-0 gap-0", className),
|
|
109
|
+
contentClassName: cn(defaultContentClassName, contentClassName),
|
|
110
|
+
headerActions: actions,
|
|
111
|
+
isEmpty: shouldRenderEmptyState,
|
|
112
|
+
emptyState: value === void 0 ? emptyState : void 0,
|
|
113
|
+
children: value !== void 0 ? /* @__PURE__ */ jsx("div", {
|
|
114
|
+
className: "text-foreground text-[24px] leading-none font-medium tracking-[-0.02em]",
|
|
115
|
+
"aria-busy": isLoading || void 0,
|
|
116
|
+
children: isLoading ? /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-16" }) : value
|
|
117
|
+
}) : isLoading ? loadingFallback ?? /* @__PURE__ */ jsx(Skeleton, { className: "h-[264px] w-full rounded-[10px]" }) : children
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
//#endregion
|
|
122
|
+
export { DashboardWidget, EntityInfoWidget, WidgetEmptyState };
|
|
123
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/widget-empty-state.tsx","../src/entity-info-widget.tsx","../src/dashboard-widget.tsx"],"sourcesContent":["\"use client\";\n\nimport type { LucideIcon } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\n\nimport { Button, cn } from \"@carefully-built/ui\";\n\nexport interface WidgetEmptyStateAction {\n readonly label: string;\n readonly href?: string;\n readonly onClick?: () => void;\n readonly target?: \"_blank\" | \"_self\" | \"_parent\" | \"_top\";\n readonly rel?: string;\n readonly icon?: ReactNode;\n readonly disabled?: boolean;\n}\n\nexport interface WidgetEmptyStateConfig {\n readonly title: string;\n readonly description: string;\n readonly icon?: LucideIcon;\n readonly minHeightClassName?: string;\n readonly className?: string;\n readonly action?: WidgetEmptyStateAction;\n}\n\nexport interface WidgetEmptyStateProps extends WidgetEmptyStateConfig {\n readonly icon: LucideIcon;\n}\n\nexport function WidgetEmptyState({\n icon: Icon,\n title,\n description,\n minHeightClassName,\n className,\n action,\n}: WidgetEmptyStateProps): React.ReactElement {\n return (\n <div\n className={cn(\n \"flex h-full w-full items-center justify-center rounded-[16px] border border-dashed border-border/70 px-4 py-8 text-center\",\n minHeightClassName ?? \"min-h-[248px]\",\n className,\n )}\n >\n <div className=\"max-w-[280px] space-y-2\">\n <div className=\"text-muted-foreground flex justify-center\">\n <Icon className=\"size-5\" strokeWidth={1.75} />\n </div>\n <p className=\"text-foreground text-sm font-medium\">{title}</p>\n <p className=\"text-muted-foreground text-xs leading-5\">{description}</p>\n {action ? (\n action.href ? (\n <Button asChild variant=\"outline\" size=\"sm\" className=\"mt-4\">\n <a href={action.href} target={action.target ?? \"_self\"} rel={action.rel}>\n {action.icon ? <span className=\"inline-flex items-center\">{action.icon}</span> : null}\n {action.label}\n </a>\n </Button>\n ) : (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"mt-4\"\n onClick={action.onClick}\n disabled={action.disabled}\n >\n {action.icon ? <span className=\"inline-flex items-center\">{action.icon}</span> : null}\n {action.label}\n </Button>\n )\n ) : null}\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport type { LucideIcon } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\n\nimport { cn } from \"@carefully-built/ui\";\n\nimport { WidgetEmptyState } from \"./widget-empty-state\";\nimport type { WidgetEmptyStateConfig } from \"./widget-empty-state\";\n\nexport interface EntityInfoWidgetProps {\n readonly icon: LucideIcon;\n readonly name: string;\n readonly children: ReactNode;\n readonly className?: string;\n readonly contentClassName?: string;\n readonly nameActions?: ReactNode;\n readonly headerActions?: ReactNode;\n readonly isEmpty?: boolean;\n readonly emptyState?: WidgetEmptyStateConfig;\n}\n\nexport function EntityInfoWidget({\n icon: Icon,\n name,\n children,\n className,\n contentClassName,\n nameActions,\n headerActions,\n isEmpty = false,\n emptyState,\n}: EntityInfoWidgetProps): React.ReactElement {\n return (\n <section\n className={cn(\n \"border-border flex min-w-0 flex-col gap-3 rounded-[12px] border bg-background p-1.5\",\n className,\n )}\n >\n <div className=\"flex min-w-0 flex-wrap items-center justify-between gap-3 px-0.5 sm:flex-nowrap\">\n <div className=\"text-muted-foreground flex min-w-0 items-center gap-[3px] text-[13px]\">\n <Icon className=\"size-3.5 shrink-0\" strokeWidth={1.75} />\n <span className=\"truncate\">{name}</span>\n {nameActions ? <span className=\"ml-1 shrink-0\">{nameActions}</span> : null}\n </div>\n {headerActions ? (\n <div className=\"flex min-w-0 max-w-full items-center gap-2 sm:shrink-0\">\n {headerActions}\n </div>\n ) : null}\n </div>\n <div className={cn(\"min-w-0\", contentClassName)}>\n {isEmpty && emptyState ? (\n <WidgetEmptyState\n icon={emptyState.icon ?? Icon}\n title={emptyState.title}\n description={emptyState.description}\n minHeightClassName={emptyState.minHeightClassName}\n className={emptyState.className}\n action={emptyState.action}\n />\n ) : (\n children\n )}\n </div>\n </section>\n );\n}\n","\"use client\";\n\nimport type { LucideIcon } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\n\nimport { Skeleton, cn } from \"@carefully-built/ui\";\n\nimport { EntityInfoWidget } from \"./entity-info-widget\";\nimport type { WidgetEmptyStateConfig } from \"./widget-empty-state\";\n\nexport interface DashboardWidgetProps {\n readonly icon: LucideIcon;\n readonly title: string;\n readonly value?: ReactNode;\n readonly actions?: ReactNode;\n readonly children?: ReactNode;\n readonly className?: string;\n readonly contentClassName?: string;\n readonly isLoading?: boolean;\n readonly loadingFallback?: ReactNode;\n readonly isEmpty?: boolean;\n readonly emptyState?: WidgetEmptyStateConfig;\n}\n\nexport function DashboardWidget({\n icon,\n title,\n value,\n actions,\n children,\n className,\n contentClassName,\n isLoading = false,\n loadingFallback,\n isEmpty = false,\n emptyState,\n}: DashboardWidgetProps): React.ReactElement {\n const shouldRenderEmptyState = !isLoading && value === undefined && isEmpty;\n let defaultContentClassName = \"pt-1\";\n\n if (value !== undefined) {\n defaultContentClassName = \"px-0.5 pt-2 pb-0.5\";\n } else if (shouldRenderEmptyState) {\n defaultContentClassName = \"flex min-h-0 flex-1 pt-1\";\n }\n\n return (\n <EntityInfoWidget\n icon={icon}\n name={title}\n className={cn(\"h-full min-w-0 gap-0\", className)}\n contentClassName={cn(defaultContentClassName, contentClassName)}\n headerActions={actions}\n isEmpty={shouldRenderEmptyState}\n emptyState={value === undefined ? emptyState : undefined}\n >\n {value !== undefined ? (\n <div\n className=\"text-foreground text-[24px] leading-none font-medium tracking-[-0.02em]\"\n aria-busy={isLoading || undefined}\n >\n {isLoading ? <Skeleton className=\"h-7 w-16\" /> : value}\n </div>\n ) : isLoading ? (\n (loadingFallback ?? <Skeleton className=\"h-[264px] w-full rounded-[10px]\" />)\n ) : (\n children\n )}\n </EntityInfoWidget>\n );\n}\n"],"mappings":";;;;AA8BA,SAAgB,iBAAiB,EAC/B,MAAM,MACN,OACA,aACA,oBACA,WACA,UAC4C;AAC5C,QACE,oBAAC;EACC,WAAW,GACT,6HACA,sBAAsB,iBACtB,UACD;YAED,qBAAC;GAAI,WAAU;;IACb,oBAAC;KAAI,WAAU;eACb,oBAAC;MAAK,WAAU;MAAS,aAAa;OAAQ;MAC1C;IACN,oBAAC;KAAE,WAAU;eAAuC;MAAU;IAC9D,oBAAC;KAAE,WAAU;eAA2C;MAAgB;IACvE,SACC,OAAO,OACL,oBAAC;KAAO;KAAQ,SAAQ;KAAU,MAAK;KAAK,WAAU;eACpD,qBAAC;MAAE,MAAM,OAAO;MAAM,QAAQ,OAAO,UAAU;MAAS,KAAK,OAAO;iBACjE,OAAO,OAAO,oBAAC;OAAK,WAAU;iBAA4B,OAAO;QAAY,GAAG,MAChF,OAAO;OACN;MACG,GAET,qBAAC;KACC,MAAK;KACL,SAAQ;KACR,MAAK;KACL,WAAU;KACV,SAAS,OAAO;KAChB,UAAU,OAAO;gBAEhB,OAAO,OAAO,oBAAC;MAAK,WAAU;gBAA4B,OAAO;OAAY,GAAG,MAChF,OAAO;MACD,GAET;;IACA;GACF;;;;;ACrDV,SAAgB,iBAAiB,EAC/B,MAAM,MACN,MACA,UACA,WACA,kBACA,aACA,eACA,UAAU,OACV,cAC4C;AAC5C,QACE,qBAAC;EACC,WAAW,GACT,uFACA,UACD;aAED,qBAAC;GAAI,WAAU;cACb,qBAAC;IAAI,WAAU;;KACb,oBAAC;MAAK,WAAU;MAAoB,aAAa;OAAQ;KACzD,oBAAC;MAAK,WAAU;gBAAY;OAAY;KACvC,cAAc,oBAAC;MAAK,WAAU;gBAAiB;OAAmB,GAAG;;KAClE,EACL,gBACC,oBAAC;IAAI,WAAU;cACZ;KACG,GACJ;IACA,EACN,oBAAC;GAAI,WAAW,GAAG,WAAW,iBAAiB;aAC5C,WAAW,aACV,oBAAC;IACC,MAAM,WAAW,QAAQ;IACzB,OAAO,WAAW;IAClB,aAAa,WAAW;IACxB,oBAAoB,WAAW;IAC/B,WAAW,WAAW;IACtB,QAAQ,WAAW;KACnB,GAEF;IAEE;GACE;;;;;AC1Cd,SAAgB,gBAAgB,EAC9B,MACA,OACA,OACA,SACA,UACA,WACA,kBACA,YAAY,OACZ,iBACA,UAAU,OACV,cAC2C;CAC3C,MAAM,yBAAyB,CAAC,aAAa,UAAU,UAAa;CACpE,IAAI,0BAA0B;AAE9B,KAAI,UAAU,OACZ,2BAA0B;UACjB,uBACT,2BAA0B;AAG5B,QACE,oBAAC;EACO;EACN,MAAM;EACN,WAAW,GAAG,wBAAwB,UAAU;EAChD,kBAAkB,GAAG,yBAAyB,iBAAiB;EAC/D,eAAe;EACf,SAAS;EACT,YAAY,UAAU,SAAY,aAAa;YAE9C,UAAU,SACT,oBAAC;GACC,WAAU;GACV,aAAW,aAAa;aAEvB,YAAY,oBAAC,YAAS,WAAU,aAAa,GAAG;IAC7C,GACJ,YACD,mBAAmB,oBAAC,YAAS,WAAU,oCAAoC,GAE5E;GAEe"}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@carefully-built/widgets",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Reusable SaaS dashboard and detail widgets for Carefully Built apps.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Alessandro Dodi",
|
|
8
|
+
"homepage": "https://github.com/AlessandroDodi/carefully-built-saas-kit#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/AlessandroDodi/carefully-built-saas-kit.git",
|
|
12
|
+
"directory": "packages/widgets"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/AlessandroDodi/carefully-built-saas-kit/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"react",
|
|
19
|
+
"widgets",
|
|
20
|
+
"dashboard",
|
|
21
|
+
"saas"
|
|
22
|
+
],
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"main": "./dist/index.mjs",
|
|
25
|
+
"module": "./dist/index.mjs",
|
|
26
|
+
"types": "./dist/index.d.mts",
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"README.md"
|
|
30
|
+
],
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./dist/index.d.mts",
|
|
34
|
+
"import": "./dist/index.mjs",
|
|
35
|
+
"default": "./dist/index.mjs"
|
|
36
|
+
},
|
|
37
|
+
"./package.json": "./package.json"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsdown src/index.ts --format esm --dts",
|
|
41
|
+
"prepublishOnly": "bun run typecheck && bun run build",
|
|
42
|
+
"typecheck": "tsc --noEmit"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"@carefully-built/ui": ">=0.1.15",
|
|
49
|
+
"lucide-react": ">=0.400.0 || >=1.0.0",
|
|
50
|
+
"react": ">=18.2.0 || >=19.0.0",
|
|
51
|
+
"react-dom": ">=18.2.0 || >=19.0.0"
|
|
52
|
+
},
|
|
53
|
+
"peerDependenciesMeta": {
|
|
54
|
+
"@carefully-built/ui": {
|
|
55
|
+
"optional": true
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@carefully-built/ui": "workspace:*",
|
|
60
|
+
"lucide-react": "^1.8.0",
|
|
61
|
+
"react": "^19.2.3",
|
|
62
|
+
"react-dom": "^19.2.3"
|
|
63
|
+
}
|
|
64
|
+
}
|