@nqlib/nqui 0.4.5 → 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.
- package/INSTALLATION.md +27 -23
- package/README.md +1 -1
- package/dist/{command-palette-MHc03bBf.cjs → command-palette-DSQYbRiH.cjs} +2 -2
- package/dist/{command-palette-DCtLpM3Q.js → command-palette-D_SFxXyQ.js} +47 -50
- package/dist/command.cjs.js +1 -1
- package/dist/command.es.js +1 -1
- package/dist/components/custom/enhanced-scroll-area.d.ts.map +1 -1
- package/dist/components/index.d.ts +2 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/ui/card.d.ts.map +1 -1
- package/dist/components/ui/combobox.d.ts +63 -18
- package/dist/components/ui/combobox.d.ts.map +1 -1
- package/dist/components/ui/command.d.ts +9 -1
- package/dist/components/ui/command.d.ts.map +1 -1
- package/dist/{debug-panel-pg39-6xw.js → debug-panel-BtOvhfpR.js} +43 -39
- package/dist/{debug-panel-CNKk-No5.cjs → debug-panel-DLfH4sdK.cjs} +6 -6
- package/dist/debug.cjs.js +1 -1
- package/dist/debug.es.js +1 -1
- package/dist/nqui.cjs.js +13 -13
- package/dist/nqui.es.js +3620 -3266
- package/dist/styles.css +3 -2
- package/docs/components/nqui-card.md +1 -1
- package/docs/components/nqui-combobox.md +75 -11
- package/package.json +1 -7
- package/scripts/generate-docs.js +3 -1
- package/scripts/peer-deps.js +0 -1
- package/docs/internal-notes/APP_BUILDER_PACKAGE.md +0 -86
- package/docs/internal-notes/BUILD_VERIFICATION.md +0 -174
- package/docs/internal-notes/DASHBOARD_LAYOUT_DESIGN.md +0 -1429
- package/docs/internal-notes/FROSTED_GLASS_FIX.md +0 -50
- package/docs/internal-notes/INSTALLATION.md +0 -274
- package/docs/internal-notes/PEER_DEPENDENCIES.md +0 -105
- package/docs/internal-notes/PUBLISHING.md +0 -411
- package/docs/internal-notes/SKILLS-ARCHITECTURE.md +0 -105
- package/docs/internal-notes/layoutdesign.md +0 -616
- package/docs/internal-notes/progress.md +0 -348
- 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
|
-
|
|
1189
|
-
--accent
|
|
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
|
|
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 (
|
|
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
|
-
- **
|
|
9
|
-
- **
|
|
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 **`
|
|
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="
|
|
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
|
-
-
|
|
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.
|
|
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",
|
package/scripts/generate-docs.js
CHANGED
|
@@ -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(
|
|
42
|
+
const installPath = join(INTERNAL_NOTES_DIR, 'INSTALLATION.md');
|
|
41
43
|
let content = readDoc(installPath);
|
|
42
44
|
|
|
43
45
|
if (!content) {
|
package/scripts/peer-deps.js
CHANGED
|
@@ -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)
|