moduix 0.7.0 → 0.8.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 CHANGED
@@ -1,18 +1,53 @@
1
+ ![moduix banner](https://raw.githubusercontent.com/Blinks44/moduix/main/apps/docs/public/banner.png)
2
+
3
+ [![npm](https://img.shields.io/npm/v/moduix?logo=npm&label=npm)](https://www.npmjs.com/package/moduix)
4
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
5
+ [![Turborepo](https://img.shields.io/badge/Monorepo-Turborepo-EF4444)](https://turbo.build/)
6
+
1
7
  # moduix
2
8
 
3
- Ready-made React components for product interfaces. The library is built on top of Base UI primitives and follows a composition-first API strongly inspired by shadcn/ui: you assemble small named parts, keep behavior accessible, and customize styles through props, `className`, and CSS variables. Styles are written in native CSS with CSS Modules, so the package ships framework-agnostic component CSS without requiring a utility CSS runtime.
9
+ Composable React components for product interfaces, built on top of
10
+ [Base UI](https://base-ui.com/) primitives.
11
+
12
+ moduix gives you ready-made components with accessible behavior, native CSS styles, and a
13
+ composition-first API. It is inspired by the clarity of
14
+ [shadcn/ui](https://ui.shadcn.com/), and it is trying to combine two useful workflows: install
15
+ components as a regular npm package when that fits your project, or copy component source when
16
+ you need direct ownership.
17
+
18
+ ## Why It Exists
19
+
20
+ moduix started as an internal tool for shared product UI. We needed a component library that
21
+ was practical enough for real application screens, predictable enough to use across teams, and
22
+ small enough to stay easy to understand.
23
+
24
+ The library is now public because it may be useful outside of the original company context. If
25
+ it helps another team build consistent interfaces faster, that is already a good outcome.
4
26
 
5
- ## Website
27
+ ## Principles
6
28
 
7
- The live documentation is temporarily available at https://moduix.blinks44.workers.dev/.
29
+ - **Base UI underneath.** Components are built on accessible Base UI primitives instead of
30
+ reimplementing low-level interaction behavior.
31
+ - **Small dependency surface.** Base UI is the only external UI primitive layer. The package
32
+ keeps the runtime stack intentionally small and does not bring a styling framework with it.
33
+ - **Two installation paths.** Use moduix as an npm package, or copy component source into your
34
+ project when direct ownership is more important than package-managed updates.
35
+ - **Composable API.** Components are exposed as named parts, so complex UI can be assembled
36
+ without hiding important structure.
37
+ - **Native CSS.** Styles are distributed as CSS, use CSS custom properties, and are designed to
38
+ work with your existing styling approach.
39
+ - **Not a shadcn/ui competitor.** shadcn/ui is a major inspiration for the developer experience.
40
+ moduix explores whether package-managed components and copy-owned components can coexist in
41
+ one library.
8
42
 
9
- ## Install
43
+ ## Installation
10
44
 
11
45
  ```bash
12
46
  npm install moduix @base-ui/react
13
47
  ```
14
48
 
15
- `react`, `react-dom`, and `@base-ui/react` are peer dependencies. They stay in your application bundle, so the library does not ship duplicate React or Base UI runtimes.
49
+ `react`, `react-dom`, and `@base-ui/react` are peer dependencies. They stay in your application
50
+ bundle, so moduix does not ship duplicate React or Base UI runtimes.
16
51
 
17
52
  ## Usage
18
53
 
@@ -22,7 +57,7 @@ Import the library styles once in your application entry point:
22
57
  import 'moduix/style.css';
23
58
  ```
24
59
 
25
- Then import the components you need:
60
+ Then import and compose the components you need:
26
61
 
27
62
  ```tsx
28
63
  import { Button, Dialog, DialogContent, DialogTitle, DialogTrigger } from 'moduix';
@@ -39,11 +74,13 @@ export function Example() {
39
74
  }
40
75
  ```
41
76
 
42
- The CSS file includes component styles and design tokens. It does not include global reset or application-level base styles, so those stay under the consuming project's control. If your bundler supports CSS imports from JavaScript, styles are also referenced by the library entry, but explicit `moduix/style.css` import is the most predictable setup for apps, SSR, and tests.
77
+ The distributed stylesheet includes component styles and design tokens. It does not force a
78
+ global application theme or utility CSS runtime.
43
79
 
44
80
  ## Styling
45
81
 
46
- Components expose stable `data-slot` attributes and accept `className` where customization is expected. Theme values are regular CSS custom properties:
82
+ Components accept `className` where customization is expected and expose stable `data-slot`
83
+ attributes for targeted styling. Theme values are regular CSS custom properties:
47
84
 
48
85
  ```css
49
86
  :root {
@@ -52,17 +89,37 @@ Components expose stable `data-slot` attributes and accept `className` where cus
52
89
  }
53
90
  ```
54
91
 
55
- The distributed stylesheet uses CSS cascade layers:
92
+ Library CSS is organized with cascade layers:
56
93
 
57
94
  ```css
58
95
  @layer ui.reset, ui.tokens, ui.components;
59
96
  ```
60
97
 
61
- This keeps library styles predictable while still letting application styles override tokens or component classes.
98
+ This keeps defaults predictable while still letting application styles override tokens,
99
+ classes, or component-level variables.
100
+
101
+ ## What Is Included
102
+
103
+ The package exports composed components for common product UI needs, including Accordion,
104
+ AlertDialog, Autocomplete, Avatar, Button, Checkbox, Dialog, Drawer, Field, Form, Input,
105
+ Menu, NavigationMenu, Popover, Select, Tabs, Toast, Tooltip, and supporting primitives.
106
+
107
+ ## Documentation
108
+
109
+ - Documentation: https://moduix.blinks44.workers.dev/
110
+ - npm package: https://www.npmjs.com/package/moduix
111
+ - UI package README: `packages/ui/README.md`
112
+ - Docs app README: `apps/docs/README.md`
113
+
114
+ ## Repository Quick Start
62
115
 
63
- ## What is included
116
+ From the monorepo root:
64
117
 
65
- The package exports composed components for common UI needs: Accordion, AlertDialog, Autocomplete, Avatar, Button, Checkbox, Dialog, Drawer, Field, Form, Input, Menu, NavigationMenu, Popover, Select, Tabs, Toast, Tooltip, and more. It also exports small shared primitives such as icons and close buttons.
118
+ ```bash
119
+ npm install
120
+ npm run build:ui
121
+ npm run dev
122
+ ```
66
123
 
67
124
  ## Acknowledgements
68
125
 
@@ -76,16 +133,36 @@ This project could not exist without the work of these teams and communities:
76
133
  - [TanStack](https://tanstack.com/) for the application tooling used by the docs.
77
134
  - [Voidzero](https://voidzero.dev/) for awesome JS tools
78
135
 
79
- ## Publishing Checklist
136
+ ## Contributing
80
137
 
81
- Before publishing a new version:
138
+ Contributions are welcome, especially bug reports, accessibility fixes, documentation
139
+ improvements, and focused component improvements.
82
140
 
83
- ```bash
84
- npm run fmt
85
- npm run lint
86
- npm run tsc:check
87
- npm run build -w packages/ui
88
- npm pack --dry-run -w packages/ui
89
- ```
141
+ Before opening a pull request:
142
+
143
+ 1. Install dependencies from the repository root:
144
+
145
+ ```bash
146
+ npm install
147
+ ```
148
+
149
+ 2. Build the UI package when your change affects `packages/ui` or documentation examples:
150
+
151
+ ```bash
152
+ npm run build:ui
153
+ ```
154
+
155
+ 3. Run the required checks:
156
+
157
+ ```bash
158
+ npm run fmt:fix
159
+ npm run lint:check
160
+ npm run tsc:check
161
+ ```
162
+
163
+ Keep pull requests small and specific. For component changes, update the related stories,
164
+ exports, and documentation so the package and docs stay in sync.
90
165
 
91
- Check that the tarball contains `dist/index.js`, `dist/index.cjs`, `dist/index.d.ts`, `dist/index.css`, `package.json`, and this README.
166
+ Feel free to use agents or code generation tools, but
167
+ please review the result before submitting. The components are intentionally small and direct,
168
+ so the goal is to keep the code readable, maintainable, and free from unnecessary abstractions.
@@ -0,0 +1,43 @@
1
+ import { Menu as MenuPrimitive } from '@base-ui/react/menu';
2
+ import * as React from 'react';
3
+ type BreadcrumbsItemRenderProps = Omit<React.ComponentProps<'a'>, 'children'> & {
4
+ children: React.ReactNode;
5
+ };
6
+ type BreadcrumbsItem = {
7
+ key?: React.Key;
8
+ label: React.ReactNode;
9
+ href?: string;
10
+ target?: React.ComponentProps<'a'>['target'];
11
+ rel?: React.ComponentProps<'a'>['rel'];
12
+ onClick?: React.ComponentProps<'a'>['onClick'];
13
+ render?: (props: BreadcrumbsItemRenderProps) => React.ReactElement;
14
+ };
15
+ type BreadcrumbsClassNames = {
16
+ ellipsisTrigger?: MenuPrimitive.Trigger.Props['className'];
17
+ popup?: MenuPrimitive.Popup.Props['className'];
18
+ popupItem?: MenuPrimitive.Item.Props['className'];
19
+ portal?: MenuPrimitive.Portal.Props['className'];
20
+ positioner?: MenuPrimitive.Positioner.Props['className'];
21
+ };
22
+ type BreadcrumbsSlotProps = {
23
+ ellipsisTrigger?: Omit<MenuPrimitive.Trigger.Props, 'children' | 'className'>;
24
+ popup?: Omit<MenuPrimitive.Popup.Props, 'children' | 'className'>;
25
+ popupItem?: Omit<MenuPrimitive.Item.Props, 'children' | 'className'>;
26
+ popupLinkItem?: Omit<MenuPrimitive.LinkItem.Props, 'children' | 'className' | 'href' | 'render'>;
27
+ portal?: Omit<MenuPrimitive.Portal.Props, 'children' | 'className'>;
28
+ positioner?: Omit<MenuPrimitive.Positioner.Props, 'children' | 'className'>;
29
+ };
30
+ type BreadcrumbsProps = Omit<React.ComponentProps<'nav'>, 'children'> & {
31
+ items: BreadcrumbsItem[];
32
+ separator?: React.ReactNode;
33
+ maxItems?: number;
34
+ itemsBeforeCollapse?: number;
35
+ itemsAfterCollapse?: number;
36
+ ellipsisLabel?: React.ReactNode;
37
+ hiddenItemsMenuLabel?: string;
38
+ classNames?: BreadcrumbsClassNames;
39
+ slotProps?: BreadcrumbsSlotProps;
40
+ };
41
+ declare function Breadcrumbs({ className, items, separator, maxItems, itemsBeforeCollapse, itemsAfterCollapse, ellipsisLabel, hiddenItemsMenuLabel, classNames, slotProps, ...props }: BreadcrumbsProps): import("react/jsx-runtime").JSX.Element;
42
+ export { Breadcrumbs };
43
+ export type { BreadcrumbsProps, BreadcrumbsItem, BreadcrumbsItemRenderProps, BreadcrumbsClassNames, BreadcrumbsSlotProps, };
@@ -0,0 +1,2 @@
1
+ export { Breadcrumbs } from './Breadcrumbs';
2
+ export type { BreadcrumbsProps, BreadcrumbsItem, BreadcrumbsItemRenderProps, BreadcrumbsClassNames, BreadcrumbsSlotProps, } from './Breadcrumbs';
@@ -0,0 +1,59 @@
1
+ import { Dialog as DialogPrimitive } from '@base-ui/react/dialog';
2
+ import * as React from 'react';
3
+ type LightboxContentClassNames = {
4
+ portal?: DialogPrimitive.Portal.Props['className'];
5
+ backdrop?: DialogPrimitive.Backdrop.Props['className'];
6
+ viewport?: DialogPrimitive.Viewport.Props['className'];
7
+ frame?: string;
8
+ };
9
+ type LightboxContentSlotProps = {
10
+ portal?: Omit<DialogPrimitive.Portal.Props, 'className' | 'children'>;
11
+ backdrop?: Omit<DialogPrimitive.Backdrop.Props, 'className'>;
12
+ viewport?: Omit<DialogPrimitive.Viewport.Props, 'className' | 'children'>;
13
+ };
14
+ type LightboxContentProps = Omit<DialogPrimitive.Popup.Props, 'className'> & {
15
+ className?: DialogPrimitive.Popup.Props['className'];
16
+ classNames?: LightboxContentClassNames;
17
+ slotProps?: LightboxContentSlotProps;
18
+ container?: DialogPrimitive.Portal.Props['container'];
19
+ withBackdrop?: boolean;
20
+ closeLabel?: string;
21
+ closeButton?: DialogPrimitive.Close.Props['render'];
22
+ withCloseButton?: boolean;
23
+ closeOnContentClick?: boolean;
24
+ };
25
+ type LightboxImageProps = Omit<React.ComponentProps<'img'>, 'src'> & {
26
+ src: string;
27
+ /**
28
+ * Controls image source used in popup. Defaults to `src`.
29
+ */
30
+ previewSrc?: string;
31
+ };
32
+ type LightboxGalleryProps = {
33
+ selector?: string;
34
+ rootRef?: React.RefObject<HTMLElement | null>;
35
+ rootSelector?: string;
36
+ withBackdrop?: boolean;
37
+ closeLabel?: string;
38
+ className?: DialogPrimitive.Popup.Props['className'];
39
+ classNames?: LightboxContentClassNames;
40
+ slotProps?: LightboxContentSlotProps;
41
+ container?: DialogPrimitive.Portal.Props['container'];
42
+ };
43
+ declare const Lightbox: typeof DialogPrimitive.Root;
44
+ declare const createLightboxHandle: typeof DialogPrimitive.createHandle;
45
+ declare function LightboxTrigger({ className, render, ...props }: DialogPrimitive.Trigger.Props): import("react/jsx-runtime").JSX.Element;
46
+ declare function LightboxPortal({ className, ...props }: DialogPrimitive.Portal.Props): import("react/jsx-runtime").JSX.Element;
47
+ declare function LightboxBackdrop({ className, ...props }: DialogPrimitive.Backdrop.Props): import("react/jsx-runtime").JSX.Element;
48
+ declare function LightboxViewport({ className, ...props }: DialogPrimitive.Viewport.Props): import("react/jsx-runtime").JSX.Element;
49
+ declare function LightboxPopup({ className, ...props }: DialogPrimitive.Popup.Props): import("react/jsx-runtime").JSX.Element;
50
+ declare function LightboxClose({ className, ...props }: DialogPrimitive.Close.Props): import("react/jsx-runtime").JSX.Element;
51
+ declare function LightboxImage({ src, previewSrc, alt, className, ...props }: LightboxImageProps): import("react/jsx-runtime").JSX.Element;
52
+ declare function LightboxContent({ className, classNames, slotProps, container, withBackdrop, withCloseButton, closeOnContentClick, closeLabel, closeButton, children, ...props }: LightboxContentProps): import("react/jsx-runtime").JSX.Element;
53
+ declare function LightboxGallery({ selector, rootRef, rootSelector, withBackdrop, closeLabel, className, classNames, slotProps, container, }: LightboxGalleryProps): import("react/jsx-runtime").JSX.Element;
54
+ type LightboxProps<Payload = unknown> = DialogPrimitive.Root.Props<Payload>;
55
+ type LightboxHandle<Payload = unknown> = DialogPrimitive.Handle<Payload>;
56
+ type LightboxTriggerProps = DialogPrimitive.Trigger.Props;
57
+ type LightboxCloseProps = DialogPrimitive.Close.Props;
58
+ export { Lightbox, createLightboxHandle, LightboxTrigger, LightboxPortal, LightboxBackdrop, LightboxViewport, LightboxPopup, LightboxContent, LightboxClose, LightboxImage, LightboxGallery, };
59
+ export type { LightboxProps, LightboxHandle, LightboxTriggerProps, LightboxContentProps, LightboxCloseProps, LightboxImageProps, LightboxGalleryProps, LightboxContentClassNames, LightboxContentSlotProps, };
@@ -0,0 +1 @@
1
+ export * from './Lightbox';
@@ -11,8 +11,15 @@ type ListProps = React.ComponentPropsWithoutRef<ListAs> & {
11
11
  size?: ListSize;
12
12
  tone?: ListTone;
13
13
  };
14
- type ListItemProps = React.ComponentProps<'li'>;
14
+ type ListItemClassNames = {
15
+ marker?: string;
16
+ content?: string;
17
+ };
18
+ type ListItemProps = React.ComponentProps<'li'> & {
19
+ marker?: React.ReactNode;
20
+ classNames?: ListItemClassNames;
21
+ };
15
22
  declare function List({ as, marker, gap, size, tone, className, ...props }: ListProps): import("react/jsx-runtime").JSX.Element;
16
- declare function ListItem({ className, ...props }: ListItemProps): import("react/jsx-runtime").JSX.Element;
23
+ declare function ListItem({ className, classNames, marker, children, ...props }: ListItemProps): import("react/jsx-runtime").JSX.Element;
17
24
  export { List, ListItem };
18
- export type { ListProps, ListItemProps, ListAs, ListMarker, ListGap, ListSize, ListTone };
25
+ export type { ListProps, ListItemProps, ListItemClassNames, ListAs, ListMarker, ListGap, ListSize, ListTone, };
@@ -0,0 +1,23 @@
1
+ import * as React from 'react';
2
+ type PaginationToolbarVariant = 'default' | 'outline' | 'ghost';
3
+ type PaginationToolbarSize = 'sm' | 'md' | 'lg';
4
+ type PaginationSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
5
+ type PaginationProps = Omit<React.ComponentProps<'nav'>, 'onChange'> & {
6
+ count: number;
7
+ page?: number;
8
+ defaultPage?: number;
9
+ onPageChange?: (page: number) => void;
10
+ visiblePages?: number;
11
+ showPages?: boolean;
12
+ showArrows?: boolean;
13
+ disabled?: boolean;
14
+ getPageHref?: (page: number) => string;
15
+ size?: PaginationSize;
16
+ toolbarVariant?: PaginationToolbarVariant;
17
+ toolbarSize?: PaginationToolbarSize;
18
+ previousLabel?: string;
19
+ nextLabel?: string;
20
+ };
21
+ declare function Pagination({ className, count, page, defaultPage, onPageChange, visiblePages, showPages, showArrows, disabled, getPageHref, size, toolbarVariant, toolbarSize, previousLabel, nextLabel, ...props }: PaginationProps): import("react/jsx-runtime").JSX.Element;
22
+ export { Pagination };
23
+ export type { PaginationProps, PaginationToolbarVariant, PaginationToolbarSize, PaginationSize };
@@ -0,0 +1,2 @@
1
+ export { Pagination } from './Pagination';
2
+ export type { PaginationProps, PaginationSize, PaginationToolbarVariant, PaginationToolbarSize, } from './Pagination';