@nqlib/nqui 0.4.6 → 0.4.7

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.
Files changed (35) hide show
  1. package/INSTALLATION.md +27 -23
  2. package/README.md +1 -1
  3. package/dist/{command-palette-MHc03bBf.cjs → command-palette-DSQYbRiH.cjs} +2 -2
  4. package/dist/{command-palette-DCtLpM3Q.js → command-palette-D_SFxXyQ.js} +47 -50
  5. package/dist/command.cjs.js +1 -1
  6. package/dist/command.es.js +1 -1
  7. package/dist/components/index.d.ts +2 -2
  8. package/dist/components/index.d.ts.map +1 -1
  9. package/dist/components/ui/combobox.d.ts +63 -18
  10. package/dist/components/ui/combobox.d.ts.map +1 -1
  11. package/dist/components/ui/command.d.ts +9 -1
  12. package/dist/components/ui/command.d.ts.map +1 -1
  13. package/dist/{debug-panel-pg39-6xw.js → debug-panel-BtOvhfpR.js} +43 -39
  14. package/dist/{debug-panel-CNKk-No5.cjs → debug-panel-DLfH4sdK.cjs} +6 -6
  15. package/dist/debug.cjs.js +1 -1
  16. package/dist/debug.es.js +1 -1
  17. package/dist/nqui.cjs.js +13 -13
  18. package/dist/nqui.es.js +3614 -3265
  19. package/dist/styles.css +3 -2
  20. package/docs/components/nqui-card.md +1 -1
  21. package/docs/components/nqui-combobox.md +75 -11
  22. package/package.json +1 -7
  23. package/scripts/generate-docs.js +3 -1
  24. package/scripts/peer-deps.js +0 -1
  25. package/docs/internal-notes/APP_BUILDER_PACKAGE.md +0 -86
  26. package/docs/internal-notes/BUILD_VERIFICATION.md +0 -174
  27. package/docs/internal-notes/DASHBOARD_LAYOUT_DESIGN.md +0 -1429
  28. package/docs/internal-notes/FROSTED_GLASS_FIX.md +0 -50
  29. package/docs/internal-notes/INSTALLATION.md +0 -274
  30. package/docs/internal-notes/PEER_DEPENDENCIES.md +0 -105
  31. package/docs/internal-notes/PUBLISHING.md +0 -411
  32. package/docs/internal-notes/SKILLS-ARCHITECTURE.md +0 -105
  33. package/docs/internal-notes/layoutdesign.md +0 -616
  34. package/docs/internal-notes/progress.md +0 -348
  35. package/docs/internal-notes/stacked-avatar-implementation.md +0 -38
package/dist/styles.css CHANGED
@@ -1185,8 +1185,9 @@
1185
1185
  --secondary-foreground: oklch(0.3067 0.0309 56.81);
1186
1186
  --muted: oklch(0.9111 0.0082 73.15);
1187
1187
  --muted-foreground: oklch(0.5576 0.0222 57.81);
1188
- --accent: oklch(0.4789 0.0623 56.16);
1189
- --accent-foreground: oklch(0.9792 0.0042 78.3);
1188
+ /* Hover/focus wash (menus, ghost buttons) — high L like :root accent, not a filled control */
1189
+ --accent: oklch(0.935 0.011 73.15);
1190
+ --accent-foreground: oklch(0.2416 0.0219 57);
1190
1191
  --border: oklch(0.89 0.0137 73.1);
1191
1192
  --input: oklch(0.89 0.0137 73.1);
1192
1193
 
@@ -35,5 +35,5 @@ import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter }
35
35
  - **Layout / bounds:** Root **Card**, **CardHeader**, **CardContent**, and **CardFooter** include **`min-w-0`** so nested flex/grid layouts can shrink and children are less likely to spill horizontally. **Card** stays **`overflow-visible`** on purpose so popovers, menus, and focus rings are not clipped—pair with bounded components (buttons, carousel insets, `truncate`, etc.) instead of `overflow-hidden` on the card by default.
