@replicated/portal-components 0.0.1
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/components/metadata/registry.json +273 -0
- package/components/metadata/registry.md +77 -0
- package/dist/actions/index.d.mts +23 -0
- package/dist/actions/index.d.ts +23 -0
- package/dist/actions/index.js +13 -0
- package/dist/actions/index.js.map +1 -0
- package/dist/esm/actions/index.js +11 -0
- package/dist/esm/actions/index.js.map +1 -0
- package/dist/esm/index.js +225 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/tokens/index.js +68 -0
- package/dist/esm/tokens/index.js.map +1 -0
- package/dist/index.d.mts +122 -0
- package/dist/index.d.ts +122 -0
- package/dist/index.js +232 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +956 -0
- package/dist/tokens/index.d.mts +36 -0
- package/dist/tokens/index.d.ts +36 -0
- package/dist/tokens/index.js +71 -0
- package/dist/tokens/index.js.map +1 -0
- package/package.json +90 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../package.json","../../src/tokens/index.ts","../../src/components/button.tsx","../../src/components/login.tsx","../../src/actions/index.ts","../../src/index.ts"],"names":["forwardRef","jsxs","jsx"],"mappings":"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","file":"index.js","sourcesContent":["{\n \"name\": \"@replicated/portal-components\",\n \"version\": \"0.0.1\",\n \"description\": \"Opinionated component library for Replicated enterprise portals\",\n \"license\": \"Apache-2.0\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/replicatedhq/enterprise-portal-components.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/replicatedhq/enterprise-portal-components/issues\"\n },\n \"homepage\": \"https://github.com/replicatedhq/enterprise-portal-components#readme\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/esm/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"style\": \"dist/styles.css\",\n \"files\": [\n \"dist\",\n \"components/metadata\"\n ],\n \"sideEffects\": [\n \"*.css\",\n \"*.scss\"\n ],\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/esm/index.js\",\n \"require\": \"./dist/index.js\"\n },\n \"./tokens\": {\n \"types\": \"./dist/tokens/index.d.ts\",\n \"import\": \"./dist/esm/tokens/index.js\",\n \"require\": \"./dist/tokens/index.js\"\n },\n \"./actions\": {\n \"types\": \"./dist/actions/index.d.ts\",\n \"import\": \"./dist/esm/actions/index.js\",\n \"require\": \"./dist/actions/index.js\"\n },\n \"./styles.css\": \"./dist/styles.css\",\n \"./metadata/registry.json\": \"./components/metadata/registry.json\"\n },\n \"scripts\": {\n \"clean\": \"rimraf dist\",\n \"build\": \"npm run clean && npm run registry:generate && npm run build:css && tsup\",\n \"build:css\": \"tailwindcss -i ./src/styles.css -o ./dist/styles.css --config tailwind.config.ts\",\n \"dev\": \"tsup --watch\",\n \"typecheck\": \"tsc --noEmit\",\n \"registry:generate\": \"tsx scripts/generate-registry.ts\",\n \"size\": \"size-limit\",\n \"release\": \"changeset\"\n },\n \"peerDependencies\": {\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\"\n },\n \"devDependencies\": {\n \"@changesets/cli\": \"^2.27.8\",\n \"@size-limit/preset-big-lib\": \"^9.0.0\",\n \"@types/node\": \"^22.10.1\",\n \"@types/react\": \"^19.0.4\",\n \"@types/react-dom\": \"^19.0.3\",\n \"autoprefixer\": \"^10.4.20\",\n \"postcss\": \"^8.4.49\",\n \"react\": \"19.0.0\",\n \"react-dom\": \"19.0.0\",\n \"rimraf\": \"^6.0.1\",\n \"size-limit\": \"^9.0.0\",\n \"tailwindcss\": \"^3.4.17\",\n \"tslib\": \"^2.7.0\",\n \"tsup\": \"^8.3.5\",\n \"tsx\": \"^4.19.2\",\n \"typescript\": \"^5.6.3\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"packageManager\": \"npm@10\",\n \"size-limit\": [\n {\n \"name\": \"core entry\",\n \"path\": \"dist/esm/index.js\",\n \"import\": \"{ Login }\",\n \"limit\": \"35 KB\",\n \"gzip\": true\n }\n ]\n}\n","type DeepPartial<T> = {\n [Key in keyof T]?: T[Key] extends Record<string, unknown>\n ? DeepPartial<T[Key]>\n : T[Key];\n};\n\nexport interface PortalThemeTokens {\n colors: {\n background: string;\n foreground: string;\n surfaceMuted: string;\n primary: string;\n onPrimary: string;\n secondary: string;\n onSecondary: string;\n success: string;\n warning: string;\n danger: string;\n };\n radii: {\n lg: string;\n md: string;\n sm: string;\n };\n spacing: Record<\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\", string>;\n typography: {\n fontFamily: string;\n monoFamily: string;\n lineHeight: Record<\"tight\" | \"normal\" | \"relaxed\", string>;\n };\n shadows: {\n focus: string;\n overlay: string;\n };\n}\n\nconst baseTokens: PortalThemeTokens = {\n colors: {\n background: \"#0b0d12\",\n foreground: \"#f4f6fb\",\n surfaceMuted: \"#1b1f2a\",\n primary: \"#0d6efd\",\n onPrimary: \"#ffffff\",\n secondary: \"#6c757d\",\n onSecondary: \"#ffffff\",\n success: \"#22c55e\",\n warning: \"#fbbf24\",\n danger: \"#ef4444\"\n },\n radii: {\n lg: \"16px\",\n md: \"10px\",\n sm: \"6px\"\n },\n spacing: {\n xs: \"0.25rem\",\n sm: \"0.5rem\",\n md: \"0.75rem\",\n lg: \"1rem\",\n xl: \"1.5rem\"\n },\n typography: {\n fontFamily:\n \"Inter, 'SF Pro Display', 'Segoe UI', system-ui, -apple-system, sans-serif\",\n monoFamily: \"'JetBrains Mono', 'SFMono-Regular', Consolas, monospace\",\n lineHeight: {\n tight: \"1.2\",\n normal: \"1.5\",\n relaxed: \"1.75\"\n }\n },\n shadows: {\n focus: \"0 0 0 3px color-mix(in srgb, #0d6efd 35%, transparent)\",\n overlay: \"0px 20px 55px rgba(5, 7, 11, 0.5)\"\n }\n};\n\nconst mergeTokens = (\n base: PortalThemeTokens,\n overrides?: DeepPartial<PortalThemeTokens>\n): PortalThemeTokens => {\n if (!overrides) {\n return base;\n }\n\n const clone = structuredClone(base);\n\n const apply = (target: Record<string, any>, source: Record<string, any>) => {\n Object.entries(source).forEach(([key, value]) => {\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n typeof target[key] === \"object\"\n ) {\n apply(target[key], value);\n return;\n }\n\n target[key] = value;\n });\n };\n\n apply(clone as Record<string, any>, overrides as Record<string, any>);\n return clone;\n};\n\nexport const portalThemeTokens: PortalThemeTokens =\n mergeTokens(baseTokens);\n\nexport const createPortalTheme = (\n overrides?: DeepPartial<PortalThemeTokens>\n) => mergeTokens(baseTokens, overrides);\n\nexport type { DeepPartial as PortalThemeOverrides };\n","import {\n forwardRef,\n type ComponentPropsWithoutRef,\n type ReactNode\n} from \"react\";\n\nconst buttonVariants = [\"primary\", \"secondary\", \"ghost\", \"destructive\"] as const;\nconst buttonSizes = [\"sm\", \"md\", \"lg\"] as const;\n\nconst variantStyles: Record<ButtonVariant, string> = {\n primary:\n \"bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-primary\",\n secondary:\n \"bg-secondary/20 text-secondary-foreground hover:bg-secondary/30 focus-visible:ring-secondary\",\n ghost:\n \"bg-transparent text-primary hover:bg-primary/10 focus-visible:ring-primary/60\",\n destructive:\n \"bg-danger text-white hover:bg-danger/90 focus-visible:ring-danger\"\n};\n\nconst sizeStyles: Record<ButtonSize, string> = {\n sm: \"h-8 px-3 text-sm\",\n md: \"h-10 px-4 text-sm\",\n lg: \"h-12 px-6 text-base\"\n};\n\nconst inlineFlexBase =\n \"inline-flex items-center justify-center gap-2 rounded-md font-medium tracking-tight transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-60\";\n\nconst Spinner = () => (\n <span className=\"inline-flex h-3.5 w-3.5 animate-spin items-center justify-center\">\n <span className=\"h-3 w-3 rounded-full border-2 border-transparent border-t-current\" />\n </span>\n);\n\nexport type ButtonVariant = (typeof buttonVariants)[number];\nexport type ButtonSize = (typeof buttonSizes)[number];\n\nexport interface ButtonProps extends ComponentPropsWithoutRef<\"button\"> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n isLoading?: boolean;\n leadingIcon?: ReactNode;\n trailingIcon?: ReactNode;\n}\n\nconst composeClassName = (\n ...values: Array<string | undefined | false>\n): string => values.filter(Boolean).join(\" \");\n\n/**\n * Button is the primary interactive primitive for triggering portal actions.\n * It is theme aware via CSS variables generated from portal tokens.\n */\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n variant = \"primary\",\n size = \"md\",\n type = \"button\",\n isLoading = false,\n leadingIcon,\n trailingIcon,\n disabled,\n className,\n children,\n ...props\n },\n ref\n ) => {\n const computedLeading = isLoading ? <Spinner /> : leadingIcon;\n const computedDisabled = disabled ?? isLoading;\n\n return (\n <button\n ref={ref}\n type={type}\n className={composeClassName(\n inlineFlexBase,\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n aria-busy={isLoading || undefined}\n disabled={computedDisabled}\n {...props}\n >\n {computedLeading ? (\n <span aria-hidden=\"true\" className=\"inline-flex\">\n {computedLeading}\n </span>\n ) : null}\n <span className=\"flex-1 whitespace-nowrap\">{children}</span>\n {trailingIcon ? (\n <span aria-hidden=\"true\" className=\"inline-flex\">\n {trailingIcon}\n </span>\n ) : null}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n","'use client';\n\nimport {\n forwardRef,\n useState,\n type ComponentPropsWithoutRef,\n type FormEvent,\n type ReactNode\n} from \"react\";\n\nimport { Button } from \"./button\";\n\nexport interface LoginProps\n extends Omit<ComponentPropsWithoutRef<\"form\">, \"onSubmit\" | \"children\"> {\n logo?: ReactNode;\n title?: string;\n description?: string;\n label?: string;\n placeholder?: string;\n ctaLabel?: string;\n initialEmail?: string;\n isSubmitting?: boolean;\n onContinue?: (email: string) => Promise<void> | void;\n}\n\n/**\n * Login renders a compact form card tailored for portal authentication flows.\n * The component keeps styling self-contained so it can be dropped into the\n * local Next.js template without additional wrappers.\n */\nexport const Login = forwardRef<HTMLFormElement, LoginProps>(\n (\n {\n logo,\n title = \"Enterprise Factory Installation Portal\",\n description = \"Sign in to manage your enterprise installation\",\n label = \"Work email address\",\n placeholder = \"you@company.com\",\n ctaLabel = \"Continue with email →\",\n initialEmail = \"\",\n isSubmitting = false,\n onContinue,\n className,\n ...props\n },\n ref\n ) => {\n const [email, setEmail] = useState(initialEmail);\n const [pending, setPending] = useState(false);\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!onContinue) {\n return;\n }\n\n try {\n setPending(true);\n await onContinue(email);\n } finally {\n setPending(false);\n }\n };\n\n const disabled = isSubmitting || pending;\n\n return (\n <form\n ref={ref}\n className={[\n \"w-full max-w-md rounded-3xl border border-white/15 bg-slate-950/80 p-10 shadow-[0_25px_70px_rgba(5,7,11,0.65)] backdrop-blur\",\n \"text-white transition-shadow\",\n className\n ]\n .filter(Boolean)\n .join(\" \")}\n onSubmit={handleSubmit}\n {...props}\n >\n <div className=\"flex flex-col items-center gap-4 text-center\">\n {logo ?? (\n <div className=\"flex h-16 w-16 items-center justify-center rounded-2xl border border-white/20 bg-white/10 text-lg font-semibold leading-tight\">\n EP\n </div>\n )}\n <div>\n <p className=\"text-base font-semibold uppercase tracking-[0.35em] text-white/65\">\n Enterprise Portal\n </p>\n <h1 className=\"mt-3 text-3xl font-semibold tracking-tight\">\n {title}\n </h1>\n <p className=\"mt-2 text-sm text-white/70\">{description}</p>\n </div>\n </div>\n <div className=\"mt-8 space-y-3\">\n <label\n htmlFor=\"login-email\"\n className=\"text-sm font-medium text-white/70\"\n >\n {label}\n </label>\n <input\n id=\"login-email\"\n type=\"email\"\n inputMode=\"email\"\n autoComplete=\"email\"\n placeholder={placeholder}\n value={email}\n onChange={(event) => setEmail(event.target.value)}\n className=\"w-full rounded-2xl border border-white/15 bg-white/5 px-5 py-4 text-base text-white placeholder:text-white/40 focus:border-white/40 focus:outline-none focus:ring-2 focus:ring-white/25\"\n disabled={disabled}\n required\n />\n <Button\n type=\"submit\"\n size=\"lg\"\n className=\"w-full justify-center\"\n disabled={disabled}\n isLoading={disabled}\n >\n {ctaLabel}\n </Button>\n </div>\n </form>\n );\n }\n);\n\nLogin.displayName = \"Login\";\n","/**\n * Light-weight type helpers for defining Server Actions that align with the\n * enterprise portal guardrails. The component library does not implement\n * specific actions, but it exports helpers so downstream portals can describe\n * their actions with consistent metadata.\n */\n\nexport type PortalActionVisibility = \"vendor\" | \"customer\";\n\nexport interface PortalActionContext {\n vendorId: string;\n licenseId: string;\n userId: string;\n signal?: AbortSignal;\n}\n\nexport interface PortalServerActionDefinition<Input, Output> {\n id: string;\n description: string;\n visibility: PortalActionVisibility;\n tags: string[];\n run: (input: Input, context: PortalActionContext) => Promise<Output>;\n}\n\nexport const defineServerAction = <Input, Output>(\n definition: PortalServerActionDefinition<Input, Output>\n) => definition;\n","import packageJson from \"../package.json\";\n\nexport const portalComponentsVersion = packageJson.version;\n\nexport type {\n ComponentAccessibilityMetadata,\n ComponentBehaviorMetadata,\n ComponentCategory,\n ComponentRegistryDocument,\n ComponentRegistryEntry,\n ComponentExampleMetadata,\n ComponentPerformanceMetadata,\n ComponentPropMetadata\n} from \"./types/metadata\";\n\nexport {\n createPortalTheme,\n portalThemeTokens\n} from \"./tokens\";\nexport type { PortalThemeTokens, PortalThemeOverrides } from \"./tokens\";\n\nexport * from \"./components\";\n\nexport {\n defineServerAction\n} from \"./actions\";\nexport type {\n PortalActionContext,\n PortalActionVisibility,\n PortalServerActionDefinition\n} from \"./actions\";\n"]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enterprise Portal Components
|
|
3
|
+
* This file is generated by tsup. Do not edit manually.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// src/tokens/index.ts
|
|
7
|
+
var baseTokens = {
|
|
8
|
+
colors: {
|
|
9
|
+
background: "#0b0d12",
|
|
10
|
+
foreground: "#f4f6fb",
|
|
11
|
+
surfaceMuted: "#1b1f2a",
|
|
12
|
+
primary: "#0d6efd",
|
|
13
|
+
onPrimary: "#ffffff",
|
|
14
|
+
secondary: "#6c757d",
|
|
15
|
+
onSecondary: "#ffffff",
|
|
16
|
+
success: "#22c55e",
|
|
17
|
+
warning: "#fbbf24",
|
|
18
|
+
danger: "#ef4444"
|
|
19
|
+
},
|
|
20
|
+
radii: {
|
|
21
|
+
lg: "16px",
|
|
22
|
+
md: "10px",
|
|
23
|
+
sm: "6px"
|
|
24
|
+
},
|
|
25
|
+
spacing: {
|
|
26
|
+
xs: "0.25rem",
|
|
27
|
+
sm: "0.5rem",
|
|
28
|
+
md: "0.75rem",
|
|
29
|
+
lg: "1rem",
|
|
30
|
+
xl: "1.5rem"
|
|
31
|
+
},
|
|
32
|
+
typography: {
|
|
33
|
+
fontFamily: "Inter, 'SF Pro Display', 'Segoe UI', system-ui, -apple-system, sans-serif",
|
|
34
|
+
monoFamily: "'JetBrains Mono', 'SFMono-Regular', Consolas, monospace",
|
|
35
|
+
lineHeight: {
|
|
36
|
+
tight: "1.2",
|
|
37
|
+
normal: "1.5",
|
|
38
|
+
relaxed: "1.75"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
shadows: {
|
|
42
|
+
focus: "0 0 0 3px color-mix(in srgb, #0d6efd 35%, transparent)",
|
|
43
|
+
overlay: "0px 20px 55px rgba(5, 7, 11, 0.5)"
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var mergeTokens = (base, overrides) => {
|
|
47
|
+
if (!overrides) {
|
|
48
|
+
return base;
|
|
49
|
+
}
|
|
50
|
+
const clone = structuredClone(base);
|
|
51
|
+
const apply = (target, source) => {
|
|
52
|
+
Object.entries(source).forEach(([key, value]) => {
|
|
53
|
+
if (value && typeof value === "object" && !Array.isArray(value) && typeof target[key] === "object") {
|
|
54
|
+
apply(target[key], value);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
target[key] = value;
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
apply(clone, overrides);
|
|
61
|
+
return clone;
|
|
62
|
+
};
|
|
63
|
+
var portalThemeTokens = mergeTokens(baseTokens);
|
|
64
|
+
var createPortalTheme = (overrides) => mergeTokens(baseTokens, overrides);
|
|
65
|
+
|
|
66
|
+
export { createPortalTheme, portalThemeTokens };
|
|
67
|
+
//# sourceMappingURL=index.js.map
|
|
68
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/tokens/index.ts"],"names":[],"mappings":";;;;;;AAoCA,IAAM,UAAA,GAAgC;AAAA,EACpC,MAAA,EAAQ;AAAA,IACN,UAAA,EAAY,SAAA;AAAA,IACZ,UAAA,EAAY,SAAA;AAAA,IACZ,YAAA,EAAc,SAAA;AAAA,IACd,OAAA,EAAS,SAAA;AAAA,IACT,SAAA,EAAW,SAAA;AAAA,IACX,SAAA,EAAW,SAAA;AAAA,IACX,WAAA,EAAa,SAAA;AAAA,IACb,OAAA,EAAS,SAAA;AAAA,IACT,OAAA,EAAS,SAAA;AAAA,IACT,MAAA,EAAQ;AAAA,GACV;AAAA,EACA,KAAA,EAAO;AAAA,IACL,EAAA,EAAI,MAAA;AAAA,IACJ,EAAA,EAAI,MAAA;AAAA,IACJ,EAAA,EAAI;AAAA,GACN;AAAA,EACA,OAAA,EAAS;AAAA,IACP,EAAA,EAAI,SAAA;AAAA,IACJ,EAAA,EAAI,QAAA;AAAA,IACJ,EAAA,EAAI,SAAA;AAAA,IACJ,EAAA,EAAI,MAAA;AAAA,IACJ,EAAA,EAAI;AAAA,GACN;AAAA,EACA,UAAA,EAAY;AAAA,IACV,UAAA,EACE,2EAAA;AAAA,IACF,UAAA,EAAY,yDAAA;AAAA,IACZ,UAAA,EAAY;AAAA,MACV,KAAA,EAAO,KAAA;AAAA,MACP,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA;AACX,GACF;AAAA,EACA,OAAA,EAAS;AAAA,IACP,KAAA,EAAO,wDAAA;AAAA,IACP,OAAA,EAAS;AAAA;AAEb,CAAA;AAEA,IAAM,WAAA,GAAc,CAClB,IAAA,EACA,SAAA,KACsB;AACtB,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,KAAA,GAAQ,gBAAgB,IAAI,CAAA;AAElC,EAAA,MAAM,KAAA,GAAQ,CAAC,MAAA,EAA6B,MAAA,KAAgC;AAC1E,IAAA,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM;AAC/C,MAAA,IACE,KAAA,IACA,OAAO,KAAA,KAAU,QAAA,IACjB,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,IACpB,OAAO,MAAA,CAAO,GAAG,MAAM,QAAA,EACvB;AACA,QAAA,KAAA,CAAM,MAAA,CAAO,GAAG,CAAA,EAAG,KAAK,CAAA;AACxB,QAAA;AAAA,MACF;AAEA,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,IAChB,CAAC,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,KAAA,CAAM,OAA8B,SAAgC,CAAA;AACpE,EAAA,OAAO,KAAA;AACT,CAAA;AAEO,IAAM,iBAAA,GACX,YAAY,UAAU;AAEjB,IAAM,iBAAA,GAAoB,CAC/B,SAAA,KACG,WAAA,CAAY,YAAY,SAAS","file":"index.js","sourcesContent":["type DeepPartial<T> = {\n [Key in keyof T]?: T[Key] extends Record<string, unknown>\n ? DeepPartial<T[Key]>\n : T[Key];\n};\n\nexport interface PortalThemeTokens {\n colors: {\n background: string;\n foreground: string;\n surfaceMuted: string;\n primary: string;\n onPrimary: string;\n secondary: string;\n onSecondary: string;\n success: string;\n warning: string;\n danger: string;\n };\n radii: {\n lg: string;\n md: string;\n sm: string;\n };\n spacing: Record<\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\", string>;\n typography: {\n fontFamily: string;\n monoFamily: string;\n lineHeight: Record<\"tight\" | \"normal\" | \"relaxed\", string>;\n };\n shadows: {\n focus: string;\n overlay: string;\n };\n}\n\nconst baseTokens: PortalThemeTokens = {\n colors: {\n background: \"#0b0d12\",\n foreground: \"#f4f6fb\",\n surfaceMuted: \"#1b1f2a\",\n primary: \"#0d6efd\",\n onPrimary: \"#ffffff\",\n secondary: \"#6c757d\",\n onSecondary: \"#ffffff\",\n success: \"#22c55e\",\n warning: \"#fbbf24\",\n danger: \"#ef4444\"\n },\n radii: {\n lg: \"16px\",\n md: \"10px\",\n sm: \"6px\"\n },\n spacing: {\n xs: \"0.25rem\",\n sm: \"0.5rem\",\n md: \"0.75rem\",\n lg: \"1rem\",\n xl: \"1.5rem\"\n },\n typography: {\n fontFamily:\n \"Inter, 'SF Pro Display', 'Segoe UI', system-ui, -apple-system, sans-serif\",\n monoFamily: \"'JetBrains Mono', 'SFMono-Regular', Consolas, monospace\",\n lineHeight: {\n tight: \"1.2\",\n normal: \"1.5\",\n relaxed: \"1.75\"\n }\n },\n shadows: {\n focus: \"0 0 0 3px color-mix(in srgb, #0d6efd 35%, transparent)\",\n overlay: \"0px 20px 55px rgba(5, 7, 11, 0.5)\"\n }\n};\n\nconst mergeTokens = (\n base: PortalThemeTokens,\n overrides?: DeepPartial<PortalThemeTokens>\n): PortalThemeTokens => {\n if (!overrides) {\n return base;\n }\n\n const clone = structuredClone(base);\n\n const apply = (target: Record<string, any>, source: Record<string, any>) => {\n Object.entries(source).forEach(([key, value]) => {\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n typeof target[key] === \"object\"\n ) {\n apply(target[key], value);\n return;\n }\n\n target[key] = value;\n });\n };\n\n apply(clone as Record<string, any>, overrides as Record<string, any>);\n return clone;\n};\n\nexport const portalThemeTokens: PortalThemeTokens =\n mergeTokens(baseTokens);\n\nexport const createPortalTheme = (\n overrides?: DeepPartial<PortalThemeTokens>\n) => mergeTokens(baseTokens, overrides);\n\nexport type { DeepPartial as PortalThemeOverrides };\n"]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
export { PortalThemeOverrides, PortalThemeTokens, createPortalTheme, portalThemeTokens } from './tokens/index.mjs';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
4
|
+
export { PortalActionContext, PortalActionVisibility, PortalServerActionDefinition, defineServerAction } from './actions/index.mjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Types that describe the metadata schema documented in
|
|
8
|
+
* proposals/enterprise_portal_builder.md.
|
|
9
|
+
* The component registry generator consumes these definitions to keep the JSON
|
|
10
|
+
* manifest consistent with what the LLM expects.
|
|
11
|
+
*/
|
|
12
|
+
type ComponentCategory = "primitive" | "pattern" | "layout" | "enterprise";
|
|
13
|
+
type ComponentBehaviorMode = "server" | "client" | "hybrid";
|
|
14
|
+
interface ComponentPropConstraints {
|
|
15
|
+
min?: number;
|
|
16
|
+
max?: number;
|
|
17
|
+
allowedValues?: Array<string | number>;
|
|
18
|
+
pattern?: string;
|
|
19
|
+
}
|
|
20
|
+
interface ComponentPropDeprecation {
|
|
21
|
+
message: string;
|
|
22
|
+
replacement?: string;
|
|
23
|
+
}
|
|
24
|
+
interface ComponentPropMetadata {
|
|
25
|
+
name: string;
|
|
26
|
+
type: string;
|
|
27
|
+
required: boolean;
|
|
28
|
+
defaultValue?: string;
|
|
29
|
+
description: string;
|
|
30
|
+
constraints?: ComponentPropConstraints;
|
|
31
|
+
deprecation?: ComponentPropDeprecation;
|
|
32
|
+
}
|
|
33
|
+
interface CompositionRuleMetadata {
|
|
34
|
+
requiredParents?: string[];
|
|
35
|
+
requiredChildren?: string[];
|
|
36
|
+
forbiddenChildren?: string[];
|
|
37
|
+
slots?: string[];
|
|
38
|
+
}
|
|
39
|
+
interface ComponentExampleMetadata {
|
|
40
|
+
id: string;
|
|
41
|
+
description: string;
|
|
42
|
+
code: string;
|
|
43
|
+
scenario: string;
|
|
44
|
+
}
|
|
45
|
+
interface ComponentBehaviorMetadata {
|
|
46
|
+
mode: ComponentBehaviorMode;
|
|
47
|
+
requiresJavaScript: boolean;
|
|
48
|
+
dataAccess: "none" | "server-action" | "client-hook";
|
|
49
|
+
managesState: "presentational" | "local-state" | "controlled";
|
|
50
|
+
}
|
|
51
|
+
interface ComponentAccessibilityMetadata {
|
|
52
|
+
aria?: string[];
|
|
53
|
+
keyboard?: string[];
|
|
54
|
+
screenReader?: string[];
|
|
55
|
+
focusManagement?: string[];
|
|
56
|
+
}
|
|
57
|
+
interface ComponentPerformanceMetadata {
|
|
58
|
+
bundleImpact: "low" | "medium" | "high";
|
|
59
|
+
notes?: string;
|
|
60
|
+
lazyLoadable?: boolean;
|
|
61
|
+
virtualization?: boolean;
|
|
62
|
+
}
|
|
63
|
+
interface ComponentRegistryEntry {
|
|
64
|
+
name: string;
|
|
65
|
+
displayName: string;
|
|
66
|
+
versionIntroduced: string;
|
|
67
|
+
stability: "experimental" | "beta" | "stable" | "deprecated";
|
|
68
|
+
category: ComponentCategory;
|
|
69
|
+
tags: string[];
|
|
70
|
+
description: string;
|
|
71
|
+
props: ComponentPropMetadata[];
|
|
72
|
+
composition: CompositionRuleMetadata;
|
|
73
|
+
examples: ComponentExampleMetadata[];
|
|
74
|
+
behavior: ComponentBehaviorMetadata;
|
|
75
|
+
accessibility: ComponentAccessibilityMetadata;
|
|
76
|
+
performance: ComponentPerformanceMetadata;
|
|
77
|
+
relatedComponents?: string[];
|
|
78
|
+
}
|
|
79
|
+
interface ComponentRegistryDocument {
|
|
80
|
+
version: string;
|
|
81
|
+
generatedAt: string;
|
|
82
|
+
components: ComponentRegistryEntry[];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
declare const buttonVariants: readonly ["primary", "secondary", "ghost", "destructive"];
|
|
86
|
+
declare const buttonSizes: readonly ["sm", "md", "lg"];
|
|
87
|
+
type ButtonVariant = (typeof buttonVariants)[number];
|
|
88
|
+
type ButtonSize = (typeof buttonSizes)[number];
|
|
89
|
+
interface ButtonProps extends ComponentPropsWithoutRef<"button"> {
|
|
90
|
+
variant?: ButtonVariant;
|
|
91
|
+
size?: ButtonSize;
|
|
92
|
+
isLoading?: boolean;
|
|
93
|
+
leadingIcon?: ReactNode;
|
|
94
|
+
trailingIcon?: ReactNode;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Button is the primary interactive primitive for triggering portal actions.
|
|
98
|
+
* It is theme aware via CSS variables generated from portal tokens.
|
|
99
|
+
*/
|
|
100
|
+
declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
|
|
101
|
+
|
|
102
|
+
interface LoginProps extends Omit<ComponentPropsWithoutRef<"form">, "onSubmit" | "children"> {
|
|
103
|
+
logo?: ReactNode;
|
|
104
|
+
title?: string;
|
|
105
|
+
description?: string;
|
|
106
|
+
label?: string;
|
|
107
|
+
placeholder?: string;
|
|
108
|
+
ctaLabel?: string;
|
|
109
|
+
initialEmail?: string;
|
|
110
|
+
isSubmitting?: boolean;
|
|
111
|
+
onContinue?: (email: string) => Promise<void> | void;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Login renders a compact form card tailored for portal authentication flows.
|
|
115
|
+
* The component keeps styling self-contained so it can be dropped into the
|
|
116
|
+
* local Next.js template without additional wrappers.
|
|
117
|
+
*/
|
|
118
|
+
declare const Login: react.ForwardRefExoticComponent<LoginProps & react.RefAttributes<HTMLFormElement>>;
|
|
119
|
+
|
|
120
|
+
declare const portalComponentsVersion: string;
|
|
121
|
+
|
|
122
|
+
export { Button, type ButtonProps, type ButtonSize, type ButtonVariant, type ComponentAccessibilityMetadata, type ComponentBehaviorMetadata, type ComponentCategory, type ComponentExampleMetadata, type ComponentPerformanceMetadata, type ComponentPropMetadata, type ComponentRegistryDocument, type ComponentRegistryEntry, Login, type LoginProps, portalComponentsVersion };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
export { PortalThemeOverrides, PortalThemeTokens, createPortalTheme, portalThemeTokens } from './tokens/index.js';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
4
|
+
export { PortalActionContext, PortalActionVisibility, PortalServerActionDefinition, defineServerAction } from './actions/index.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Types that describe the metadata schema documented in
|
|
8
|
+
* proposals/enterprise_portal_builder.md.
|
|
9
|
+
* The component registry generator consumes these definitions to keep the JSON
|
|
10
|
+
* manifest consistent with what the LLM expects.
|
|
11
|
+
*/
|
|
12
|
+
type ComponentCategory = "primitive" | "pattern" | "layout" | "enterprise";
|
|
13
|
+
type ComponentBehaviorMode = "server" | "client" | "hybrid";
|
|
14
|
+
interface ComponentPropConstraints {
|
|
15
|
+
min?: number;
|
|
16
|
+
max?: number;
|
|
17
|
+
allowedValues?: Array<string | number>;
|
|
18
|
+
pattern?: string;
|
|
19
|
+
}
|
|
20
|
+
interface ComponentPropDeprecation {
|
|
21
|
+
message: string;
|
|
22
|
+
replacement?: string;
|
|
23
|
+
}
|
|
24
|
+
interface ComponentPropMetadata {
|
|
25
|
+
name: string;
|
|
26
|
+
type: string;
|
|
27
|
+
required: boolean;
|
|
28
|
+
defaultValue?: string;
|
|
29
|
+
description: string;
|
|
30
|
+
constraints?: ComponentPropConstraints;
|
|
31
|
+
deprecation?: ComponentPropDeprecation;
|
|
32
|
+
}
|
|
33
|
+
interface CompositionRuleMetadata {
|
|
34
|
+
requiredParents?: string[];
|
|
35
|
+
requiredChildren?: string[];
|
|
36
|
+
forbiddenChildren?: string[];
|
|
37
|
+
slots?: string[];
|
|
38
|
+
}
|
|
39
|
+
interface ComponentExampleMetadata {
|
|
40
|
+
id: string;
|
|
41
|
+
description: string;
|
|
42
|
+
code: string;
|
|
43
|
+
scenario: string;
|
|
44
|
+
}
|
|
45
|
+
interface ComponentBehaviorMetadata {
|
|
46
|
+
mode: ComponentBehaviorMode;
|
|
47
|
+
requiresJavaScript: boolean;
|
|
48
|
+
dataAccess: "none" | "server-action" | "client-hook";
|
|
49
|
+
managesState: "presentational" | "local-state" | "controlled";
|
|
50
|
+
}
|
|
51
|
+
interface ComponentAccessibilityMetadata {
|
|
52
|
+
aria?: string[];
|
|
53
|
+
keyboard?: string[];
|
|
54
|
+
screenReader?: string[];
|
|
55
|
+
focusManagement?: string[];
|
|
56
|
+
}
|
|
57
|
+
interface ComponentPerformanceMetadata {
|
|
58
|
+
bundleImpact: "low" | "medium" | "high";
|
|
59
|
+
notes?: string;
|
|
60
|
+
lazyLoadable?: boolean;
|
|
61
|
+
virtualization?: boolean;
|
|
62
|
+
}
|
|
63
|
+
interface ComponentRegistryEntry {
|
|
64
|
+
name: string;
|
|
65
|
+
displayName: string;
|
|
66
|
+
versionIntroduced: string;
|
|
67
|
+
stability: "experimental" | "beta" | "stable" | "deprecated";
|
|
68
|
+
category: ComponentCategory;
|
|
69
|
+
tags: string[];
|
|
70
|
+
description: string;
|
|
71
|
+
props: ComponentPropMetadata[];
|
|
72
|
+
composition: CompositionRuleMetadata;
|
|
73
|
+
examples: ComponentExampleMetadata[];
|
|
74
|
+
behavior: ComponentBehaviorMetadata;
|
|
75
|
+
accessibility: ComponentAccessibilityMetadata;
|
|
76
|
+
performance: ComponentPerformanceMetadata;
|
|
77
|
+
relatedComponents?: string[];
|
|
78
|
+
}
|
|
79
|
+
interface ComponentRegistryDocument {
|
|
80
|
+
version: string;
|
|
81
|
+
generatedAt: string;
|
|
82
|
+
components: ComponentRegistryEntry[];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
declare const buttonVariants: readonly ["primary", "secondary", "ghost", "destructive"];
|
|
86
|
+
declare const buttonSizes: readonly ["sm", "md", "lg"];
|
|
87
|
+
type ButtonVariant = (typeof buttonVariants)[number];
|
|
88
|
+
type ButtonSize = (typeof buttonSizes)[number];
|
|
89
|
+
interface ButtonProps extends ComponentPropsWithoutRef<"button"> {
|
|
90
|
+
variant?: ButtonVariant;
|
|
91
|
+
size?: ButtonSize;
|
|
92
|
+
isLoading?: boolean;
|
|
93
|
+
leadingIcon?: ReactNode;
|
|
94
|
+
trailingIcon?: ReactNode;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Button is the primary interactive primitive for triggering portal actions.
|
|
98
|
+
* It is theme aware via CSS variables generated from portal tokens.
|
|
99
|
+
*/
|
|
100
|
+
declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
|
|
101
|
+
|
|
102
|
+
interface LoginProps extends Omit<ComponentPropsWithoutRef<"form">, "onSubmit" | "children"> {
|
|
103
|
+
logo?: ReactNode;
|
|
104
|
+
title?: string;
|
|
105
|
+
description?: string;
|
|
106
|
+
label?: string;
|
|
107
|
+
placeholder?: string;
|
|
108
|
+
ctaLabel?: string;
|
|
109
|
+
initialEmail?: string;
|
|
110
|
+
isSubmitting?: boolean;
|
|
111
|
+
onContinue?: (email: string) => Promise<void> | void;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Login renders a compact form card tailored for portal authentication flows.
|
|
115
|
+
* The component keeps styling self-contained so it can be dropped into the
|
|
116
|
+
* local Next.js template without additional wrappers.
|
|
117
|
+
*/
|
|
118
|
+
declare const Login: react.ForwardRefExoticComponent<LoginProps & react.RefAttributes<HTMLFormElement>>;
|
|
119
|
+
|
|
120
|
+
declare const portalComponentsVersion: string;
|
|
121
|
+
|
|
122
|
+
export { Button, type ButtonProps, type ButtonSize, type ButtonVariant, type ComponentAccessibilityMetadata, type ComponentBehaviorMetadata, type ComponentCategory, type ComponentExampleMetadata, type ComponentPerformanceMetadata, type ComponentPropMetadata, type ComponentRegistryDocument, type ComponentRegistryEntry, Login, type LoginProps, portalComponentsVersion };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Enterprise Portal Components
|
|
8
|
+
* This file is generated by tsup. Do not edit manually.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// package.json
|
|
12
|
+
var package_default = {
|
|
13
|
+
version: "0.0.1"};
|
|
14
|
+
|
|
15
|
+
// src/tokens/index.ts
|
|
16
|
+
var baseTokens = {
|
|
17
|
+
colors: {
|
|
18
|
+
background: "#0b0d12",
|
|
19
|
+
foreground: "#f4f6fb",
|
|
20
|
+
surfaceMuted: "#1b1f2a",
|
|
21
|
+
primary: "#0d6efd",
|
|
22
|
+
onPrimary: "#ffffff",
|
|
23
|
+
secondary: "#6c757d",
|
|
24
|
+
onSecondary: "#ffffff",
|
|
25
|
+
success: "#22c55e",
|
|
26
|
+
warning: "#fbbf24",
|
|
27
|
+
danger: "#ef4444"
|
|
28
|
+
},
|
|
29
|
+
radii: {
|
|
30
|
+
lg: "16px",
|
|
31
|
+
md: "10px",
|
|
32
|
+
sm: "6px"
|
|
33
|
+
},
|
|
34
|
+
spacing: {
|
|
35
|
+
xs: "0.25rem",
|
|
36
|
+
sm: "0.5rem",
|
|
37
|
+
md: "0.75rem",
|
|
38
|
+
lg: "1rem",
|
|
39
|
+
xl: "1.5rem"
|
|
40
|
+
},
|
|
41
|
+
typography: {
|
|
42
|
+
fontFamily: "Inter, 'SF Pro Display', 'Segoe UI', system-ui, -apple-system, sans-serif",
|
|
43
|
+
monoFamily: "'JetBrains Mono', 'SFMono-Regular', Consolas, monospace",
|
|
44
|
+
lineHeight: {
|
|
45
|
+
tight: "1.2",
|
|
46
|
+
normal: "1.5",
|
|
47
|
+
relaxed: "1.75"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
shadows: {
|
|
51
|
+
focus: "0 0 0 3px color-mix(in srgb, #0d6efd 35%, transparent)",
|
|
52
|
+
overlay: "0px 20px 55px rgba(5, 7, 11, 0.5)"
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var mergeTokens = (base, overrides) => {
|
|
56
|
+
if (!overrides) {
|
|
57
|
+
return base;
|
|
58
|
+
}
|
|
59
|
+
const clone = structuredClone(base);
|
|
60
|
+
const apply = (target, source) => {
|
|
61
|
+
Object.entries(source).forEach(([key, value]) => {
|
|
62
|
+
if (value && typeof value === "object" && !Array.isArray(value) && typeof target[key] === "object") {
|
|
63
|
+
apply(target[key], value);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
target[key] = value;
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
apply(clone, overrides);
|
|
70
|
+
return clone;
|
|
71
|
+
};
|
|
72
|
+
var portalThemeTokens = mergeTokens(baseTokens);
|
|
73
|
+
var createPortalTheme = (overrides) => mergeTokens(baseTokens, overrides);
|
|
74
|
+
var variantStyles = {
|
|
75
|
+
primary: "bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-primary",
|
|
76
|
+
secondary: "bg-secondary/20 text-secondary-foreground hover:bg-secondary/30 focus-visible:ring-secondary",
|
|
77
|
+
ghost: "bg-transparent text-primary hover:bg-primary/10 focus-visible:ring-primary/60",
|
|
78
|
+
destructive: "bg-danger text-white hover:bg-danger/90 focus-visible:ring-danger"
|
|
79
|
+
};
|
|
80
|
+
var sizeStyles = {
|
|
81
|
+
sm: "h-8 px-3 text-sm",
|
|
82
|
+
md: "h-10 px-4 text-sm",
|
|
83
|
+
lg: "h-12 px-6 text-base"
|
|
84
|
+
};
|
|
85
|
+
var inlineFlexBase = "inline-flex items-center justify-center gap-2 rounded-md font-medium tracking-tight transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-60";
|
|
86
|
+
var Spinner = () => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex h-3.5 w-3.5 animate-spin items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-3 w-3 rounded-full border-2 border-transparent border-t-current" }) });
|
|
87
|
+
var composeClassName = (...values) => values.filter(Boolean).join(" ");
|
|
88
|
+
var Button = react.forwardRef(
|
|
89
|
+
({
|
|
90
|
+
variant = "primary",
|
|
91
|
+
size = "md",
|
|
92
|
+
type = "button",
|
|
93
|
+
isLoading = false,
|
|
94
|
+
leadingIcon,
|
|
95
|
+
trailingIcon,
|
|
96
|
+
disabled,
|
|
97
|
+
className,
|
|
98
|
+
children,
|
|
99
|
+
...props
|
|
100
|
+
}, ref) => {
|
|
101
|
+
const computedLeading = isLoading ? /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) : leadingIcon;
|
|
102
|
+
const computedDisabled = disabled ?? isLoading;
|
|
103
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
104
|
+
"button",
|
|
105
|
+
{
|
|
106
|
+
ref,
|
|
107
|
+
type,
|
|
108
|
+
className: composeClassName(
|
|
109
|
+
inlineFlexBase,
|
|
110
|
+
variantStyles[variant],
|
|
111
|
+
sizeStyles[size],
|
|
112
|
+
className
|
|
113
|
+
),
|
|
114
|
+
"aria-busy": isLoading || void 0,
|
|
115
|
+
disabled: computedDisabled,
|
|
116
|
+
...props,
|
|
117
|
+
children: [
|
|
118
|
+
computedLeading ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "inline-flex", children: computedLeading }) : null,
|
|
119
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 whitespace-nowrap", children }),
|
|
120
|
+
trailingIcon ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "inline-flex", children: trailingIcon }) : null
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
Button.displayName = "Button";
|
|
127
|
+
var Login = react.forwardRef(
|
|
128
|
+
({
|
|
129
|
+
logo,
|
|
130
|
+
title = "Enterprise Factory Installation Portal",
|
|
131
|
+
description = "Sign in to manage your enterprise installation",
|
|
132
|
+
label = "Work email address",
|
|
133
|
+
placeholder = "you@company.com",
|
|
134
|
+
ctaLabel = "Continue with email \u2192",
|
|
135
|
+
initialEmail = "",
|
|
136
|
+
isSubmitting = false,
|
|
137
|
+
onContinue,
|
|
138
|
+
className,
|
|
139
|
+
...props
|
|
140
|
+
}, ref) => {
|
|
141
|
+
const [email, setEmail] = react.useState(initialEmail);
|
|
142
|
+
const [pending, setPending] = react.useState(false);
|
|
143
|
+
const handleSubmit = async (event) => {
|
|
144
|
+
event.preventDefault();
|
|
145
|
+
if (!onContinue) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
setPending(true);
|
|
150
|
+
await onContinue(email);
|
|
151
|
+
} finally {
|
|
152
|
+
setPending(false);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const disabled = isSubmitting || pending;
|
|
156
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
157
|
+
"form",
|
|
158
|
+
{
|
|
159
|
+
ref,
|
|
160
|
+
className: [
|
|
161
|
+
"w-full max-w-md rounded-3xl border border-white/15 bg-slate-950/80 p-10 shadow-[0_25px_70px_rgba(5,7,11,0.65)] backdrop-blur",
|
|
162
|
+
"text-white transition-shadow",
|
|
163
|
+
className
|
|
164
|
+
].filter(Boolean).join(" "),
|
|
165
|
+
onSubmit: handleSubmit,
|
|
166
|
+
...props,
|
|
167
|
+
children: [
|
|
168
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-4 text-center", children: [
|
|
169
|
+
logo ?? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-16 w-16 items-center justify-center rounded-2xl border border-white/20 bg-white/10 text-lg font-semibold leading-tight", children: "EP" }),
|
|
170
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
171
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base font-semibold uppercase tracking-[0.35em] text-white/65", children: "Enterprise Portal" }),
|
|
172
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "mt-3 text-3xl font-semibold tracking-tight", children: title }),
|
|
173
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-white/70", children: description })
|
|
174
|
+
] })
|
|
175
|
+
] }),
|
|
176
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-8 space-y-3", children: [
|
|
177
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
178
|
+
"label",
|
|
179
|
+
{
|
|
180
|
+
htmlFor: "login-email",
|
|
181
|
+
className: "text-sm font-medium text-white/70",
|
|
182
|
+
children: label
|
|
183
|
+
}
|
|
184
|
+
),
|
|
185
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
186
|
+
"input",
|
|
187
|
+
{
|
|
188
|
+
id: "login-email",
|
|
189
|
+
type: "email",
|
|
190
|
+
inputMode: "email",
|
|
191
|
+
autoComplete: "email",
|
|
192
|
+
placeholder,
|
|
193
|
+
value: email,
|
|
194
|
+
onChange: (event) => setEmail(event.target.value),
|
|
195
|
+
className: "w-full rounded-2xl border border-white/15 bg-white/5 px-5 py-4 text-base text-white placeholder:text-white/40 focus:border-white/40 focus:outline-none focus:ring-2 focus:ring-white/25",
|
|
196
|
+
disabled,
|
|
197
|
+
required: true
|
|
198
|
+
}
|
|
199
|
+
),
|
|
200
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
201
|
+
Button,
|
|
202
|
+
{
|
|
203
|
+
type: "submit",
|
|
204
|
+
size: "lg",
|
|
205
|
+
className: "w-full justify-center",
|
|
206
|
+
disabled,
|
|
207
|
+
isLoading: disabled,
|
|
208
|
+
children: ctaLabel
|
|
209
|
+
}
|
|
210
|
+
)
|
|
211
|
+
] })
|
|
212
|
+
]
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
);
|
|
217
|
+
Login.displayName = "Login";
|
|
218
|
+
|
|
219
|
+
// src/actions/index.ts
|
|
220
|
+
var defineServerAction = (definition) => definition;
|
|
221
|
+
|
|
222
|
+
// src/index.ts
|
|
223
|
+
var portalComponentsVersion = package_default.version;
|
|
224
|
+
|
|
225
|
+
exports.Button = Button;
|
|
226
|
+
exports.Login = Login;
|
|
227
|
+
exports.createPortalTheme = createPortalTheme;
|
|
228
|
+
exports.defineServerAction = defineServerAction;
|
|
229
|
+
exports.portalComponentsVersion = portalComponentsVersion;
|
|
230
|
+
exports.portalThemeTokens = portalThemeTokens;
|
|
231
|
+
//# sourceMappingURL=index.js.map
|
|
232
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/tokens/index.ts","../src/components/button.tsx","../src/components/login.tsx","../src/actions/index.ts","../src/index.ts"],"names":["jsx","forwardRef","jsxs","useState"],"mappings":"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","file":"index.js","sourcesContent":["{\n \"name\": \"@replicated/portal-components\",\n \"version\": \"0.0.1\",\n \"description\": \"Opinionated component library for Replicated enterprise portals\",\n \"license\": \"Apache-2.0\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/replicatedhq/enterprise-portal-components.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/replicatedhq/enterprise-portal-components/issues\"\n },\n \"homepage\": \"https://github.com/replicatedhq/enterprise-portal-components#readme\",\n \"main\": \"dist/index.js\",\n \"module\": \"dist/esm/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"style\": \"dist/styles.css\",\n \"files\": [\n \"dist\",\n \"components/metadata\"\n ],\n \"sideEffects\": [\n \"*.css\",\n \"*.scss\"\n ],\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/esm/index.js\",\n \"require\": \"./dist/index.js\"\n },\n \"./tokens\": {\n \"types\": \"./dist/tokens/index.d.ts\",\n \"import\": \"./dist/esm/tokens/index.js\",\n \"require\": \"./dist/tokens/index.js\"\n },\n \"./actions\": {\n \"types\": \"./dist/actions/index.d.ts\",\n \"import\": \"./dist/esm/actions/index.js\",\n \"require\": \"./dist/actions/index.js\"\n },\n \"./styles.css\": \"./dist/styles.css\",\n \"./metadata/registry.json\": \"./components/metadata/registry.json\"\n },\n \"scripts\": {\n \"clean\": \"rimraf dist\",\n \"build\": \"npm run clean && npm run registry:generate && npm run build:css && tsup\",\n \"build:css\": \"tailwindcss -i ./src/styles.css -o ./dist/styles.css --config tailwind.config.ts\",\n \"dev\": \"tsup --watch\",\n \"typecheck\": \"tsc --noEmit\",\n \"registry:generate\": \"tsx scripts/generate-registry.ts\",\n \"size\": \"size-limit\",\n \"release\": \"changeset\"\n },\n \"peerDependencies\": {\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\"\n },\n \"devDependencies\": {\n \"@changesets/cli\": \"^2.27.8\",\n \"@size-limit/preset-big-lib\": \"^9.0.0\",\n \"@types/node\": \"^22.10.1\",\n \"@types/react\": \"^19.0.4\",\n \"@types/react-dom\": \"^19.0.3\",\n \"autoprefixer\": \"^10.4.20\",\n \"postcss\": \"^8.4.49\",\n \"react\": \"19.0.0\",\n \"react-dom\": \"19.0.0\",\n \"rimraf\": \"^6.0.1\",\n \"size-limit\": \"^9.0.0\",\n \"tailwindcss\": \"^3.4.17\",\n \"tslib\": \"^2.7.0\",\n \"tsup\": \"^8.3.5\",\n \"tsx\": \"^4.19.2\",\n \"typescript\": \"^5.6.3\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"packageManager\": \"npm@10\",\n \"size-limit\": [\n {\n \"name\": \"core entry\",\n \"path\": \"dist/esm/index.js\",\n \"import\": \"{ Login }\",\n \"limit\": \"35 KB\",\n \"gzip\": true\n }\n ]\n}\n","type DeepPartial<T> = {\n [Key in keyof T]?: T[Key] extends Record<string, unknown>\n ? DeepPartial<T[Key]>\n : T[Key];\n};\n\nexport interface PortalThemeTokens {\n colors: {\n background: string;\n foreground: string;\n surfaceMuted: string;\n primary: string;\n onPrimary: string;\n secondary: string;\n onSecondary: string;\n success: string;\n warning: string;\n danger: string;\n };\n radii: {\n lg: string;\n md: string;\n sm: string;\n };\n spacing: Record<\"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\", string>;\n typography: {\n fontFamily: string;\n monoFamily: string;\n lineHeight: Record<\"tight\" | \"normal\" | \"relaxed\", string>;\n };\n shadows: {\n focus: string;\n overlay: string;\n };\n}\n\nconst baseTokens: PortalThemeTokens = {\n colors: {\n background: \"#0b0d12\",\n foreground: \"#f4f6fb\",\n surfaceMuted: \"#1b1f2a\",\n primary: \"#0d6efd\",\n onPrimary: \"#ffffff\",\n secondary: \"#6c757d\",\n onSecondary: \"#ffffff\",\n success: \"#22c55e\",\n warning: \"#fbbf24\",\n danger: \"#ef4444\"\n },\n radii: {\n lg: \"16px\",\n md: \"10px\",\n sm: \"6px\"\n },\n spacing: {\n xs: \"0.25rem\",\n sm: \"0.5rem\",\n md: \"0.75rem\",\n lg: \"1rem\",\n xl: \"1.5rem\"\n },\n typography: {\n fontFamily:\n \"Inter, 'SF Pro Display', 'Segoe UI', system-ui, -apple-system, sans-serif\",\n monoFamily: \"'JetBrains Mono', 'SFMono-Regular', Consolas, monospace\",\n lineHeight: {\n tight: \"1.2\",\n normal: \"1.5\",\n relaxed: \"1.75\"\n }\n },\n shadows: {\n focus: \"0 0 0 3px color-mix(in srgb, #0d6efd 35%, transparent)\",\n overlay: \"0px 20px 55px rgba(5, 7, 11, 0.5)\"\n }\n};\n\nconst mergeTokens = (\n base: PortalThemeTokens,\n overrides?: DeepPartial<PortalThemeTokens>\n): PortalThemeTokens => {\n if (!overrides) {\n return base;\n }\n\n const clone = structuredClone(base);\n\n const apply = (target: Record<string, any>, source: Record<string, any>) => {\n Object.entries(source).forEach(([key, value]) => {\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n typeof target[key] === \"object\"\n ) {\n apply(target[key], value);\n return;\n }\n\n target[key] = value;\n });\n };\n\n apply(clone as Record<string, any>, overrides as Record<string, any>);\n return clone;\n};\n\nexport const portalThemeTokens: PortalThemeTokens =\n mergeTokens(baseTokens);\n\nexport const createPortalTheme = (\n overrides?: DeepPartial<PortalThemeTokens>\n) => mergeTokens(baseTokens, overrides);\n\nexport type { DeepPartial as PortalThemeOverrides };\n","import {\n forwardRef,\n type ComponentPropsWithoutRef,\n type ReactNode\n} from \"react\";\n\nconst buttonVariants = [\"primary\", \"secondary\", \"ghost\", \"destructive\"] as const;\nconst buttonSizes = [\"sm\", \"md\", \"lg\"] as const;\n\nconst variantStyles: Record<ButtonVariant, string> = {\n primary:\n \"bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-primary\",\n secondary:\n \"bg-secondary/20 text-secondary-foreground hover:bg-secondary/30 focus-visible:ring-secondary\",\n ghost:\n \"bg-transparent text-primary hover:bg-primary/10 focus-visible:ring-primary/60\",\n destructive:\n \"bg-danger text-white hover:bg-danger/90 focus-visible:ring-danger\"\n};\n\nconst sizeStyles: Record<ButtonSize, string> = {\n sm: \"h-8 px-3 text-sm\",\n md: \"h-10 px-4 text-sm\",\n lg: \"h-12 px-6 text-base\"\n};\n\nconst inlineFlexBase =\n \"inline-flex items-center justify-center gap-2 rounded-md font-medium tracking-tight transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-60\";\n\nconst Spinner = () => (\n <span className=\"inline-flex h-3.5 w-3.5 animate-spin items-center justify-center\">\n <span className=\"h-3 w-3 rounded-full border-2 border-transparent border-t-current\" />\n </span>\n);\n\nexport type ButtonVariant = (typeof buttonVariants)[number];\nexport type ButtonSize = (typeof buttonSizes)[number];\n\nexport interface ButtonProps extends ComponentPropsWithoutRef<\"button\"> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n isLoading?: boolean;\n leadingIcon?: ReactNode;\n trailingIcon?: ReactNode;\n}\n\nconst composeClassName = (\n ...values: Array<string | undefined | false>\n): string => values.filter(Boolean).join(\" \");\n\n/**\n * Button is the primary interactive primitive for triggering portal actions.\n * It is theme aware via CSS variables generated from portal tokens.\n */\nexport const Button = forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n variant = \"primary\",\n size = \"md\",\n type = \"button\",\n isLoading = false,\n leadingIcon,\n trailingIcon,\n disabled,\n className,\n children,\n ...props\n },\n ref\n ) => {\n const computedLeading = isLoading ? <Spinner /> : leadingIcon;\n const computedDisabled = disabled ?? isLoading;\n\n return (\n <button\n ref={ref}\n type={type}\n className={composeClassName(\n inlineFlexBase,\n variantStyles[variant],\n sizeStyles[size],\n className\n )}\n aria-busy={isLoading || undefined}\n disabled={computedDisabled}\n {...props}\n >\n {computedLeading ? (\n <span aria-hidden=\"true\" className=\"inline-flex\">\n {computedLeading}\n </span>\n ) : null}\n <span className=\"flex-1 whitespace-nowrap\">{children}</span>\n {trailingIcon ? (\n <span aria-hidden=\"true\" className=\"inline-flex\">\n {trailingIcon}\n </span>\n ) : null}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n","'use client';\n\nimport {\n forwardRef,\n useState,\n type ComponentPropsWithoutRef,\n type FormEvent,\n type ReactNode\n} from \"react\";\n\nimport { Button } from \"./button\";\n\nexport interface LoginProps\n extends Omit<ComponentPropsWithoutRef<\"form\">, \"onSubmit\" | \"children\"> {\n logo?: ReactNode;\n title?: string;\n description?: string;\n label?: string;\n placeholder?: string;\n ctaLabel?: string;\n initialEmail?: string;\n isSubmitting?: boolean;\n onContinue?: (email: string) => Promise<void> | void;\n}\n\n/**\n * Login renders a compact form card tailored for portal authentication flows.\n * The component keeps styling self-contained so it can be dropped into the\n * local Next.js template without additional wrappers.\n */\nexport const Login = forwardRef<HTMLFormElement, LoginProps>(\n (\n {\n logo,\n title = \"Enterprise Factory Installation Portal\",\n description = \"Sign in to manage your enterprise installation\",\n label = \"Work email address\",\n placeholder = \"you@company.com\",\n ctaLabel = \"Continue with email →\",\n initialEmail = \"\",\n isSubmitting = false,\n onContinue,\n className,\n ...props\n },\n ref\n ) => {\n const [email, setEmail] = useState(initialEmail);\n const [pending, setPending] = useState(false);\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!onContinue) {\n return;\n }\n\n try {\n setPending(true);\n await onContinue(email);\n } finally {\n setPending(false);\n }\n };\n\n const disabled = isSubmitting || pending;\n\n return (\n <form\n ref={ref}\n className={[\n \"w-full max-w-md rounded-3xl border border-white/15 bg-slate-950/80 p-10 shadow-[0_25px_70px_rgba(5,7,11,0.65)] backdrop-blur\",\n \"text-white transition-shadow\",\n className\n ]\n .filter(Boolean)\n .join(\" \")}\n onSubmit={handleSubmit}\n {...props}\n >\n <div className=\"flex flex-col items-center gap-4 text-center\">\n {logo ?? (\n <div className=\"flex h-16 w-16 items-center justify-center rounded-2xl border border-white/20 bg-white/10 text-lg font-semibold leading-tight\">\n EP\n </div>\n )}\n <div>\n <p className=\"text-base font-semibold uppercase tracking-[0.35em] text-white/65\">\n Enterprise Portal\n </p>\n <h1 className=\"mt-3 text-3xl font-semibold tracking-tight\">\n {title}\n </h1>\n <p className=\"mt-2 text-sm text-white/70\">{description}</p>\n </div>\n </div>\n <div className=\"mt-8 space-y-3\">\n <label\n htmlFor=\"login-email\"\n className=\"text-sm font-medium text-white/70\"\n >\n {label}\n </label>\n <input\n id=\"login-email\"\n type=\"email\"\n inputMode=\"email\"\n autoComplete=\"email\"\n placeholder={placeholder}\n value={email}\n onChange={(event) => setEmail(event.target.value)}\n className=\"w-full rounded-2xl border border-white/15 bg-white/5 px-5 py-4 text-base text-white placeholder:text-white/40 focus:border-white/40 focus:outline-none focus:ring-2 focus:ring-white/25\"\n disabled={disabled}\n required\n />\n <Button\n type=\"submit\"\n size=\"lg\"\n className=\"w-full justify-center\"\n disabled={disabled}\n isLoading={disabled}\n >\n {ctaLabel}\n </Button>\n </div>\n </form>\n );\n }\n);\n\nLogin.displayName = \"Login\";\n","/**\n * Light-weight type helpers for defining Server Actions that align with the\n * enterprise portal guardrails. The component library does not implement\n * specific actions, but it exports helpers so downstream portals can describe\n * their actions with consistent metadata.\n */\n\nexport type PortalActionVisibility = \"vendor\" | \"customer\";\n\nexport interface PortalActionContext {\n vendorId: string;\n licenseId: string;\n userId: string;\n signal?: AbortSignal;\n}\n\nexport interface PortalServerActionDefinition<Input, Output> {\n id: string;\n description: string;\n visibility: PortalActionVisibility;\n tags: string[];\n run: (input: Input, context: PortalActionContext) => Promise<Output>;\n}\n\nexport const defineServerAction = <Input, Output>(\n definition: PortalServerActionDefinition<Input, Output>\n) => definition;\n","import packageJson from \"../package.json\";\n\nexport const portalComponentsVersion = packageJson.version;\n\nexport type {\n ComponentAccessibilityMetadata,\n ComponentBehaviorMetadata,\n ComponentCategory,\n ComponentRegistryDocument,\n ComponentRegistryEntry,\n ComponentExampleMetadata,\n ComponentPerformanceMetadata,\n ComponentPropMetadata\n} from \"./types/metadata\";\n\nexport {\n createPortalTheme,\n portalThemeTokens\n} from \"./tokens\";\nexport type { PortalThemeTokens, PortalThemeOverrides } from \"./tokens\";\n\nexport * from \"./components\";\n\nexport {\n defineServerAction\n} from \"./actions\";\nexport type {\n PortalActionContext,\n PortalActionVisibility,\n PortalServerActionDefinition\n} from \"./actions\";\n"]}
|