@electroplix/components 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @electroplix/components
2
2
 
3
- > Parametric, config-driven React UI components. **~154 components** across **18 categories** — zero external CSS, zero icon dependencies, fully themeable via a single provider.
3
+ > Parametric, config-driven React UI components. **153 components** across **18 categories** — zero external CSS, zero icon dependencies, fully themeable via a single provider.
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/@electroplix/components)](https://www.npmjs.com/package/@electroplix/components)
6
6
 
@@ -36,27 +36,42 @@ yarn add @electroplix/components
36
36
 
37
37
  ## Quick Start
38
38
 
39
- ### 1. Wrap your app with the provider
39
+ ### 1. Scaffold your project
40
+
41
+ ```bash
42
+ npx @electroplix/components init
43
+ ```
44
+
45
+ This creates two files:
46
+
47
+ - **`electroplix.config.ts`** — your global theme configuration
48
+ - **`components/providers.tsx`** — a `"use client"` wrapper for the provider
49
+
50
+ ### 2. Update your layout
51
+
52
+ Your root layout stays as a **Server Component** — import the client-side `Providers` wrapper:
40
53
 
41
54
  ```tsx
42
- // app/layout.tsx (Next.js App Router)
43
- import { ElectroplixProvider } from "@electroplix/components";
44
- import config from "./electroplix.config";
55
+ // app/layout.tsx — Server Component (no "use client" needed here)
56
+ import { Providers } from "../components/providers";
45
57
 
46
58
  export default function RootLayout({ children }: { children: React.ReactNode }) {
47
59
  return (
48
60
  <html>
49
61
  <body>
50
- <ElectroplixProvider config={config}>
51
- {children}
52
- </ElectroplixProvider>
62
+ <Providers>{children}</Providers>
53
63
  </body>
54
64
  </html>
55
65
  );
56
66
  }
57
67
  ```
58
68
 
59
- ### 2. Use components anywhere
69
+ > **Why a separate `providers.tsx`?**
70
+ > `ElectroplixProvider` uses React Context (`createContext`), which only works in Client Components.
71
+ > By isolating it in a `"use client"` file, your layout stays a Server Component so metadata,
72
+ > static content, and other server-only features continue to work.
73
+
74
+ ### 3. Use components in client pages
60
75
 
61
76
  ```tsx
62
77
  "use client";
@@ -64,8 +79,6 @@ import {
64
79
  PrimaryNav,
65
80
  StaticHero,
66
81
  PrimaryButton,
67
- ContactForm,
68
- BlogCard,
69
82
  } from "@electroplix/components";
70
83
 
71
84
  export default function HomePage() {
@@ -83,36 +96,34 @@ export default function HomePage() {
83
96
 
84
97
  ## Configuration
85
98
 
86
- Create an `electroplix.config.ts` file using the server-safe `./config` entry:
99
+ The `electroplix.config.ts` file uses the server-safe `./config` entry point (no React, no `"use client"`):
87
100
 
88
101
  ```ts
89
102
  // electroplix.config.ts
90
103
  import { defineConfig } from "@electroplix/components/config";
91
104
 
92
- export default defineConfig({
93
- navigation: {
94
- bgColor: "#1a1a2e",
95
- accentColor: "#e94560",
96
- sticky: true,
97
- height: 64,
98
- },
99
- buttons: {
100
- bgColor: "#e94560",
101
- textColor: "#ffffff",
102
- radius: 12,
103
- },
104
- hero: {
105
- bgColor: "#16213e",
106
- minH: 600,
107
- },
108
- forms: {
109
- inputBg: "rgba(255,255,255,0.05)",
110
- radius: 8,
111
- },
112
- // ... configure any of the 18 categories
105
+ const config = defineConfig({
106
+ // ── Global overrides (applied to ALL categories) ──────────
107
+ accentColor: "#7C3AED",
108
+ textColor: "#E5E7EB",
109
+ bgColor: "#0b0b0c",
110
+ borderColor: "rgba(255,255,255,0.14)",
111
+ radius: 14,
112
+ fontFamily: "Inter, system-ui, sans-serif",
113
+
114
+ // ── Per-category overrides ────────────────────────────────
115
+ navigation: { sticky: true, height: 64 },
116
+ hero: { minH: 600 },
117
+ buttons: { bgColor: "#e94560", radius: 12 },
118
+ forms: { inputBg: "rgba(255,255,255,0.05)" },
119
+ ecommerce: { accentColor: "#10B981" },
113
120
  });
121
+
122
+ export default config;
114
123
  ```
115
124
 
125
+ **How merging works:** Global `BaseTheme` props (like `accentColor`, `bgColor`) are spread into every category as a baseline. Per-category overrides take priority. Built-in defaults fill any gaps.
126
+
116
127
  ### Available config keys
117
128
 
118
129
  | Key | Theme Type | Category |
@@ -136,7 +147,7 @@ export default defineConfig({
136
147
  | `social` | `SocialTheme` | Social sharing, login |
137
148
  | `userAccounts` | `UserAccountsTheme` | Auth forms, profile |
138
149
 
139
- Every theme extends `BaseTheme` which provides: `bgColor`, `textColor`, `accentColor`, `borderColor`, `fontFamily`, `radius`, `spacing`, `headingSize`, `bodySize`, `fontWeight`, `lineHeight`, `letterSpacing`, `shadow`.
150
+ **Global BaseTheme props** (set at root level): `bgColor`, `textColor`, `accentColor`, `borderColor`, `fontFamily`, `radius`, `spacing`, `headingSize`, `bodySize`, `fontWeight`, `lineHeight`, `letterSpacing`, `shadow`.
140
151
 
141
152
  ---
142
153
 
@@ -185,17 +196,6 @@ Every theme extends `BaseTheme` which provides: `bgColor`, `textColor`, `accentC
185
196
  | `SplitHero` | `title`, `image`, `features`, `reverse` | Side-by-side hero |
186
197
  | `VideoHeaderHero` | `videoSrc`, `poster`, `title` | Full-width video hero |
187
198
 
188
- ```tsx
189
- <StaticHero
190
- title="Build Incredible Products"
191
- subtitle="Ship faster with pre-built components."
192
- ctaLabel="Get Started Free"
193
- onCta={() => router.push("/signup")}
194
- titleSize={48}
195
- align="center"
196
- />
197
- ```
198
-
199
199
  ### Buttons (10)
200
200
 
201
201
  | Component | Key Props | Description |
@@ -211,25 +211,6 @@ Every theme extends `BaseTheme` which provides: `bgColor`, `textColor`, `accentC
211
211
  | `DownloadButton` | `fileUrl`, `label` | File download button |
212
212
  | `PrintButton` | `label` | Print page button |
213
213
 
214
- ```tsx
215
- <PrimaryButton
216
- label="Add to Cart"
217
- icon="shopping-cart"
218
- onClick={handleAddToCart}
219
- bgColor="#7C3AED"
220
- radius={12}
221
- />
222
-
223
- <ButtonGroup
224
- buttons={[
225
- { label: "Monthly", value: "monthly" },
226
- { label: "Yearly", value: "yearly" },
227
- ]}
228
- toggle
229
- onChange={(v) => setBilling(v)}
230
- />
231
- ```
232
-
233
214
  ### Forms (14)
234
215
 
235
216
  | Component | Key Props | Description |
@@ -249,27 +230,6 @@ Every theme extends `BaseTheme` which provides: `bgColor`, `textColor`, `accentC
249
230
  | `AddressAutocomplete` | `suggestions`, `onQuery`, `onSelect` | Address autocomplete |
250
231
  | `ValidationWrapper` | `errors`, `children`, `success` | Error/success message wrapper |
251
232
 
252
- ```tsx
253
- <InputField
254
- label="Email"
255
- name="email"
256
- type="email"
257
- value={email}
258
- onChange={(e) => setEmail(e.target.value)}
259
- error={errors.email}
260
- icon="mail"
261
- />
262
-
263
- <MultiStepWizard
264
- steps={[
265
- { label: "Personal", content: <PersonalStep /> },
266
- { label: "Payment", content: <PaymentStep /> },
267
- { label: "Confirm", content: <ConfirmStep /> },
268
- ]}
269
- onFinish={handleSubmit}
270
- />
271
- ```
272
-
273
233
  ### Content (6)
274
234
 
275
235
  | Component | Key Props | Description |
@@ -297,26 +257,6 @@ Every theme extends `BaseTheme` which provides: `bgColor`, `textColor`, `accentC
297
257
  | `CalendarGrid` | `year`, `month`, `marks`, `onDateClick` | Month calendar grid |
298
258
  | `Timeline` | `items` | Vertical timeline |
299
259
 
300
- ```tsx
301
- <BarChart
302
- data={[120, 280, 150, 350, 210]}
303
- labels={["Mon", "Tue", "Wed", "Thu", "Fri"]}
304
- title="Weekly Sales"
305
- showGrid
306
- />
307
-
308
- <DataTable
309
- columns={[
310
- { key: "name", label: "Name" },
311
- { key: "email", label: "Email" },
312
- { key: "role", label: "Role" },
313
- ]}
314
- rows={users}
315
- pageSize={10}
316
- searchable
317
- />
318
- ```
319
-
320
260
  ### Ecommerce (10)
321
261
 
322
262
  | Component | Key Props | Description |
@@ -332,14 +272,6 @@ Every theme extends `BaseTheme` which provides: `bgColor`, `textColor`, `accentC
332
272
  | `WishlistButton` | `productId`, `wishlisted`, `onToggle` | Heart wishlist toggle |
333
273
  | `PaymentButtons` | `methods`, `onPay` | Payment method buttons |
334
274
 
335
- ```tsx
336
- <ProductCard
337
- product={{ id: "1", name: "T-Shirt", price: 29.99, image: "/tshirt.jpg" }}
338
- currency="USD"
339
- onAddToCart={(p) => addToCart(p)}
340
- />
341
- ```
342
-
343
275
  ### Lists & Cards (8)
344
276
 
345
277
  | Component | Key Props | Description |
@@ -484,7 +416,7 @@ Every theme extends `BaseTheme` which provides: `bgColor`, `textColor`, `accentC
484
416
 
485
417
  ## Icon System
486
418
 
487
- The package includes **113+ inline SVG icons** — zero external dependencies. Use the `Icon` component:
419
+ The package includes **113+ inline SVG icons** — zero external dependencies:
488
420
 
489
421
  ```tsx
490
422
  import { Icon, ICON_NAMES } from "@electroplix/components";
@@ -500,19 +432,22 @@ All available icon names: `activity`, `alert-circle`, `alert-triangle`, `align-l
500
432
 
501
433
  ## CLI
502
434
 
503
- The package includes a CLI for scaffolding:
504
-
505
435
  ```bash
506
- # Initialize config file
507
- npx electroplix-components init
436
+ # Scaffold config + providers
437
+ npx @electroplix/components init
438
+
439
+ # Show all components in a category
440
+ npx @electroplix/components add navigation
508
441
 
509
- # Add a component category to your project
510
- npx electroplix-components add navigation
442
+ # Show import instructions for a single component
443
+ npx @electroplix/components add PrimaryNav
511
444
 
512
- # List all available components
513
- npx electroplix-components list
445
+ # Browse all 153 components with tree view
446
+ npx @electroplix/components list
514
447
  ```
515
448
 
449
+ The `add` command accepts both **component names** (`PrimaryNav`, `BlogCard`) and **category names** (`navigation`, `data-display`, `social`).
450
+
516
451
  ---
517
452
 
518
453
  ## Utilities
@@ -549,12 +484,10 @@ Exported utility functions and hooks:
549
484
  </ElectroplixProvider>
550
485
  ```
551
486
 
552
- - **`config`** — `Partial<ElectroplixConfig> | undefined` — optional theme overrides for any/all categories. Falls back to `defaultConfig` for unset values.
487
+ - **`config`** — `Partial<ElectroplixConfig> | undefined` — optional theme overrides. Supports both root-level `BaseTheme` props (global) and per-category objects.
553
488
 
554
489
  ### Category hooks
555
490
 
556
- Each component internally calls its category hook. You can also use them directly:
557
-
558
491
  ```tsx
559
492
  import { useButtonTheme, useNavTheme } from "@electroplix/components";
560
493
 
@@ -566,7 +499,7 @@ function MyCustomButton() {
566
499
 
567
500
  ### `defineConfig(config)`
568
501
 
569
- Type-safe config authoring helper. Returns the config as-is.
502
+ Server-safe type-checked config helper. Import from `@electroplix/components/config`.
570
503
 
571
504
  ### `mergeTheme(target, ...sources)`
572
505
 
@@ -581,9 +514,3 @@ pnpm nx test @electroplix/components
581
514
  ```
582
515
 
583
516
  19 test suites, 163 tests covering all 18 categories.
584
-
585
- ---
586
-
587
- ## License
588
-
589
- MIT
package/cli.cjs CHANGED
@@ -4,15 +4,79 @@
4
4
  * @electroplix/components CLI
5
5
  *
6
6
  * Usage:
7
- * npx @electroplix/components init – scaffold electroplix.config.ts
8
- * npx @electroplix/components add <name> – show install/import instructions
9
- * npx @electroplix/components list – list all available components
7
+ * npx @electroplix/components init – scaffold config + providers
8
+ * npx @electroplix/components add <name|category> – show install/import instructions
9
+ * npx @electroplix/components list – list all available components
10
10
  */
11
11
 
12
12
  const fs = require("fs");
13
13
  const path = require("path");
14
14
 
15
- /* ── component registry ─────────────────────────────────── */
15
+ /* ══════════════════════════════════════════════════════════════════ */
16
+ /* ANSI Styling */
17
+ /* ══════════════════════════════════════════════════════════════════ */
18
+
19
+ const ESC = "\x1b[";
20
+ const R = `${ESC}0m`;
21
+
22
+ const s = {
23
+ bold: (t) => `${ESC}1m${t}${R}`,
24
+ dim: (t) => `${ESC}2m${t}${R}`,
25
+ italic: (t) => `${ESC}3m${t}${R}`,
26
+ purple: (t) => `${ESC}38;2;139;92;246m${t}${R}`,
27
+ violet: (t) => `${ESC}38;2;167;139;250m${t}${R}`,
28
+ cyan: (t) => `${ESC}38;2;34;211;238m${t}${R}`,
29
+ green: (t) => `${ESC}38;2;52;211;153m${t}${R}`,
30
+ yellow: (t) => `${ESC}38;2;251;191;36m${t}${R}`,
31
+ red: (t) => `${ESC}38;2;251;113;133m${t}${R}`,
32
+ white: (t) => `${ESC}38;2;243;244;246m${t}${R}`,
33
+ gray: (t) => `${ESC}38;2;107;114;128m${t}${R}`,
34
+ };
35
+
36
+ /* ══════════════════════════════════════════════════════════════════ */
37
+ /* Box-drawing helpers */
38
+ /* ══════════════════════════════════════════════════════════════════ */
39
+
40
+ const B = {
41
+ tl: "\u256D", tr: "\u256E", bl: "\u2570", br: "\u256F",
42
+ h: "\u2500", v: "\u2502",
43
+ tee: "\u251C", end: "\u2570",
44
+ branch: "\u251C\u2500\u2500", last: "\u2570\u2500\u2500",
45
+ pipe: "\u2502 ",
46
+ dot: "\u25CF", arrow: "\u2192", check: "\u2713", star: "\u2605",
47
+ diamond: "\u25C6", spark: "\u26A1",
48
+ };
49
+
50
+ function hr(w) { return B.h.repeat(w); }
51
+
52
+ function stripAnsi(t) { return t.replace(/\x1b\[[0-9;]*m/g, ""); }
53
+
54
+ function boxLine(l, content, r, w) {
55
+ const vis = stripAnsi(content);
56
+ const pad = Math.max(0, w - vis.length - 2);
57
+ return ` ${l}${content}${" ".repeat(pad)}${r}`;
58
+ }
59
+
60
+ /* ══════════════════════════════════════════════════════════════════ */
61
+ /* Brand banner */
62
+ /* ══════════════════════════════════════════════════════════════════ */
63
+
64
+ function printBanner() {
65
+ const W = 58;
66
+ const lines = [
67
+ "",
68
+ ` ${B.tl}${hr(W)}${B.tr}`,
69
+ boxLine(B.v, ` ${s.bold(s.purple(`${B.spark} ELECTROPLIX`))} ${s.dim(s.violet("COMPONENTS"))}`, B.v, W),
70
+ boxLine(B.v, ` ${s.gray("Parametric \u2022 Config-Driven \u2022 Zero-Dependency")}`, B.v, W),
71
+ ` ${B.bl}${hr(W)}${B.br}`,
72
+ "",
73
+ ];
74
+ console.log(lines.join("\n"));
75
+ }
76
+
77
+ /* ══════════════════════════════════════════════════════════════════ */
78
+ /* Component registry */
79
+ /* ══════════════════════════════════════════════════════════════════ */
16
80
 
17
81
  const CATEGORIES = {
18
82
  navigation: [
@@ -32,6 +96,7 @@ const CATEGORIES = {
32
96
  "FormShell", "InputField", "TextAreaField", "SelectDropdown", "RadioGroup",
33
97
  "ToggleSwitch", "DateTimePicker", "FileUploader", "ContactForm",
34
98
  "NewsletterSignup", "MultiStepWizard", "Captcha", "AddressAutocomplete",
99
+ "ValidationWrapper",
35
100
  ],
36
101
  content: [
37
102
  "BlockquoteTestimonial", "CalloutBox", "HeadingSection",
@@ -93,100 +158,315 @@ const CATEGORIES = {
93
158
  ],
94
159
  };
95
160
 
161
+ /* build lookup maps */
96
162
  const ALL_COMPONENTS = new Map();
97
163
  for (const [cat, names] of Object.entries(CATEGORIES)) {
98
164
  for (const n of names) ALL_COMPONENTS.set(n.toLowerCase(), { name: n, category: cat });
99
165
  }
100
166
 
101
- /* ── colours ────────────────────────────────────────────── */
167
+ const CATEGORY_ALIASES = new Map();
168
+ for (const cat of Object.keys(CATEGORIES)) {
169
+ CATEGORY_ALIASES.set(cat.toLowerCase(), cat);
170
+ CATEGORY_ALIASES.set(cat.replace(/-/g, "").toLowerCase(), cat);
171
+ CATEGORY_ALIASES.set(cat.replace(/-/g, " ").toLowerCase(), cat);
172
+ }
102
173
 
103
- const PURPLE = "\x1b[35m";
104
- const GREEN = "\x1b[32m";
105
- const CYAN = "\x1b[36m";
106
- const DIM = "\x1b[2m";
107
- const BOLD = "\x1b[1m";
108
- const RESET = "\x1b[0m";
174
+ const totalCount = Object.values(CATEGORIES).reduce((sum, a) => sum + a.length, 0);
109
175
 
110
- /* ── commands ───────────────────────────────────────────── */
176
+ /* ══════════════════════════════════════════════════════════════════ */
177
+ /* Package manager detection */
178
+ /* ══════════════════════════════════════════════════════════════════ */
179
+
180
+ function detectPackageManager() {
181
+ const cwd = process.cwd();
182
+
183
+ // Check for lockfiles in order of preference
184
+ if (fs.existsSync(path.join(cwd, "bun.lock"))) {
185
+ return { manager: "bun", command: "bun install", displayName: "Bun" };
186
+ }
187
+ if (fs.existsSync(path.join(cwd, "pnpm-lock.yaml"))) {
188
+ return { manager: "pnpm", command: "pnpm install", displayName: "pnpm" };
189
+ }
190
+ if (fs.existsSync(path.join(cwd, "yarn.lock"))) {
191
+ return { manager: "yarn", command: "yarn install", displayName: "Yarn" };
192
+ }
193
+ if (fs.existsSync(path.join(cwd, "package-lock.json"))) {
194
+ return { manager: "npm", command: "npm install", displayName: "npm" };
195
+ }
196
+
197
+ // Default to npm if no lockfile found
198
+ return { manager: "npm", command: "npm install", displayName: "npm" };
199
+ }
200
+
201
+ /* ══════════════════════════════════════════════════════════════════ */
202
+ /* INIT command */
203
+ /* ══════════════════════════════════════════════════════════════════ */
111
204
 
112
205
  function init() {
206
+ printBanner();
207
+
113
208
  const configName = "electroplix.config.ts";
114
- const target = path.join(process.cwd(), configName);
209
+ const providerRel = path.join("components", "providers.tsx");
210
+ const configPath = path.join(process.cwd(), configName);
211
+ const providerDir = path.join(process.cwd(), "components");
212
+ const providerPath = path.join(providerDir, "providers.tsx");
115
213
 
116
- if (fs.existsSync(target)) {
117
- console.log(`${PURPLE}electroplix${RESET} ${configName} already exists.`);
118
- process.exit(0);
119
- }
214
+ const created = [];
215
+ const skipped = [];
120
216
 
121
- const template = `import { defineConfig } from "@electroplix/components/config";
217
+ /* ── config file ─────────────────────────────────────── */
218
+ if (fs.existsSync(configPath)) {
219
+ skipped.push(configName);
220
+ } else {
221
+ const configTemplate = `import { defineConfig } from "@electroplix/components";
122
222
 
123
- export default defineConfig({
124
- // Global theme overrides
223
+ const config = defineConfig({
224
+ // \u2500\u2500 Global overrides (applied to ALL categories) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
125
225
  accentColor: "#7C3AED",
126
226
  textColor: "#E5E7EB",
127
227
  bgColor: "#0b0b0c",
128
228
  borderColor: "rgba(255,255,255,0.14)",
129
229
  radius: 14,
130
- spacing: 14,
131
230
  fontFamily: "Inter, system-ui, sans-serif",
132
- headingSize: 18,
133
- bodySize: 14,
134
231
 
135
- // Optional: configure per-category themes
136
- // navigation: { accentColor: "#7C3AED" },
137
- // hero: { overlayOpacity: 0.55 },
138
- // ecommerce: { currency: "USD" },
232
+ // \u2500\u2500 Per-category overrides \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
233
+ // navigation: { sticky: true, height: 64 },
234
+ // hero: { minH: 600 },
235
+ // buttons: { bgColor: "#e94560", radius: 12 },
236
+ // forms: { inputBg: "rgba(255,255,255,0.05)" },
237
+ // ecommerce: { accentColor: "#10B981" },
139
238
  });
239
+
240
+ export default config;
140
241
  `;
242
+ fs.writeFileSync(configPath, configTemplate, "utf-8");
243
+ created.push(configName);
244
+ }
245
+
246
+ /* ── providers wrapper ───────────────────────────────── */
247
+ if (fs.existsSync(providerPath)) {
248
+ skipped.push(providerRel);
249
+ } else {
250
+ if (!fs.existsSync(providerDir)) {
251
+ fs.mkdirSync(providerDir, { recursive: true });
252
+ }
253
+ const providerTemplate = `"use client";
254
+
255
+ import { ElectroplixProvider } from "@electroplix/components";
256
+ import config from "../electroplix.config";
257
+
258
+ /**
259
+ * Client-side providers wrapper.
260
+ * Import this into your root layout (which stays as a Server Component).
261
+ */
262
+ export function Providers({ children }: { children: React.ReactNode }) {
263
+ return (
264
+ <ElectroplixProvider config={config}>
265
+ {children}
266
+ </ElectroplixProvider>
267
+ );
268
+ }
269
+ `;
270
+ fs.writeFileSync(providerPath, providerTemplate, "utf-8");
271
+ created.push(providerRel);
272
+ }
273
+
274
+ /* ── output ──────────────────────────────────────────── */
275
+ if (created.length) {
276
+ console.log(` ${s.green(B.check)} ${s.bold("Created:")}`);
277
+ for (const f of created) {
278
+ console.log(` ${s.green(B.arrow)} ${s.cyan(f)}`);
279
+ }
280
+ console.log();
281
+ }
282
+ if (skipped.length) {
283
+ console.log(` ${s.yellow("!")} ${s.bold("Already exists")} ${s.dim("(skipped):")}`);
284
+ for (const f of skipped) {
285
+ console.log(` ${s.gray(B.arrow)} ${s.gray(f)}`);
286
+ }
287
+ console.log();
288
+ }
289
+
290
+ console.log(` ${s.bold("Next steps:")}`);
291
+ console.log();
292
+ console.log(` ${s.white("1.")} Update your ${s.cyan("app/layout.tsx")}:`);
293
+ console.log();
294
+ console.log(` ${s.gray("import { Providers } from \"../components/providers\";")}`);
295
+ console.log();
296
+ console.log(` ${s.gray("export default function RootLayout({ children }) {")}`);
297
+ console.log(` ${s.gray(" return (")}`);
298
+ console.log(` ${s.gray(" <html><body>")}`);
299
+ console.log(` ${s.gray(" ")}${s.cyan("<Providers>")}${s.gray("{children}")}${s.cyan("</Providers>")}`);
300
+ console.log(` ${s.gray(" </body></html>")}`);
301
+ console.log(` ${s.gray(" );")}`);
302
+ console.log(` ${s.gray("}")}`);
303
+ console.log();
304
+ console.log(` ${s.white("2.")} Import components in ${s.cyan("\"use client\"")} pages:`);
305
+ console.log();
306
+ console.log(` ${s.gray("import { PrimaryNav, StaticHero } from \"@electroplix/components\";")}`);
307
+ console.log();
308
+ console.log();
141
309
 
142
- fs.writeFileSync(target, template, "utf-8");
143
- console.log(`\n${PURPLE}electroplix${RESET} Created ${GREEN}${configName}${RESET}\n`);
144
- console.log(`${DIM}Wrap your app with <ElectroplixProvider config={config}> to apply.${RESET}\n`);
310
+ /* ── install package ── */
311
+ const { execSync } = require("child_process");
312
+ const pmInfo = detectPackageManager();
313
+
314
+ console.log(` ${s.white("3.")} Installing ${s.cyan("@electroplix/components")} with ${s.cyan(pmInfo.displayName)}...`);
315
+ console.log();
316
+
317
+ try {
318
+ execSync(`${pmInfo.command} @electroplix/components`, { stdio: "inherit" });
319
+ console.log();
320
+ console.log(` ${s.green(B.check)} ${s.bold("Setup complete!")} You're ready to use Electroplix components.`);
321
+ console.log();
322
+ } catch (err) {
323
+ console.log();
324
+ console.log(` ${s.yellow("!")} ${s.bold("Manual install required:")}`);
325
+ console.log(` ${s.cyan(`${pmInfo.command} @electroplix/components`)}`);
326
+ console.log();
327
+ }
145
328
  }
146
329
 
330
+ /* ══════════════════════════════════════════════════════════════════ */
331
+ /* ADD command */
332
+ /* ══════════════════════════════════════════════════════════════════ */
333
+
147
334
  function add(name) {
335
+ printBanner();
336
+
148
337
  if (!name) {
149
- console.log(`\n${PURPLE}electroplix${RESET} Usage: ${CYAN}npx @electroplix/components add <ComponentName>${RESET}\n`);
338
+ console.log(` ${s.red("\u2717")} ${s.bold("Missing argument")}\n`);
339
+ console.log(` ${s.white("Usage:")}`);
340
+ console.log(` ${s.cyan("npx @electroplix/components add")} ${s.violet("<ComponentName>")}`);
341
+ console.log(` ${s.cyan("npx @electroplix/components add")} ${s.violet("<category>")}`);
342
+ console.log();
343
+ console.log(` ${s.dim("Examples:")}`);
344
+ console.log(` ${s.gray("npx @electroplix/components add PrimaryNav")}`);
345
+ console.log(` ${s.gray("npx @electroplix/components add navigation")}`);
346
+ console.log();
150
347
  process.exit(1);
151
348
  }
152
349
 
153
- const entry = ALL_COMPONENTS.get(name.toLowerCase());
350
+ const key = name.toLowerCase().replace(/\s+/g, "-");
351
+
352
+ /* ── try category match first ──────────────────────── */
353
+ const catMatch = CATEGORY_ALIASES.get(key);
354
+ if (catMatch) {
355
+ const comps = CATEGORIES[catMatch];
356
+ console.log(` ${s.purple(B.star)} ${s.bold(catMatch)} ${s.dim(`\u2014 ${comps.length} components`)}`);
357
+ console.log();
358
+ console.log(` ${s.white("Import all:")}`);
359
+ console.log();
360
+ console.log(` ${s.cyan("import {")}`);
361
+ for (let i = 0; i < comps.length; i++) {
362
+ const comma = i < comps.length - 1 ? "," : "";
363
+ console.log(` ${s.cyan(" " + comps[i] + comma)}`);
364
+ }
365
+ console.log(` ${s.cyan("} from \"@electroplix/components\";")}`);
366
+ console.log();
367
+
368
+ /* tree display */
369
+ console.log(` ${s.bold("Components:")}`);
370
+ console.log();
371
+ for (let i = 0; i < comps.length; i++) {
372
+ const isLast = i === comps.length - 1;
373
+ const prefix = isLast ? B.last : B.branch;
374
+ console.log(` ${s.gray(prefix)} ${s.violet(comps[i])}`);
375
+ }
376
+ console.log();
377
+ return;
378
+ }
379
+
380
+ /* ── try individual component match ────────────────── */
381
+ const entry = ALL_COMPONENTS.get(key);
154
382
  if (!entry) {
155
- console.log(`\n${PURPLE}electroplix${RESET} Component "${name}" not found.\n`);
156
- console.log(`Run ${CYAN}npx @electroplix/components list${RESET} to see all available components.\n`);
383
+ console.log(` ${s.red("\u2717")} Component or category ${s.bold("\"" + name + "\"")} not found.\n`);
384
+ console.log(` ${s.dim("Run")} ${s.cyan("npx @electroplix/components list")} ${s.dim("to see all options.")}\n`);
157
385
  process.exit(1);
158
386
  }
159
387
 
160
- console.log(`
161
- ${PURPLE}electroplix${RESET} ${BOLD}${entry.name}${RESET} ${DIM}(${entry.category})${RESET}
388
+ const W = 52;
389
+ console.log(` ${B.tl}${hr(W)}${B.tr}`);
390
+ console.log(boxLine(B.v, ` ${s.bold(s.purple(entry.name))} ${s.dim("from " + s.violet(entry.category))}`, B.v, W));
391
+ console.log(` ${B.bl}${hr(W)}${B.br}`);
392
+ console.log();
393
+ console.log(` ${s.green("1.")} ${s.white("Install")} ${s.dim("(if not already):")}`);
394
+ console.log(` ${s.cyan("npm install @electroplix/components")}`);
395
+ console.log();
396
+ console.log(` ${s.green("2.")} ${s.white("Import:")}`);
397
+ console.log(` ${s.cyan("import { " + entry.name + " } from \"@electroplix/components\";")}`);
398
+ console.log();
399
+ console.log(` ${s.green("3.")} ${s.white("Use in JSX:")}`);
400
+ console.log(` ${s.cyan("<" + entry.name + " />")}`);
401
+ console.log();
402
+ console.log(` ${s.dim("All components are config-driven. Wrap your app with")}`);
403
+ console.log(` ${s.dim("<Providers> (from")} ${s.cyan("npx @electroplix/components init")}${s.dim(") to theme globally.")}`);
404
+ console.log();
405
+ }
162
406
 
163
- ${GREEN}1.${RESET} Make sure @electroplix/components is installed:
407
+ /* ══════════════════════════════════════════════════════════════════ */
408
+ /* LIST command */
409
+ /* ══════════════════════════════════════════════════════════════════ */
164
410
 
165
- ${CYAN}npm install @electroplix/components${RESET}
411
+ function list() {
412
+ printBanner();
166
413
 
167
- ${GREEN}2.${RESET} Import the component:
414
+ console.log(` ${s.bold(s.white(totalCount + " components"))} ${s.dim("across")} ${s.bold(s.white(Object.keys(CATEGORIES).length + " categories"))}`);
415
+ console.log(` ${s.gray(hr(54))}`);
416
+ console.log();
168
417
 
169
- ${CYAN}import { ${entry.name} } from "@electroplix/components";${RESET}
418
+ const catEntries = Object.entries(CATEGORIES);
170
419
 
171
- ${GREEN}3.${RESET} Use it in your JSX:
420
+ for (let ci = 0; ci < catEntries.length; ci++) {
421
+ const [cat, names] = catEntries[ci];
422
+ const isLastCat = ci === catEntries.length - 1;
423
+ const catPrefix = isLastCat ? B.end : B.tee;
424
+ const childPipe = isLastCat ? " " : B.pipe;
172
425
 
173
- ${CYAN}<${entry.name} />${RESET}
426
+ console.log(` ${s.gray(catPrefix)} ${s.bold(s.purple(cat))} ${s.dim("(" + names.length + ")")}`);
174
427
 
175
- ${DIM}All components are config-driven. Wrap your app with
176
- <ElectroplixProvider> to customize themes globally.${RESET}
177
- `);
178
- }
428
+ for (let ni = 0; ni < names.length; ni++) {
429
+ const isLastName = ni === names.length - 1;
430
+ const namePrefix = isLastName ? B.last : B.branch;
431
+ console.log(` ${s.gray(childPipe)} ${s.gray(namePrefix)} ${s.cyan(names[ni])}`);
432
+ }
179
433
 
180
- function list() {
181
- console.log(`\n${PURPLE}@electroplix/components${RESET} – ${BOLD}${ALL_COMPONENTS.size} components${RESET}\n`);
182
- for (const [cat, names] of Object.entries(CATEGORIES)) {
183
- console.log(` ${BOLD}${cat}${RESET} ${DIM}(${names.length})${RESET}`);
184
- console.log(` ${names.map((n) => `${CYAN}${n}${RESET}`).join(", ")}`);
185
- console.log();
434
+ if (!isLastCat) console.log(` ${s.gray(B.pipe)}`);
186
435
  }
436
+
437
+ console.log();
438
+ console.log(` ${s.dim("Add a component:")} ${s.cyan("npx @electroplix/components add <name>")}`);
439
+ console.log(` ${s.dim("Add a category:")} ${s.cyan("npx @electroplix/components add <category>")}`);
440
+ console.log(` ${s.dim("Scaffold project:")} ${s.cyan("npx @electroplix/components init")}`);
441
+ console.log();
442
+ }
443
+
444
+ /* ══════════════════════════════════════════════════════════════════ */
445
+ /* HELP / default */
446
+ /* ══════════════════════════════════════════════════════════════════ */
447
+
448
+ function help() {
449
+ printBanner();
450
+
451
+ console.log(` ${s.bold("Commands:")}`);
452
+ console.log();
453
+ console.log(` ${s.cyan("init")} ${s.white("Scaffold config + providers for your project")}`);
454
+ console.log(` ${s.cyan("add")} ${s.violet("<name>")} ${s.white("Show import instructions for a component")}`);
455
+ console.log(` ${s.cyan("add")} ${s.violet("<category>")} ${s.white("Show all components in a category")}`);
456
+ console.log(` ${s.cyan("list")} ${s.white("Browse all")} ${s.bold(totalCount + "")} ${s.white("components")}`);
457
+ console.log();
458
+ console.log(` ${s.bold("Examples:")}`);
459
+ console.log();
460
+ console.log(` ${s.gray("$")} ${s.white("npx @electroplix/components init")}`);
461
+ console.log(` ${s.gray("$")} ${s.white("npx @electroplix/components add PrimaryNav")}`);
462
+ console.log(` ${s.gray("$")} ${s.white("npx @electroplix/components add navigation")}`);
463
+ console.log(` ${s.gray("$")} ${s.white("npx @electroplix/components list")}`);
464
+ console.log();
187
465
  }
188
466
 
189
- /* ── main ───────────────────────────────────────────────── */
467
+ /* ══════════════════════════════════════════════════════════════════ */
468
+ /* Main */
469
+ /* ══════════════════════════════════════════════════════════════════ */
190
470
 
191
471
  const [, , cmd, ...args] = process.argv;
192
472
 
@@ -195,17 +475,11 @@ switch (cmd) {
195
475
  init();
196
476
  break;
197
477
  case "add":
198
- add(args[0]);
478
+ add(args.join(" "));
199
479
  break;
200
480
  case "list":
201
481
  list();
202
482
  break;
203
483
  default:
204
- console.log(`
205
- ${PURPLE}@electroplix/components${RESET} CLI
206
-
207
- ${CYAN}init${RESET} Scaffold electroplix.config.ts
208
- ${CYAN}add <name>${RESET} Show import instructions for a component
209
- ${CYAN}list${RESET} List all ${ALL_COMPONENTS.size} available components
210
- `);
484
+ help();
211
485
  }
package/dist/README.md CHANGED
@@ -1,110 +1,35 @@
1
1
  # @electroplix/components
2
2
 
3
- Parametric, config-driven React UI components.
3
+ Parametric, config-driven React UI components — 153 components across 18 categories.
4
4
 
5
- ## Install
6
-
7
- ```bash
8
- npm install @electroplix/components
9
- # or
10
- pnpm add @electroplix/components
11
- ```
12
-
13
- > **Peer dependencies:** `react >=18` and `react-dom >=18`.
5
+ See the full documentation in the [root README](../README.md).
14
6
 
15
7
  ## Quick start
16
8
 
17
- ```tsx
18
- import { Navbar } from "@electroplix/components";
19
-
20
- export default function Page() {
21
- return (
22
- <Navbar
23
- logoText="MyBrand"
24
- links={[
25
- { label: "Home", href: "/" },
26
- { label: "Docs", href: "/docs" },
27
- ]}
28
- ctaText="Sign Up"
29
- />
30
- );
31
- }
9
+ ```bash
10
+ npm install @electroplix/components
11
+ npx @electroplix/components init
32
12
  ```
33
13
 
34
- ## Global configuration
35
-
36
- Create a config file and wrap your app with `ElectroplixProvider` to set
37
- style defaults for **every** component instance:
38
-
39
- ```ts
40
- // electroplix.config.ts
41
- import { defineConfig } from "@electroplix/components";
42
-
43
- export default defineConfig({
44
- navbar: {
45
- bgColor: "#22223B",
46
- textColor: "#F2E9E4",
47
- accentColor: "#C9ADA7",
48
- borderColor: "#4A4E69",
49
- fontFamily: "Roboto, sans-serif",
50
- height: 80,
51
- padding: 32,
52
- sticky: true,
53
- showSearch: true,
54
- showCTA: true,
55
- },
56
- });
57
- ```
14
+ Then update `app/layout.tsx`:
58
15
 
59
16
  ```tsx
60
- // app/layout.tsx (Next.js App Router example)
61
- import { ElectroplixProvider } from "@electroplix/components";
62
- import config from "../electroplix.config";
17
+ import { Providers } from "../components/providers";
63
18
 
64
19
  export default function RootLayout({ children }: { children: React.ReactNode }) {
65
20
  return (
66
- <html lang="en">
21
+ <html>
67
22
  <body>
68
- <ElectroplixProvider config={config}>
69
- {children}
70
- </ElectroplixProvider>
23
+ <Providers>{children}</Providers>
71
24
  </body>
72
25
  </html>
73
26
  );
74
27
  }
75
28
  ```
76
29
 
77
- Components will merge configuration in priority order:
78
- 1. **Per-instance** `config` prop (highest)
79
- 2. **Global** `ElectroplixProvider` config
80
- 3. **Built-in** defaults
81
-
82
- ## API reference
30
+ Use components in `"use client"` pages:
83
31
 
84
- ### `<Navbar>`
85
-
86
- | Prop | Type | Default | Description |
87
- |------|------|---------|-------------|
88
- | `logoText` | `string` | `"Electroplix"` | Brand text |
89
- | `logoHref` | `string` | `"/"` | Logo link target |
90
- | `links` | `NavLink[]` | `[]` | Navigation links |
91
- | `ctaText` | `string` | `"Get Started"` | CTA button label |
92
- | `ctaHref` | `string` | `"#"` | CTA button href |
93
- | `searchPlaceholder` | `string` | `"Search…"` | Search input placeholder |
94
- | `onSearch` | `(q: string) => void` | — | Search callback |
95
- | `config` | `NavbarConfig` | — | Per-instance style overrides |
96
-
97
- ### `NavbarConfig` (global or per-instance)
98
-
99
- | Key | Type | Default |
100
- |-----|------|---------|
101
- | `bgColor` | `string` | `"#0B0B0C"` |
102
- | `textColor` | `string` | `"#F3F4F6"` |
103
- | `accentColor` | `string` | `"#8B5CF6"` |
104
- | `borderColor` | `string` | `"rgba(255,255,255,0.1)"` |
105
- | `fontFamily` | `string` | `"Inter, ui-sans-serif, system-ui"` |
106
- | `height` | `number` | `72` |
107
- | `padding` | `number` | `24` |
108
- | `sticky` | `boolean` | `false` |
109
- | `showSearch` | `boolean` | `false` |
110
- | `showCTA` | `boolean` | `false` |
32
+ ```tsx
33
+ "use client";
34
+ import { PrimaryNav, StaticHero } from "@electroplix/components";
35
+ ```
package/dist/index.esm.js CHANGED
@@ -234,6 +234,12 @@ function mergeTheme(target, ...sources) {
234
234
 
235
235
  const Ctx = /*#__PURE__*/createContext(defaultConfig);
236
236
 
237
+ /** Keys that belong to BaseTheme (global overrides), not categories */
238
+ const BASE_KEYS = new Set(["bgColor", "textColor", "accentColor", "borderColor", "fontFamily", "radius", "spacing", "headingSize", "bodySize", "fontWeight", "lineHeight", "letterSpacing", "shadow"]);
239
+
240
+ /** Keys that map to per-category theme objects */
241
+ const CATEGORY_KEYS = new Set(["blog", "buttons", "content", "dataDisplay", "ecommerce", "forms", "hero", "listsCards", "marketing", "media", "miscellaneous", "modals", "navigation", "onboarding", "search", "siteIdentity", "social", "userAccounts"]);
242
+
237
243
  /**
238
244
  * Wrap your app (or any subtree) to override default theme tokens.
239
245
  *
@@ -253,9 +259,22 @@ function ElectroplixProvider({
253
259
  }) {
254
260
  const merged = useMemo(() => {
255
261
  if (!config) return defaultConfig;
262
+
263
+ // Extract root-level BaseTheme overrides (accentColor, bgColor, etc.)
264
+ const globalBase = {};
265
+ for (const key of Object.keys(config)) {
266
+ if (BASE_KEYS.has(key)) {
267
+ globalBase[key] = config[key];
268
+ }
269
+ }
270
+
271
+ // Merge each category: default → global base → per-category overrides
256
272
  const out = {};
257
- for (const key of Object.keys(defaultConfig)) {
258
- out[key] = mergeTheme(defaultConfig[key], config[key]);
273
+ for (const key of CATEGORY_KEYS) {
274
+ const catKey = key;
275
+ const defaultVal = defaultConfig[catKey];
276
+ const categoryOverrides = config[catKey];
277
+ out[key] = mergeTheme(defaultVal != null ? defaultVal : {}, globalBase, categoryOverrides);
259
278
  }
260
279
  return out;
261
280
  }, [config]);
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/core/provider.tsx"],"names":[],"mappings":"AAKA,OAAO,KAA6C,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAKjD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,QAAQ,GACT,EAAE;IACD,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACpC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,2CAcA;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,iBAAiB,CAExD;AAED;;GAEG;AACH,wBAAgB,WAAW,kDAAgD;AAC3E,wBAAgB,YAAY,4CAA0C;AACtE,wBAAgB,cAAc,8CAA6C;AAC3E,wBAAgB,aAAa,6CAA2C;AACxE,wBAAgB,eAAe,+CAA6C;AAC5E,wBAAgB,mBAAmB,mDAAiD;AACpF,wBAAgB,iBAAiB,iDAA+C;AAChF,wBAAgB,kBAAkB,kDAAgD;AAClF,wBAAgB,iBAAiB,iDAA+C;AAChF,wBAAgB,aAAa,6CAA2C;AACxE,wBAAgB,YAAY,4CAAmD;AAC/E,wBAAgB,cAAc,8CAA4C;AAC1E,wBAAgB,kBAAkB,kDAAgD;AAClF,wBAAgB,cAAc,8CAA4C;AAC1E,wBAAgB,oBAAoB,oDAAkD;AACtF,wBAAgB,cAAc,8CAA4C;AAC1E,wBAAgB,oBAAoB,oDAAkD;AACtF,wBAAgB,YAAY,4CAA0C"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/core/provider.tsx"],"names":[],"mappings":"AAKA,OAAO,KAA6C,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAa,MAAM,SAAS,CAAC;AAmB5D;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,QAAQ,GACT,EAAE;IACD,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACpC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,2CA4BA;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,iBAAiB,CAExD;AAED;;GAEG;AACH,wBAAgB,WAAW,kDAAgD;AAC3E,wBAAgB,YAAY,4CAA0C;AACtE,wBAAgB,cAAc,8CAA6C;AAC3E,wBAAgB,aAAa,6CAA2C;AACxE,wBAAgB,eAAe,+CAA6C;AAC5E,wBAAgB,mBAAmB,mDAAiD;AACpF,wBAAgB,iBAAiB,iDAA+C;AAChF,wBAAgB,kBAAkB,kDAAgD;AAClF,wBAAgB,iBAAiB,iDAA+C;AAChF,wBAAgB,aAAa,6CAA2C;AACxE,wBAAgB,YAAY,4CAAmD;AAC/E,wBAAgB,cAAc,8CAA4C;AAC1E,wBAAgB,kBAAkB,kDAAgD;AAClF,wBAAgB,cAAc,8CAA4C;AAC1E,wBAAgB,oBAAoB,oDAAkD;AACtF,wBAAgB,cAAc,8CAA4C;AAC1E,wBAAgB,oBAAoB,oDAAkD;AACtF,wBAAgB,YAAY,4CAA0C"}
@@ -122,7 +122,7 @@ export interface ShellProps {
122
122
  className?: string;
123
123
  children?: ReactNode;
124
124
  }
125
- export interface ElectroplixConfig {
125
+ export interface ElectroplixConfig extends Partial<BaseTheme> {
126
126
  blog?: BlogTheme;
127
127
  buttons?: ButtonTheme;
128
128
  content?: ContentTheme;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMnE,yDAAyD;AACzD,MAAM,MAAM,OAAO,GAAG,aAAa,CAAC;AAEpC,0DAA0D;AAC1D,MAAM,WAAW,SAAS;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,yDAAyD;AACzD,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,kEAAkE;AAClE,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD,MAAM,WAAW,SAAU,SAAQ,SAAS,EAAE,UAAU;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,YAAa,SAAQ,SAAS,EAAE,UAAU;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAiB,SAAQ,SAAS,EAAE,UAAU;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAe,SAAQ,SAAS,EAAE,UAAU,EAAE,WAAW;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAW,SAAQ,SAAS,EAAE,UAAU,EAAE,WAAW;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAU,SAAQ,SAAS,EAAE,UAAU;IACtD,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAgB,SAAQ,SAAS,EAAE,UAAU,EAAE,WAAW;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAe,SAAQ,SAAS,EAAE,UAAU,EAAE,WAAW;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAW,SAAQ,SAAS;CAE5C;AAED,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;CAE7C;AAED,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,eAAgB,SAAQ,SAAS,EAAE,UAAU;CAE7D;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS,EAAE,UAAU;CAEzD;AAED,MAAM,WAAW,iBAAkB,SAAQ,SAAS;CAEnD;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAkB,SAAQ,SAAS,EAAE,WAAW;CAEhE;AAMD,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAMrD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAMvD,MAAM,WAAW,UAAU;IACzB,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAMD,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,iBAAiB,CAAC;CAClC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electroplix/components",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Parametric, config-driven UI components by Electroplix. ~154 components across 18 categories — navigation, hero, buttons, forms, content, data display, ecommerce, lists/cards, marketing, media, miscellaneous, modals, onboarding, search, site-identity, social, user-accounts, and blog.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -16,14 +16,23 @@
16
16
  "@electroplix-workspace/source": "./src/index.ts",
17
17
  "types": "./dist/index.d.ts",
18
18
  "import": "./dist/index.esm.js",
19
+ "require": "./dist/index.esm.js",
19
20
  "default": "./dist/index.esm.js"
20
21
  },
21
22
  "./config": {
22
23
  "types": "./dist/config.d.ts",
23
24
  "import": "./dist/config.esm.js",
25
+ "require": "./dist/config.esm.js",
24
26
  "default": "./dist/config.esm.js"
25
27
  }
26
28
  },
29
+ "typesVersions": {
30
+ "*": {
31
+ "config": [
32
+ "./dist/config.d.ts"
33
+ ]
34
+ }
35
+ },
27
36
  "files": [
28
37
  "dist",
29
38
  "cli.cjs",