36
36
  - **stickyHeader:** Use `stickyHeader` prop on Card for scrollable content with sticky header. The header uses `--z-sticky-content` (z-index: 15).
37
37
  - **Z-index layering:** Card sticky headers (15) are below page headers (20). If using in a page with sticky header, ensure proper z-index layering.
38
- - **Height required:** Card needs a defined height (e.g., `h-[400px]` or `h-full`) for sticky behavior to work.
38
+ - **Height required:** Card needs a bounded height (e.g., `h-[400px]`, `h-80`, or `h-full` inside a fixed-height parent). **`max-h-*` alone is not enough**—the card still grows with content, so the scroll body will not overflow. Clip frosted glass with an outer `overflow-hidden rounded-*` wrapper if needed; avoid `overflow-hidden` on the Card root with `stickyHeader` (it can break Radix ScrollArea).
39
39
  - **Content scroll:** The CardContent becomes scrollable when Card has `stickyHeader` and a defined height.
@@ -1,12 +1,13 @@
1
1
  # nqui Combobox
2
2
 
3
- > **Searchable** select (Base UI). User types to filter options. Single or multiple selection.
3
+ > **Searchable** select (Radix Popover + cmdk). Type in `**ComboboxInput`** to filter; a hidden cmdk input stays in sync. Single or multiple selection.
4
4
 
5
5
  ## When to Use
6
6
 
7
- - **Selection:** Single (default) or multiple (`multiple` on root)
8
- - **Key feature:** Filter list by typing in the input
9
- - **Options:** Many rows; use **`items`** on `Combobox` + render prop on `ComboboxList` for built-in filtering
7
+ - **Selection:** Single (default) or multiple (`multiple` on root — items toggle; popover stays open until dismissed)
8
+ - **Filter:** Type in the **trigger field** while the list is open (same `search` state as cmdk)
9
+ - **Icons:** Put icons (or other nodes) inside `**ComboboxItem`**; use `**keywords**` if the visible label text is not enough for matching
10
+ - **Options:** Many rows; use `**items`** on `Combobox` + render prop on `ComboboxList` for built-in filtering
10
11
 
11
12
  **Choose Combobox when:** Users need search. Use **Select** when a plain dropdown is enough.
12
13
 
