@ekanos/ui 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.
@@ -0,0 +1,6 @@
1
+ import * as React from 'react';
2
+ import { Separator as Separator$1 } from '@base-ui/react/separator';
3
+
4
+ declare function Separator({ className, orientation, ...props }: Separator$1.Props): React.JSX.Element;
5
+
6
+ export { Separator };
@@ -0,0 +1,35 @@
1
+ 'use client';
2
+
3
+ // ../ui/src/shadcn/separator.tsx
4
+ import { Separator as SeparatorPrimitive } from "@base-ui/react/separator";
5
+
6
+ // ../ui/src/lib/utils/cn.ts
7
+ import { clsx } from "clsx";
8
+ import { twMerge } from "tailwind-merge";
9
+ function cn(...inputs) {
10
+ return twMerge(clsx(inputs));
11
+ }
12
+
13
+ // ../ui/src/shadcn/separator.tsx
14
+ import { jsx } from "react/jsx-runtime";
15
+ function Separator({
16
+ className,
17
+ orientation = "horizontal",
18
+ ...props
19
+ }) {
20
+ return /* @__PURE__ */ jsx(
21
+ SeparatorPrimitive,
22
+ {
23
+ "data-slot": "separator",
24
+ orientation,
25
+ className: cn(
26
+ "bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
27
+ className
28
+ ),
29
+ ...props
30
+ }
31
+ );
32
+ }
33
+ export {
34
+ Separator
35
+ };
@@ -0,0 +1,5 @@
1
+ import * as React$1 from 'react';
2
+
3
+ declare function Skeleton({ className, ...props }: React.ComponentProps<'div'>): React$1.JSX.Element;
4
+
5
+ export { Skeleton };
@@ -0,0 +1,22 @@
1
+ // ../ui/src/lib/utils/cn.ts
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ function cn(...inputs) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+
8
+ // ../ui/src/shadcn/skeleton.tsx
9
+ import { jsx } from "react/jsx-runtime";
10
+ function Skeleton({ className, ...props }) {
11
+ return /* @__PURE__ */ jsx(
12
+ "div",
13
+ {
14
+ "data-slot": "skeleton",
15
+ className: cn("bg-accent animate-pulse rounded-md", className),
16
+ ...props
17
+ }
18
+ );
19
+ }
20
+ export {
21
+ Skeleton
22
+ };
@@ -0,0 +1,27 @@
1
+ import * as React from 'react';
2
+ import { ComponentProps } from 'react';
3
+
4
+ /**
5
+ * Indeterminate loading indicator.
6
+ *
7
+ * Drawn as an inline SVG so the component carries its own artwork: it needs no
8
+ * icon font, no `lucide-react`, and no client-side runtime. That makes this
9
+ * subpath hook-free and directive-free, so it renders from a React Server
10
+ * Component as happily as from a client one.
11
+ *
12
+ * The two-part figure — a faint full ring under a quarter-turn arc — is what
13
+ * reads as motion while spinning, and still reads as a "busy" glyph when it is
14
+ * held still.
15
+ *
16
+ * Motion is expressed with Tailwind utilities (`animate-spin`, plus
17
+ * `motion-reduce:animate-none` so the arc freezes for anyone who has asked
18
+ * their OS for reduced motion). Like every other component here, the host page
19
+ * owns the stylesheet that defines them.
20
+ *
21
+ * `className` lands on the SVG so the usual sizing and colour utilities apply
22
+ * (`<Spinner className="size-4 text-primary" />`); any other prop lands on the
23
+ * wrapping status element.
24
+ */
25
+ declare function Spinner({ className, ...props }: ComponentProps<'span'>): React.JSX.Element;
26
+
27
+ export { Spinner };
@@ -0,0 +1,49 @@
1
+ // ../ui/src/lib/utils/cn.ts
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ function cn(...inputs) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+
8
+ // src/_impl/spinner.tsx
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+ function Spinner({ className, ...props }) {
11
+ return /* @__PURE__ */ jsx("span", { role: "status", "aria-label": "Loading", ...props, children: /* @__PURE__ */ jsxs(
12
+ "svg",
13
+ {
14
+ viewBox: "0 0 24 24",
15
+ fill: "none",
16
+ "aria-hidden": "true",
17
+ focusable: "false",
18
+ className: cn(
19
+ "text-muted-foreground size-6 animate-spin motion-reduce:animate-none",
20
+ className
21
+ ),
22
+ children: [
23
+ /* @__PURE__ */ jsx(
24
+ "circle",
25
+ {
26
+ cx: "12",
27
+ cy: "12",
28
+ r: "9",
29
+ stroke: "currentColor",
30
+ strokeWidth: "2.5",
31
+ className: "opacity-20"
32
+ }
33
+ ),
34
+ /* @__PURE__ */ jsx(
35
+ "path",
36
+ {
37
+ d: "M21 12a9 9 0 0 0-9-9",
38
+ stroke: "currentColor",
39
+ strokeWidth: "2.5",
40
+ strokeLinecap: "round"
41
+ }
42
+ )
43
+ ]
44
+ }
45
+ ) });
46
+ }
47
+ export {
48
+ Spinner
49
+ };
@@ -0,0 +1,9 @@
1
+ import * as React from 'react';
2
+ import { Tooltip as Tooltip$1 } from '@base-ui/react/tooltip';
3
+
4
+ declare function TooltipProvider({ delay, ...props }: Tooltip$1.Provider.Props): React.JSX.Element;
5
+ declare function Tooltip({ ...props }: Tooltip$1.Root.Props): React.JSX.Element;
6
+ declare function TooltipTrigger({ ...props }: Tooltip$1.Trigger.Props): React.JSX.Element;
7
+ declare function TooltipContent({ className, side, sideOffset, align, alignOffset, children, ...props }: Tooltip$1.Popup.Props & Pick<Tooltip$1.Positioner.Props, 'side' | 'sideOffset' | 'align' | 'alignOffset'>): React.JSX.Element;
8
+
9
+ export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
@@ -0,0 +1,74 @@
1
+ 'use client';
2
+
3
+ // ../ui/src/shadcn/tooltip.tsx
4
+ import { Tooltip as TooltipPrimitive } from "@base-ui/react/tooltip";
5
+
6
+ // ../ui/src/lib/utils/cn.ts
7
+ import { clsx } from "clsx";
8
+ import { twMerge } from "tailwind-merge";
9
+ function cn(...inputs) {
10
+ return twMerge(clsx(inputs));
11
+ }
12
+
13
+ // ../ui/src/shadcn/tooltip.tsx
14
+ import { jsx, jsxs } from "react/jsx-runtime";
15
+ function TooltipProvider({
16
+ delay = 0,
17
+ ...props
18
+ }) {
19
+ return /* @__PURE__ */ jsx(
20
+ TooltipPrimitive.Provider,
21
+ {
22
+ "data-slot": "tooltip-provider",
23
+ delay,
24
+ ...props
25
+ }
26
+ );
27
+ }
28
+ function Tooltip({ ...props }) {
29
+ return /* @__PURE__ */ jsx(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props });
30
+ }
31
+ function TooltipTrigger({ ...props }) {
32
+ return /* @__PURE__ */ jsx(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
33
+ }
34
+ function TooltipContent({
35
+ className,
36
+ side = "top",
37
+ sideOffset = 4,
38
+ align = "center",
39
+ alignOffset = 0,
40
+ children,
41
+ ...props
42
+ }) {
43
+ return /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(
44
+ TooltipPrimitive.Positioner,
45
+ {
46
+ side,
47
+ sideOffset,
48
+ align,
49
+ alignOffset,
50
+ className: "isolate z-50",
51
+ children: /* @__PURE__ */ jsxs(
52
+ TooltipPrimitive.Popup,
53
+ {
54
+ "data-slot": "tooltip-content",
55
+ className: cn(
56
+ "bg-foreground text-background z-50 w-fit origin-(--transform-origin) rounded-md px-3 py-1.5 text-xs text-balance transition-[translate,scale,opacity] data-ending-style:scale-95 data-ending-style:opacity-0 data-starting-style:scale-95 data-starting-style:opacity-0 data-[side=bottom]:data-starting-style:-translate-y-2 data-[side=left]:data-starting-style:translate-x-2 data-[side=right]:data-starting-style:-translate-x-2 data-[side=top]:data-starting-style:translate-y-2",
57
+ className
58
+ ),
59
+ ...props,
60
+ children: [
61
+ children,
62
+ /* @__PURE__ */ jsx(TooltipPrimitive.Arrow, { className: "bg-foreground fill-foreground z-50 size-2.5 rotate-45 rounded-[2px] data-[side=bottom]:-top-1 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-1" })
63
+ ]
64
+ }
65
+ )
66
+ }
67
+ ) });
68
+ }
69
+ export {
70
+ Tooltip,
71
+ TooltipContent,
72
+ TooltipProvider,
73
+ TooltipTrigger
74
+ };
@@ -0,0 +1,39 @@
1
+ import * as React from 'react';
2
+ import { ComponentProps } from 'react';
3
+ import { Trans as Trans$1 } from 'react-i18next/TransWithoutContext';
4
+
5
+ /**
6
+ * Props accepted by {@link Trans}.
7
+ *
8
+ * Derived from react-i18next's own component rather than hand-listed, so the
9
+ * full translation surface (`i18nKey`, `defaults`, `values`, `components`,
10
+ * `ns`, `count`, `tOptions`, an explicit `i18n` instance, …) stays available
11
+ * and stays in step with the library across upgrades.
12
+ */
13
+ type TransProps = ComponentProps<typeof Trans$1>;
14
+ /**
15
+ * Translated text.
16
+ *
17
+ * Built on `react-i18next/TransWithoutContext` — the context-free entry point —
18
+ * rather than the default `react-i18next` export. The default export resolves
19
+ * its instance through `useTranslation()`, and a hook would make this module a
20
+ * client module; the context-free component reads the instance registered
21
+ * globally via `initReactI18next` instead, which keeps this subpath renderable
22
+ * from a React Server Component.
23
+ *
24
+ * ## Behaviour with no i18next instance
25
+ *
26
+ * Verified against react-i18next 16.5.4: when no instance is passed via the
27
+ * `i18n` prop and none has been registered globally, the component logs a
28
+ * one-time `NO_I18NEXT_INSTANCE` console warning and returns its children
29
+ * unmodified. It does not throw.
30
+ *
31
+ * Note the sharp edge this implies: the fallback is **children**, not
32
+ * `defaults`. `<Trans i18nKey="a.b" defaults="Continue" />` has no children, so
33
+ * with no instance available it renders nothing at all. Supply children when a
34
+ * string must survive an unconfigured host:
35
+ * `<Trans i18nKey="a.b" defaults="Continue">Continue</Trans>`.
36
+ */
37
+ declare function Trans(props: TransProps): React.JSX.Element;
38
+
39
+ export { Trans, type TransProps };
package/dist/trans.js ADDED
@@ -0,0 +1,9 @@
1
+ // src/_impl/trans.tsx
2
+ import { Trans as I18nTrans } from "react-i18next/TransWithoutContext";
3
+ import { jsx } from "react/jsx-runtime";
4
+ function Trans(props) {
5
+ return /* @__PURE__ */ jsx(I18nTrans, { ...props });
6
+ }
7
+ export {
8
+ Trans
9
+ };
@@ -0,0 +1,23 @@
1
+ import { ClassValue } from 'clsx';
2
+
3
+ declare function cn(...inputs: ClassValue[]): string;
4
+
5
+ /**
6
+ * @name isRouteActive
7
+ * @description A function to check if a route is active. This is used to
8
+ * @param end
9
+ * @param path
10
+ * @param currentPath
11
+ */
12
+ declare function isRouteActive(path: string, currentPath: string, end?: boolean | ((path: string) => boolean)): boolean;
13
+ /**
14
+ * @name checkIfRouteIsActive
15
+ * @description A function to check if a route is active. This is used to
16
+ * highlight the active link in the navigation.
17
+ * @param targetLink - The link to check against
18
+ * @param currentRoute - the current route
19
+ * @param depth - how far down should segments be matched?
20
+ */
21
+ declare function checkIfRouteIsActive(targetLink: string, currentRoute: string, depth?: number): boolean;
22
+
23
+ export { checkIfRouteIsActive, cn, isRouteActive };
package/dist/utils.js ADDED
@@ -0,0 +1,83 @@
1
+ // ../ui/src/lib/utils/cn.ts
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ function cn(...inputs) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+
8
+ // ../ui/src/lib/utils/is-route-active.ts
9
+ var ROOT_PATH = "/";
10
+ function isRouteActive(path, currentPath, end) {
11
+ if (path === currentPath) {
12
+ return true;
13
+ }
14
+ if (typeof end === "function") {
15
+ return !end(currentPath);
16
+ }
17
+ const defaultEnd = end ?? true;
18
+ const oneLevelDeep = 1;
19
+ const threeLevelsDeep = 3;
20
+ const depth = defaultEnd ? oneLevelDeep : threeLevelsDeep;
21
+ return checkIfRouteIsActive(path, currentPath, depth);
22
+ }
23
+ function checkIfRouteIsActive(targetLink, currentRoute, depth = 1) {
24
+ const [targetPath, targetQuery] = targetLink.split("?");
25
+ const [currentPath, currentQuery] = currentRoute.split("?");
26
+ if (targetQuery) {
27
+ const targetParams = new URLSearchParams(targetQuery);
28
+ const currentParams = new URLSearchParams(currentQuery || "");
29
+ let allMatch = true;
30
+ for (const [key, value] of targetParams.entries()) {
31
+ if (currentParams.get(key) !== value) {
32
+ allMatch = false;
33
+ break;
34
+ }
35
+ }
36
+ if (!allMatch) {
37
+ return false;
38
+ }
39
+ }
40
+ const currentRoutePath = currentPath ?? "";
41
+ const targetLinkPath = targetPath ?? "";
42
+ if (!isRoot(currentRoutePath) && isRoot(targetLinkPath)) {
43
+ return false;
44
+ }
45
+ if (!currentRoutePath.includes(targetLinkPath)) {
46
+ return false;
47
+ }
48
+ const isSameRoute = targetLinkPath === currentRoutePath;
49
+ if (isSameRoute) {
50
+ return true;
51
+ }
52
+ return hasMatchingSegments(targetLinkPath, currentRoutePath, depth);
53
+ }
54
+ function splitIntoSegments(href) {
55
+ return href.split("/").filter(Boolean);
56
+ }
57
+ function hasMatchingSegments(targetLink, currentRoute, depth) {
58
+ const segments = splitIntoSegments(targetLink);
59
+ const matchingSegments = numberOfMatchingSegments(currentRoute, segments);
60
+ if (targetLink === currentRoute) {
61
+ return true;
62
+ }
63
+ return matchingSegments > segments.length - (depth - 1);
64
+ }
65
+ function numberOfMatchingSegments(href, segments) {
66
+ let count = 0;
67
+ for (const segment of splitIntoSegments(href)) {
68
+ if (segments.includes(segment)) {
69
+ count += 1;
70
+ } else {
71
+ return count;
72
+ }
73
+ }
74
+ return count;
75
+ }
76
+ function isRoot(path) {
77
+ return path === ROOT_PATH;
78
+ }
79
+ export {
80
+ checkIfRouteIsActive,
81
+ cn,
82
+ isRouteActive
83
+ };
package/package.json ADDED
@@ -0,0 +1,150 @@
1
+ {
2
+ "name": "@ekanos/ui",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Fusion-styled UI primitives for building Ekanos integrations outside the monorepo. A curated, published slice of the internal @kit/ui library.",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/companydotcom/fusion.git",
10
+ "directory": "packages/ekanos-ui"
11
+ },
12
+ "homepage": "https://github.com/companydotcom/fusion/tree/dev/packages/ekanos-ui#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/companydotcom/fusion/issues"
15
+ },
16
+ "sideEffects": false,
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "exports": {
23
+ "./alert": {
24
+ "types": "./dist/alert.d.ts",
25
+ "default": "./dist/alert.js"
26
+ },
27
+ "./button": {
28
+ "types": "./dist/button.d.ts",
29
+ "default": "./dist/button.js"
30
+ },
31
+ "./dialog": {
32
+ "types": "./dist/dialog.d.ts",
33
+ "default": "./dist/dialog.js"
34
+ },
35
+ "./separator": {
36
+ "types": "./dist/separator.d.ts",
37
+ "default": "./dist/separator.js"
38
+ },
39
+ "./card": {
40
+ "types": "./dist/card.d.ts",
41
+ "default": "./dist/card.js"
42
+ },
43
+ "./badge": {
44
+ "types": "./dist/badge.d.ts",
45
+ "default": "./dist/badge.js"
46
+ },
47
+ "./tooltip": {
48
+ "types": "./dist/tooltip.d.ts",
49
+ "default": "./dist/tooltip.js"
50
+ },
51
+ "./select": {
52
+ "types": "./dist/select.d.ts",
53
+ "default": "./dist/select.js"
54
+ },
55
+ "./form": {
56
+ "types": "./dist/form.d.ts",
57
+ "default": "./dist/form.js"
58
+ },
59
+ "./input": {
60
+ "types": "./dist/input.d.ts",
61
+ "default": "./dist/input.js"
62
+ },
63
+ "./dropdown-menu": {
64
+ "types": "./dist/dropdown-menu.d.ts",
65
+ "default": "./dist/dropdown-menu.js"
66
+ },
67
+ "./label": {
68
+ "types": "./dist/label.d.ts",
69
+ "default": "./dist/label.js"
70
+ },
71
+ "./skeleton": {
72
+ "types": "./dist/skeleton.d.ts",
73
+ "default": "./dist/skeleton.js"
74
+ },
75
+ "./icon": {
76
+ "types": "./dist/icon.d.ts",
77
+ "default": "./dist/icon.js"
78
+ },
79
+ "./utils": {
80
+ "types": "./dist/utils.d.ts",
81
+ "default": "./dist/utils.js"
82
+ },
83
+ "./if": {
84
+ "types": "./dist/if.d.ts",
85
+ "default": "./dist/if.js"
86
+ },
87
+ "./trans": {
88
+ "types": "./dist/trans.d.ts",
89
+ "default": "./dist/trans.js"
90
+ },
91
+ "./spinner": {
92
+ "types": "./dist/spinner.d.ts",
93
+ "default": "./dist/spinner.js"
94
+ },
95
+ "./ai-prompt-input": {
96
+ "types": "./dist/ai-prompt-input.d.ts",
97
+ "default": "./dist/ai-prompt-input.js"
98
+ }
99
+ },
100
+ "publishConfig": {
101
+ "access": "public"
102
+ },
103
+ "dependencies": {
104
+ "@base-ui/react": "1.6.0",
105
+ "ai": "^6.0.197",
106
+ "class-variance-authority": "^0.7.1",
107
+ "clsx": "^2.1.1",
108
+ "cmdk": "1.1.1",
109
+ "i18next": "25.7.2",
110
+ "nanoid": "^5.1.11",
111
+ "react-i18next": "^16.5.0",
112
+ "tailwind-merge": "^3.4.0"
113
+ },
114
+ "peerDependencies": {
115
+ "@hookform/resolvers": "^5.2.2",
116
+ "react": "^19.2.8",
117
+ "react-dom": "^19.2.8",
118
+ "react-hook-form": "^7.68.0"
119
+ },
120
+ "devDependencies": {
121
+ "@hookform/resolvers": "^5.2.2",
122
+ "@types/react": "19.2.18",
123
+ "@types/react-dom": "19.2.4",
124
+ "react": "19.2.8",
125
+ "react-dom": "19.2.8",
126
+ "react-hook-form": "^7.68.0",
127
+ "tsup": "8.5.1",
128
+ "typescript": "^5.9.3",
129
+ "@kit/eslint-config": "0.2.0",
130
+ "@kit/ui": "0.1.0",
131
+ "@kit/prettier-config": "0.1.0",
132
+ "@kit/tsconfig": "0.1.0"
133
+ },
134
+ "prettier": "@kit/prettier-config",
135
+ "typesVersions": {
136
+ "*": {
137
+ "*": [
138
+ "dist/*"
139
+ ]
140
+ }
141
+ },
142
+ "scripts": {
143
+ "build": "tsup",
144
+ "clean": "git clean -xdf .turbo node_modules dist",
145
+ "format": "prettier --check \"**/*.{ts,tsx,mjs}\"",
146
+ "lint": "eslint .",
147
+ "typecheck": "tsc --noEmit",
148
+ "pack:test": "node scripts/pack-test.mjs"
149
+ }
150
+ }