@@ -16,6 +17,7 @@
16
17
  import {
17
18
  Combobox,
18
19
  ComboboxInput,
20
+ ComboboxBadgeTrigger,
19
21
  ComboboxContent,
20
22
  ComboboxList,
21
23
  ComboboxItem,
@@ -36,16 +38,16 @@ import {
36
38
 
37
39
  ## Single selection + type-to-filter (recommended)
38
40
 
39
- Pass **`items`** to `Combobox` and use a **render function** as the only child of `ComboboxList`. Place **`ComboboxEmpty`** next to `ComboboxList` (both under `ComboboxContent`), not inside `ComboboxList` alongside the function.
41
+ Pass `**items**` to `Combobox` and use a **render function** on `ComboboxList`. Put `**ComboboxEmpty`** first inside `**ComboboxList**` (cmdk empty state).
40
42
 
41
43
  ```tsx
42
44
  const fruits = ["Apple", "Banana", "Cherry", "Date", "Elderberry"]
43
45
 
44
- <Combobox items={fruits}>
45
- <ComboboxInput placeholder="Search..." />
46
+ <Combobox items={fruits} searchPlaceholder="Filter…">
47
+ <ComboboxInput placeholder="Pick a fruit…" />
46
48
  <ComboboxContent>
47
- <ComboboxEmpty>No results found.</ComboboxEmpty>
48
49
  <ComboboxList>
50
+ <ComboboxEmpty>No results found.</ComboboxEmpty>
49
51
  {(item) => (
50
52
  <ComboboxItem key={item} value={item}>
51
53
  {item}
@@ -78,17 +80,79 @@ You can still render `ComboboxItem` children manually when you control filtering
78
80
  <ComboboxInput showClear placeholder="Search..." />
79
81
  ```
80
82
 
81
- ## Multiple selection
83
+ ## Multiple selection (badge trigger)
84
+
85
+ Use `**ComboboxBadgeTrigger**` as the anchor (outline button, badges, **maxShownItems** truncation, **+N more** / **Show less**). Pair with `**ComboboxContent showPanelSearch`** so users type in the **panel** search field (matches typical multi-select combobox UX).
86
+
87
+ ```tsx
88
+ <Combobox multiple items={ids} value={value} onValueChange={setValue} searchPlaceholder="Search…">
89
+ <ComboboxBadgeTrigger placeholder="Select…" maxShownItems={2} />
90
+ <ComboboxContent showPanelSearch>
91
+ <ComboboxList>
92
+ <ComboboxEmpty>No results.</ComboboxEmpty>
93
+ {(id) => (
94
+ <ComboboxItem key={id} value={id}>
95
+ {resolveLabel(id)}
96
+ </ComboboxItem>
97
+ )}
98
+ </ComboboxList>
99
+ </ComboboxContent>
100
+ </Combobox>
101
+ ```
102
+
103
+ For a custom chip row, you can still use `**ComboboxChips**`, `**ComboboxChip**`, and `**ComboboxChipsInput**` inside `**ComboboxContent**`.
104
+
105
+ ## Development-only diagnostics
106
+
107
+ Pass `**debug**` on `**Combobox**` to log open state, value, search, and list id (only when `**import.meta.env.DEV**` is true, e.g. Vite dev). No logging in production builds.
108
+
109
+ ```tsx
110
+ <Combobox debug defaultValue="us">
111
+ ...
112
+ </Combobox>
113
+ ```
114
+
115
+ ## Architecture (internal)
116
+
117
+ The public API is unchanged; the implementation composes:
118
+
119
+
120
+ | Layer | Role |
121
+ | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
122
+ | `**radix-ui` Popover** | Same primitives as `popover.tsx` (`Root`, `Anchor`, `Portal`, `Content`) — one Radix entrypoint for positioning and focus. |
123
+ | `**Command` (cmdk)** | Panel search + list; order matches the command palette: `**CommandInput`** then list children. |
124
+ | `**ComboboxList` → `CommandList**` | Ref reads the **real** list node id after mount for `**aria-controls`** on the trigger (see cmdk constraints below). |
125
+ | `**ComboboxItem` → `CommandItem**` | Shared row styles and checkmark behavior with `**CommandPalette**` / cmdk. |
126
+
127
+
128
+ When `**showPanelSearch**` is false, the panel `**CommandInput**` is wrapped in `**sr-only**` (not `hidden` / `display: none`) so cmdk filtering stays consistent.
129
+
130
+ ## cmdk constraints
131
+
132
+ - **List `id`:** cmdk **overwrites** the `id` on `Command.List`. Do not assume `useId()` matches the DOM — the combobox mirrors the mounted list element’s id into context for `**aria-controls`**.
133
+ - **Selection styling:** Prefer `**aria-selected`** / `**data-selected**` (boolean) utilities. Patterns like `**data-[selected=true]:**` can fail because the attribute is not always the string `"true"`.
134
+ - **Panel input:** Keep the cmdk input **mounted** when filtering (see `**sr-only`** branch above).
135
+
136
+ ## Troubleshooting
137
+
138
+
139
+ | Symptom | What to check |
140
+ | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
141
+ | Trigger `**aria-controls**` missing or wrong | `**ComboboxList**` must mount while the popover is open so the list ref can read `**id**`. |
142
+ | Row highlight / keyboard selection looks wrong | Styles targeting only `**data-[selected=true]**`; use `**aria-selected:**` or boolean `**data-selected**` variants. |
143
+ | **Mouse hover / click on rows does nothing; keyboard works** | Row styles must not use a broad `**data-[disabled]:pointer-events-none`** (can match any `data-disabled` value). Use `**aria-disabled:**` (or `**data-[disabled=true]:**`) so only disabled items drop pointer events. Hidden panel search is wrapped with `**sr-only**` + `**pointer-events-none**`; the cmdk `**CommandInput**` keeps `**pointer-events-auto**`. |
144
+ | Filter feels out of sync | Avoid hiding the panel `**CommandInput**` with `**display: none**`. |
82
145
 
83
- Use **`multiple`** on `Combobox` (see [Base UI Combobox](https://base-ui.com/react/components/combobox)). Combine with **`ComboboxChips`**, **`ComboboxChip`**, **`ComboboxChipsInput`** as needed for chip UI.
84
146
 
85
147
  ## Implementation
86
148
 
87
149
  - **Source:** `packages/nqui/src/components/ui/combobox.tsx`
88
150
  - **Public API:** exported from `@nqlib/nqui` (same as `CoreCombobox*` aliases in the barrel if you need the unprefixed base re-exports)
89
151
  - **Styling:** Input group uses injected CSS once per page (`nqui-combobox-styles-v1`) for trigger depth/shadow; component is `"use client"`.
152
+ - **Docs location:** In-repo `packages/nqui/docs/components/`; in apps, `node_modules/@nqlib/nqui/docs/components/` (docs ship with the npm package). Skill: **nqui-components** (`.cursor/skills/nqui-components/SKILL.md`).
90
153
 
91
154
  ## Notes
92
155
 
93
- - **`useComboboxAnchor`:** ref for anchoring `ComboboxContent` when using chips / custom layout.
156
+ - `**useComboboxAnchor`:** returns a ref to pass to `**PopoverAnchor`** (from `@nqlib/nqui`) wrapping the chips row so the dropdown positions correctly when using `**ComboboxChips**` / custom layout.
94
157
  - **Dropdown items:** spacing/hover treatment aligns with **Select** (`SelectItem`-style density).
158
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nqlib/nqui",
3
- "version": "0.4.6",
3
+ "version": "0.4.7",
4
4
  "description": "A React component library with enhanced UI components and developer tools",
5
5
  "type": "module",
6
6
  "main": "./dist/nqui.cjs.js",
@@ -139,7 +139,6 @@
139
139
  "@radix-ui/react-direction": "^1.1.1",
140
140
  "@radix-ui/react-dropdown-menu": "^2.1.16",
141
141
  "@radix-ui/react-label": "^2.1.8",
142
- "@radix-ui/react-popover": "^1.1.15",
143
142
  "@radix-ui/react-select": "^2.2.6",
144
143
  "@radix-ui/react-separator": "^1.1.8",
145
144
  "@radix-ui/react-slot": "^1.2.4",
@@ -178,7 +177,6 @@
178
177
  "vaul": "^1.1.2"
179
178
  },
180
179
  "peerDependencies": {
181
- "@base-ui/react": "^1.0.0",
182
180
  "@hugeicons/core-free-icons": "^3.0.0",
183
181
  "@hugeicons/react": "^1.0.0",
184
182
  "@dnd-kit/core": "^6.0.0",
@@ -232,13 +230,9 @@
232
230
  },
233
231
  "react-resizable-panels": {
234
232
  "optional": true
235
- },
236
- "@base-ui/react": {
237
- "optional": true
238
233
  }
239
234
  },
240
235
  "devDependencies": {
241
- "@base-ui/react": "^1.0.0",
242
236
  "@eslint/js": "^9.39.1",
243
237
  "@storybook/addon-docs": "^10.1.11",
244
238
  "@storybook/addon-links": "^10.1.11",
@@ -17,6 +17,8 @@ import { fileURLToPath } from 'url';
17
17
 
18
18
  const __dirname = dirname(fileURLToPath(import.meta.url));
19
19
  const DOCS_DIR = join(__dirname, '../docs');
20
+ /** Maintainer-only notes; not under docs/ so they are not shipped in the npm `docs` bundle. */
21
+ const INTERNAL_NOTES_DIR = join(__dirname, '../internal-notes');
20
22
  const OUTPUT_DIR = join(__dirname, '../dist/docs');
21
23
 
22
24
  // Ensure output directory exists
@@ -37,7 +39,7 @@ function readDoc(filePath) {
37
39
  }
38
40
 
39
41
  function generateInstallDoc() {
40
- const installPath = join(DOCS_DIR, 'internal-notes/INSTALLATION.md');
42
+ const installPath = join(INTERNAL_NOTES_DIR, 'INSTALLATION.md');
41
43
  let content = readDoc(installPath);
42
44
 
43
45
  if (!content) {
@@ -21,7 +21,6 @@ export const OPTIONAL_PEERS = [
21
21
  'sonner',
22
22
  'vaul',
23
23
  'react-resizable-panels',
24
- '@base-ui/react',
25
24
  ];
26
25
 
27
26
  export const FULL_PEER_LIST = [...REQUIRED_PEERS, ...OPTIONAL_PEERS];
@@ -1,86 +0,0 @@
1
- # App Builder Package (@nqlib/nqappbuilder)
2
-
3
- ## Overview
4
-
5
- The App Builder has been extracted from nqui into a separate package `@nqlib/nqappbuilder` to reduce nqui's bundle size and allow independent versioning. The visual app builder includes a drag-and-drop canvas, widget palette, configurator, and registry system.
6
-
7
- ## Installation
8
-
9
- ```bash
10
- pnpm add @nqlib/nqappbuilder @nqlib/nqui
11
- # or
12
- npm install @nqlib/nqappbuilder @nqlib/nqui
13
- ```
14
-
15
- ## Peer Dependencies
16
-
17
- - `react` (^18.2.0)
18
- - `react-dom` (^18.2.0)
19
- - `@nqlib/nqui` (required) — provides UI components, design tokens, and utilities
20
-
21
- Consumers must install these alongside nqappbuilder.
22
-
23
- ## Usage
24
-
25
- ```tsx
26
- import {
27
- AppBuilder,
28
- AppBuilderProvider,
29
- AppCanvas,
30
- WidgetPalette,
31
- WidgetConfigurator,
32
- defaultRegistry,
33
- } from "@nqlib/nqappbuilder"
34
-
35
- // All-in-one component
36
- export default function MyAppBuilder() {
37
- return (
38
- <AppBuilderProvider registry={defaultRegistry}>
39
- <AppBuilder />
40
- </AppBuilderProvider>
41
- )
42
- }
43
-
44
- // Or compose manually
45
- export default function CustomLayout() {
46
- return (
47
- <AppBuilderProvider registry={defaultRegistry}>
48
- <aside>
49
- <WidgetPalette />
50
- </aside>
51
- <main>
52
- <AppCanvas showToolbar enableCollisionDetection />
53
- </main>
54
- <WidgetConfigurator />
55
- </AppBuilderProvider>
56
- )
57
- }
58
- ```
59
-
60
- ## Extending the Registry
61
-
62
- Use `createWidgetRegistry`, `extendRegistry`, or pass a custom `registry` to `AppBuilderProvider`:
63
-
64
- ```tsx
65
- import {
66
- createWidgetRegistry,
67
- extendRegistry,
68
- defaultRegistry,
69
- buttonWidget,
70
- containerWidget,
71
- } from "@nqlib/nqappbuilder"
72
-
73
- const myRegistry = extendRegistry(defaultRegistry, [
74
- buttonWidget,
75
- containerWidget,
76
- myCustomWidget,
77
- ])
78
-
79
- <AppBuilderProvider registry={myRegistry}>
80
- <AppBuilder />
81
- </AppBuilderProvider>
82
- ```
83
-
84
- ## Documentation App
85
-
86
- Documentation maintainers: add a section or page for nqappbuilder in the documentation app. Link to this note for package details and migration context.
@@ -1,174 +0,0 @@
1
- # Build Verification Report
2
-
3
- This document provides a comprehensive comparison between source CSS files and the built `dist/styles.css` to ensure no content is missing or broken during the build process.
4
-
5
- ## Verification Script
6
-
7
- Run the verification script after building:
8
-
9
- ```bash
10
- npm run verify:build
11
- ```
12
-
13
- Or manually:
14
-
15
- ```bash
16
- node scripts/verify-build.js
17
- ```
18
-
19
- ## Verification Checks
20
-
21
- The verification script performs the following checks:
22
-
23
- ### 1. @source inline() Directives
24
- - ✅ Verifies all 15 `@source inline()` directives are preserved
25
- - ✅ Checks that all categories are present (Layout, Spacing, Typography, etc.)
26
- - ✅ Ensures no directives are missing or duplicated
27
-
28
- ### 2. :root CSS Variables
29
- - ✅ Extracts all CSS variables from `src/index.css`, `src/styles/colors.css`, and `src/styles/elevation.css`
30
- - ✅ Verifies all variables are present in the built CSS
31
- - ✅ Checks for missing or extra variables
32
-
33
- ### 3. .dark CSS Variables
34
- - ✅ Extracts all dark mode CSS variables from source files
35
- - ✅ Verifies all dark mode variables are preserved
36
- - ✅ Ensures proper merging of variables from multiple sources
37
-
38
- ### 4. Custom CSS Classes
39
- - ✅ Checks for custom `.nqui-*` classes (e.g., `.nqui-button-gradient`, `.nqui-debug-panel`)
40
- - ✅ Verifies all custom classes are present in the built CSS
41
-
42
- ### 5. Utility Classes in @source inline()
43
- - ✅ Extracts all utility class names from `@source inline()` directives
44
- - ✅ Verifies all 137+ utility classes are preserved
45
- - ✅ Ensures no utility classes are missing
46
-
47
- ### 6. Critical Patterns
48
- - ✅ Checks for presence of `@source inline()` directives
49
- - ✅ Verifies `:root` and `.dark` blocks exist
50
- - ✅ Validates specific elevation variables (--z-base, --z-content, etc.)
51
- - ✅ Validates specific color variables (--primary-500, --background, etc.)
52
-
53
- ### 7. Unwanted Patterns
54
- - ✅ Ensures `@import` directives are removed
55
- - ✅ Ensures `@custom-variant` directives are removed
56
- - ✅ Ensures framework-specific `@source` directives are removed
57
-
58
- ## Expected Results
59
-
60
- ### File Sizes
61
- - **Source index.css**: ~20 KB
62
- - **Built styles.css**: ~35 KB (includes merged colors.css and elevation.css)
63
- - **Colors.css**: ~6 KB
64
- - **Elevation.css**: ~10 KB
65
-
66
- ### Content Counts
67
- - **@source inline() directives**: 15 (17 occurrences including comments)
68
- - **:root blocks**: 1 (merged from all sources)
69
- - **.dark blocks**: 1 (merged from all sources)
70
- - **CSS variables**: ~240 total
71
- - **Custom classes**: 4 (.nqui-button-gradient, .nqui-button-shadow, .nqui-debug-panel, .nqui-shiki-container)
72
- - **@keyframes**: 6
73
- - **@layer base**: 1
74
-
75
- ### Structure Verification
76
- - ✅ `@source inline()` directives present
77
- - ✅ `@theme inline` present
78
- - ✅ `:root` block present
79
- - ✅ `.dark` block present
80
- - ✅ Elevation variables present (11 variables)
81
- - ✅ Color variables present (all primary, background, foreground, etc.)
82
- - ✅ Custom classes present
83
- - ✅ No `@import` directives
84
- - ✅ No `@custom-variant` directives
85
-
86
- ## Build Process
87
-
88
- The build process (`scripts/build-styles.js`) performs the following steps:
89
-
90
- 1. **Extract @source inline() directives** - Preserves all `@source inline()` directives before processing
91
- 2. **Remove framework-specific directives** - Removes `@import`, `@custom-variant`, and non-inline `@source` directives
92
- 3. **Extract CSS variables** - Extracts `:root` and `.dark` blocks from:
93
- - `src/index.css`
94
- - `src/styles/colors.css`
95
- - `src/styles/elevation.css`
96
- 4. **Merge variables** - Merges variables from all sources in the correct order:
97
- - Elevation variables first
98
- - Color system variables second
99
- - Additional variables from index.css last
100
- 5. **Preserve custom classes** - Keeps all custom CSS classes (`.nqui-*`)
101
- 6. **Preserve @theme inline** - Keeps the `@theme inline` block
102
- 7. **Preserve @keyframes** - Keeps all animation keyframes
103
- 8. **Add header** - Adds documentation header
104
- 9. **Prepend @source inline()** - Adds extracted `@source inline()` directives at the top
105
-
106
- ## Common Issues
107
-
108
- ### Missing @source inline() Directives
109
- **Symptom**: Verification fails with "Missing @source inline() directives"
110
-
111
- **Cause**: The build script's regex might not be matching multiline directives correctly.
112
-
113
- **Fix**: Ensure the regex uses `[\s\S]*?` for multiline matching:
114
- ```javascript
115
- const sourceInlineRegex = /\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/\s*@source\s+inline\([\s\S]*?\)\s*;/g;
116
- ```
117
-
118
- ### Missing CSS Variables
119
- **Symptom**: Verification fails with "Missing X variables"
120
-
121
- **Cause**: The extraction regex might not be handling nested braces correctly.
122
-
123
- **Fix**: Ensure the regex uses a pattern that handles nested braces:
124
- ```javascript
125
- const regex = /:root\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/s;
126
- ```
127
-
128
- ### Duplicate @source inline() Directives
129
- **Symptom**: Verification shows more directives than expected
130
-
131
- **Cause**: The removal regex might not be matching correctly, causing directives to be added twice.
132
-
133
- **Fix**: Ensure the removal regex matches the extraction regex exactly.
134
-
135
- ## Integration with CI/CD
136
-
137
- Add verification to your build pipeline:
138
-
139
- ```yaml
140
- # Example GitHub Actions workflow
141
- - name: Build library
142
- run: npm run build:lib
143
-
144
- - name: Verify build integrity
145
- run: npm run verify:build
146
- ```
147
-
148
- ## Manual Verification
149
-
150
- To manually verify specific aspects:
151
-
152
- ```bash
153
- # Check @source inline() directives
154
- grep -c "@source inline" dist/styles.css
155
-
156
- # Check CSS variables
157
- grep -c "--.*:" dist/styles.css
158
-
159
- # Check custom classes
160
- grep -c "\.nqui-" dist/styles.css
161
-
162
- # Check for unwanted patterns
163
- grep "@import" dist/styles.css # Should return nothing
164
- grep "@custom-variant" dist/styles.css # Should return nothing
165
- ```
166
-
167
- ## Related Files
168
-
169
- - `scripts/build-styles.js` - Build script that generates `dist/styles.css`
170
- - `scripts/verify-build.js` - Verification script
171
- - `src/index.css` - Main source CSS file
172
- - `src/styles/colors.css` - Color system variables
173
- - `src/styles/elevation.css` - Z-index elevation variables
174
- - `dist/styles.css` - Built CSS file (generated)