@exxatdesignux/ui 0.4.0 → 0.4.1
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/CHANGELOG.md +93 -0
- package/README.md +138 -0
- package/bin/init.mjs +134 -31
- package/dist/components/ui/banner.d.ts +2 -2
- package/package.json +3 -2
- package/template/eslint.config.mjs +9 -39
- package/template/package.json +0 -1
- package/tokens/hooks-index.json +2874 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,98 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ### `@exxatdesignux/ui` — publish hygiene + smarter scaffolder
|
|
8
|
+
|
|
9
|
+
Three real bugs in the `0.4.0` tarball made first-run consumer installs
|
|
10
|
+
fail. All three are now fixed.
|
|
11
|
+
- **`tokens/hooks-index.json` ships.** The `exports` map declared
|
|
12
|
+
`"./tokens/hooks-index.json"` but the `files` array did not include
|
|
13
|
+
`tokens`, so the file was silently omitted from the published tarball.
|
|
14
|
+
Any `import "@exxatdesignux/ui/tokens/hooks-index.json"` (used by
|
|
15
|
+
`@exxatdesignux/eslint-plugin`'s `no-deprecated-tokens` rule and by
|
|
16
|
+
workspaces that read the token registry) blew up with
|
|
17
|
+
`MODULE_NOT_FOUND`. The `files` array now includes `tokens`.
|
|
18
|
+
- **No more `workspace:*` leaking into the published template.** The
|
|
19
|
+
scaffolder template was sync'd from `apps/web/package.json`, which
|
|
20
|
+
uses `workspace:*` for both `@exxatdesignux/ui` (correct, gets
|
|
21
|
+
rewritten to a real semver pin) and a handful of monorepo-internal
|
|
22
|
+
dev tools (`@exxatdesignux/eslint-plugin`, …) which are not published
|
|
23
|
+
on npm. The previous sync rewrote only the design-system line, so
|
|
24
|
+
every consumer install (`npm` / `pnpm` / `yarn`) crashed on the
|
|
25
|
+
leaked entries. The sync script now walks every dep map
|
|
26
|
+
(`dependencies` / `devDependencies` / `peerDependencies` /
|
|
27
|
+
`optionalDependencies`), pins `@exxatdesignux/ui`, deletes any
|
|
28
|
+
remaining `workspace:` value, and fails the build if any leaks
|
|
29
|
+
survive — so the bug surfaces here, not on a consumer's terminal.
|
|
30
|
+
- **Consumer-safe `eslint.config.mjs` in the template.** The repo's
|
|
31
|
+
own `apps/web/eslint.config.mjs` imports
|
|
32
|
+
`@exxatdesignux/eslint-plugin` for DS guardrails (no hex literals,
|
|
33
|
+
no deprecated tokens, no SLDS leakage, no Sonner toasts). Because
|
|
34
|
+
that plugin isn't published, `pnpm lint` in a freshly-scaffolded app
|
|
35
|
+
crashed with `Cannot find package '@exxatdesignux/eslint-plugin'`.
|
|
36
|
+
The sync script now overwrites `template/eslint.config.mjs` with a
|
|
37
|
+
clean `eslint-config-next + globalIgnores + unused-vars` setup that
|
|
38
|
+
every consumer can run. The DS guardrails graduate to this template
|
|
39
|
+
whenever the plugin lands on npm.
|
|
40
|
+
|
|
41
|
+
### Smarter `bin/init.mjs` scaffolder
|
|
42
|
+
|
|
43
|
+
The `create-exxat-app` binary now matches the conventions of
|
|
44
|
+
`create-next-app` and `create-vite`:
|
|
45
|
+
- **Positional target directory.** `create-exxat-app my-app` creates
|
|
46
|
+
`./my-app` and scaffolds into it. `create-exxat-app .` scaffolds
|
|
47
|
+
into the current directory. Missing directories are auto-created.
|
|
48
|
+
- **Package-manager auto-detection.** Reads `npm_config_user_agent`
|
|
49
|
+
and runs the matching install (`pnpm install` / `yarn install` /
|
|
50
|
+
`bun install` / `npm install`). The post-install hint prints the
|
|
51
|
+
matching `<pm> run dev` command.
|
|
52
|
+
- **`--force` flag.** Allow scaffolding into a non-empty directory
|
|
53
|
+
(existing files are not overwritten unless the template ships the
|
|
54
|
+
same path). The previous "directory must be empty" hard-error
|
|
55
|
+
blocked every "install the DS first, then scaffold" sequence.
|
|
56
|
+
- **`--no-install` flag.** Skip the install step (useful in CI or
|
|
57
|
+
sandboxed setups).
|
|
58
|
+
- **`--help` / `-h`.** Print usage.
|
|
59
|
+
- **Clearer blocked-directory error.** When the target is non-empty
|
|
60
|
+
without `--force`, the CLI lists which files are blocking and
|
|
61
|
+
suggests both options (`create-exxat-app my-new-app` or
|
|
62
|
+
`create-exxat-app . --force`) instead of failing silently.
|
|
63
|
+
|
|
64
|
+
### Real README on the npm package page
|
|
65
|
+
|
|
66
|
+
`packages/ui/` had no `README.md` — the npm landing page at
|
|
67
|
+
[npmjs.com/package/@exxatdesignux/ui](https://www.npmjs.com/package/@exxatdesignux/ui)
|
|
68
|
+
showed only the bare package.json description. The new README leads
|
|
69
|
+
with the 60-second start (`pnpm create exxat-app my-app`), covers
|
|
70
|
+
"adding to an existing Next.js app", documents `exxat-ui sync-extras`
|
|
71
|
+
for Cursor skill installation, and links the full doc set.
|
|
72
|
+
|
|
73
|
+
### `create-exxat-app@0.0.x` → new package
|
|
74
|
+
|
|
75
|
+
A new `create-exxat-app` discovery package now ships on npm so
|
|
76
|
+
`pnpm create exxat-app my-app` (and the npm / yarn / bun variants)
|
|
77
|
+
resolve natively without a `--package=` flag. The shim is intentionally
|
|
78
|
+
tiny — it depends on `@exxatdesignux/ui` (via `workspace:^`, pinned to
|
|
79
|
+
`^<version>` at publish) and delegates to
|
|
80
|
+
`@exxatdesignux/ui/bin/init.mjs`. All template, version-pinning, and
|
|
81
|
+
package-manager-detection logic stays in `@exxatdesignux/ui` so there
|
|
82
|
+
is exactly one source of truth.
|
|
83
|
+
|
|
84
|
+
### Migration
|
|
85
|
+
|
|
86
|
+
Consumers on `0.4.0` should bump to `0.4.1`:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pnpm up @exxatdesignux/ui@latest
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
If you scaffolded with `0.4.0` and edited `eslint.config.mjs` /
|
|
93
|
+
`package.json` to work around the workspace leak, you can either keep
|
|
94
|
+
your manual edits or re-scaffold with `0.4.1` for a clean baseline.
|
|
95
|
+
|
|
3
96
|
## 0.4.0
|
|
4
97
|
|
|
5
98
|
### Minor Changes
|
package/README.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# @exxatdesignux/ui
|
|
2
|
+
|
|
3
|
+
The Exxat Design System — a Next.js + React 19 + Tailwind v4 component
|
|
4
|
+
library plus the full hub-page stack (`ListPageTemplate`, `DataTable`,
|
|
5
|
+
`HubTable`, `TablePropertiesDrawer`, `KeyMetrics`, `PageHeader`, board
|
|
6
|
+
cards, charts, …) wrapped in one publishable package.
|
|
7
|
+
|
|
8
|
+
## 60-second start
|
|
9
|
+
|
|
10
|
+
Spin up a brand-new app pre-wired with the DS:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pnpm create exxat-app my-app
|
|
14
|
+
cd my-app
|
|
15
|
+
pnpm dev
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Works with every modern package manager — the scaffolder auto-detects
|
|
19
|
+
the runner and uses the matching install:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm create exxat-app my-app
|
|
23
|
+
yarn create exxat-app my-app
|
|
24
|
+
bun create exxat-app my-app
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The scaffolder ships a complete Next.js 16 starter: the reference
|
|
28
|
+
**Library** hub at `/library/all`, the `/columns` cell-catalog showcase,
|
|
29
|
+
typed mock data, the full Cursor skill + pattern doc set under
|
|
30
|
+
`cursor-rules/`, `cursor-skills/`, `patterns/`, and `handbook/`.
|
|
31
|
+
|
|
32
|
+
## Adding to an existing Next.js app
|
|
33
|
+
|
|
34
|
+
If you already have a Next 15/16 app and just want the components:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pnpm add @exxatdesignux/ui
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Then in your global CSS (e.g. `app/globals.css`):
|
|
41
|
+
|
|
42
|
+
```css
|
|
43
|
+
@import "@exxatdesignux/ui/globals.css";
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
And import primitives or full patterns from the umbrella or a subpath:
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { DataTable, HubTable, ListPageTemplate, KeyMetrics } from "@exxatdesignux/ui"
|
|
50
|
+
import { Button } from "@exxatdesignux/ui/components/button"
|
|
51
|
+
import { useTableState } from "@exxatdesignux/ui/components/data-table/use-table-state"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Mount `KeyMetricsProvider` near the root if you want the "Ask Leo about
|
|
55
|
+
these metrics" CTA wired to your AI surface (otherwise the strip just
|
|
56
|
+
hides that button automatically).
|
|
57
|
+
|
|
58
|
+
## Refresh Cursor skills + pattern docs in any consumer
|
|
59
|
+
|
|
60
|
+
The package ships a parallel set of binding rules, skills, and pattern
|
|
61
|
+
docs so AI agents in your own repo can read the same guidance the source
|
|
62
|
+
repo uses. To install or refresh them in your repo:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pnpm dlx --package=@exxatdesignux/ui@latest exxat-ui sync-extras
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This copies `cursor-rules/`, `cursor-skills/`, `patterns/`, and
|
|
69
|
+
`handbook/` into your repo root. The next time Cursor opens, every
|
|
70
|
+
binding rule + skill is live.
|
|
71
|
+
|
|
72
|
+
## What's inside
|
|
73
|
+
|
|
74
|
+
- **Primitives** (`@exxatdesignux/ui/components/<name>`) — Button, Input,
|
|
75
|
+
Select, Dialog, AlertDialog, Sheet, Drawer, Popover, DropdownMenu,
|
|
76
|
+
ContextMenu, Tabs, Accordion, Tooltip, Toast-free Banner, ScrollArea,
|
|
77
|
+
Slider, HoverCard, Avatar, Badge, StatusBadge, Calendar, Kbd, …
|
|
78
|
+
- **Hub stack** — `DataTable<TRow>`, `useTableState<TRow>`,
|
|
79
|
+
`TablePropertiesDrawer`, `HubTable<TRow>`, `ListPageTemplate`,
|
|
80
|
+
`PageHeader`, `KeyMetrics`, `ListPageBoardCard`,
|
|
81
|
+
`ListPageBoardTemplate`, `DataRowList`, `FinderPanelView`,
|
|
82
|
+
`FolderGridView`, `OutlineTreeMenu`.
|
|
83
|
+
- **Data-list registry** — `DataListViewType`, `DATA_LIST_VIEW_TILES`,
|
|
84
|
+
`dataListViewIcon`, `dataListViewAddShortcut`, `usesDataTableComponent`,
|
|
85
|
+
`usesDashboardSurface`.
|
|
86
|
+
- **Templates** — `ListPageTemplate`, `NestedSecondaryPanelShell`,
|
|
87
|
+
`DedicatedSearchLandingTemplate`, `DedicatedSearchResultsTemplate`.
|
|
88
|
+
- **Tokens** — `tokens/hooks-index.json` (197 tokens · 42 namespaces)
|
|
89
|
+
feeds the workspace ESLint plugin's `no-deprecated-tokens` rule.
|
|
90
|
+
- **Tailwind v4 token bridge** — `globals.css` imports the L0
|
|
91
|
+
`--exxat-color-*` / `--exxat-radius-*` / `--exxat-spacing-*` family
|
|
92
|
+
and wires Tailwind shorthand (`bg-surface-1`, `text-ink-1`,
|
|
93
|
+
`rounded-2`, …) via `@theme inline`.
|
|
94
|
+
|
|
95
|
+
## CLI commands
|
|
96
|
+
|
|
97
|
+
After `pnpm add @exxatdesignux/ui` (or globally `npm i -g @exxatdesignux/ui`):
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# In an empty directory (or new sub-folder), scaffold an app:
|
|
101
|
+
npx --package=@exxatdesignux/ui create-exxat-app my-app
|
|
102
|
+
|
|
103
|
+
# Sync Cursor skills + binding rules + pattern docs into your repo:
|
|
104
|
+
npx --package=@exxatdesignux/ui exxat-ui sync-extras
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The standalone [`create-exxat-app`](https://www.npmjs.com/package/create-exxat-app)
|
|
108
|
+
package wraps the first command so `<pm> create exxat-app …` resolves
|
|
109
|
+
natively.
|
|
110
|
+
|
|
111
|
+
## Docs
|
|
112
|
+
|
|
113
|
+
- Design-system **HANDBOOK** — read-this-first orientation, the 6-step
|
|
114
|
+
"how to build a hub" walkthrough, the §13 PR checklist.
|
|
115
|
+
- **Blueprints** — framework-agnostic specs for each major composition
|
|
116
|
+
(`PageHeader`, `DataTable`, `ListPageTemplate`, `BoardCard`,
|
|
117
|
+
`KeyMetrics`, …).
|
|
118
|
+
- **Component selection guide** — top-of-funnel decision tree for
|
|
119
|
+
picking the right composition.
|
|
120
|
+
- **Token taxonomy** — naming + deprecation policy for every CSS
|
|
121
|
+
custom property the DS ships.
|
|
122
|
+
|
|
123
|
+
The full doc set is mirrored under `handbook/` and `patterns/` in this
|
|
124
|
+
package; `exxat-ui sync-extras` drops them into your repo so they sit
|
|
125
|
+
alongside your source.
|
|
126
|
+
|
|
127
|
+
## Compatibility
|
|
128
|
+
|
|
129
|
+
| Peer | Range |
|
|
130
|
+
| --- | --- |
|
|
131
|
+
| React | `>=19.0.0` |
|
|
132
|
+
| Next.js | `>=15.0.0` (App Router) |
|
|
133
|
+
| Tailwind CSS | `>=4.0.0` |
|
|
134
|
+
| Node | `>=22.0.0` (build / dev) |
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
UNLICENSED — proprietary to Exxat Design.
|
package/bin/init.mjs
CHANGED
|
@@ -1,43 +1,146 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Scaffold a new Exxat DS app from the bundled template.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx create-exxat-app # scaffold into current directory
|
|
7
|
+
* npx create-exxat-app my-app # scaffold into ./my-app (created if missing)
|
|
8
|
+
* npx create-exxat-app . --force # overwrite-merge into current directory
|
|
9
|
+
* npx create-exxat-app my-app --no-install # skip the package install step
|
|
10
|
+
*
|
|
11
|
+
* Also runs as `npx --package=@exxatdesignux/ui create-exxat-app …` and as
|
|
12
|
+
* `pnpm create exxat-app …` when invoked via the standalone create-exxat-app
|
|
13
|
+
* discovery shim.
|
|
14
|
+
*/
|
|
15
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs"
|
|
16
|
+
import { resolve, dirname, basename, join } from "node:path"
|
|
17
|
+
import { fileURLToPath } from "node:url"
|
|
18
|
+
import { execSync } from "node:child_process"
|
|
6
19
|
|
|
7
20
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
8
|
-
const templateDir = resolve(__dirname,
|
|
9
|
-
const selfPkgPath = resolve(__dirname,
|
|
10
|
-
const
|
|
21
|
+
const templateDir = resolve(__dirname, "../template")
|
|
22
|
+
const selfPkgPath = resolve(__dirname, "../package.json")
|
|
23
|
+
const selfPkg = JSON.parse(readFileSync(selfPkgPath, "utf8"))
|
|
11
24
|
|
|
12
|
-
const
|
|
13
|
-
const
|
|
25
|
+
const args = process.argv.slice(2)
|
|
26
|
+
const flags = new Set(args.filter((a) => a.startsWith("--")))
|
|
27
|
+
const positional = args.filter((a) => !a.startsWith("--"))
|
|
28
|
+
const targetArg = positional[0] ?? "."
|
|
29
|
+
const targetDir = resolve(process.cwd(), targetArg)
|
|
30
|
+
const projectName = targetArg === "." ? basename(targetDir) : targetArg
|
|
31
|
+
const force = flags.has("--force")
|
|
32
|
+
const skipInstall = flags.has("--no-install") || flags.has("--skip-install")
|
|
14
33
|
|
|
15
|
-
if (
|
|
16
|
-
console.
|
|
34
|
+
if (flags.has("--help") || flags.has("-h")) {
|
|
35
|
+
console.log(`
|
|
36
|
+
create-exxat-app — scaffold a Next.js app on @exxatdesignux/ui
|
|
37
|
+
|
|
38
|
+
Usage:
|
|
39
|
+
create-exxat-app [target-directory] [options]
|
|
40
|
+
|
|
41
|
+
Arguments:
|
|
42
|
+
target-directory Where to create the app (default: ".")
|
|
43
|
+
A relative or absolute path. Created if it does not exist.
|
|
44
|
+
|
|
45
|
+
Options:
|
|
46
|
+
--force Allow scaffolding into a non-empty directory (existing
|
|
47
|
+
files are NOT overwritten unless template ships the
|
|
48
|
+
same path).
|
|
49
|
+
--no-install Skip the dependency install step.
|
|
50
|
+
-h, --help Show this message.
|
|
51
|
+
|
|
52
|
+
Examples:
|
|
53
|
+
create-exxat-app my-app
|
|
54
|
+
create-exxat-app .
|
|
55
|
+
create-exxat-app ../sandbox --force --no-install
|
|
56
|
+
`)
|
|
57
|
+
process.exit(0)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!existsSync(targetDir)) {
|
|
61
|
+
mkdirSync(targetDir, { recursive: true })
|
|
62
|
+
console.log(`📁 Created ${projectName}/`)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const targetStat = statSync(targetDir)
|
|
66
|
+
if (!targetStat.isDirectory()) {
|
|
67
|
+
console.error(`❌ Target ${targetDir} exists but is not a directory.`)
|
|
17
68
|
process.exit(1)
|
|
18
69
|
}
|
|
19
70
|
|
|
20
|
-
|
|
71
|
+
const existing = readdirSync(targetDir)
|
|
72
|
+
const ignorable = new Set([".git", ".gitignore", ".DS_Store"])
|
|
73
|
+
const blockers = existing.filter((name) => !ignorable.has(name))
|
|
74
|
+
|
|
75
|
+
if (blockers.length > 0 && !force) {
|
|
76
|
+
console.error(`❌ Target directory is not empty (${targetDir}).`)
|
|
77
|
+
console.error("")
|
|
78
|
+
console.error(" Found:")
|
|
79
|
+
for (const name of blockers.slice(0, 8)) console.error(` - ${name}`)
|
|
80
|
+
if (blockers.length > 8) console.error(` … and ${blockers.length - 8} more`)
|
|
81
|
+
console.error("")
|
|
82
|
+
console.error(" Options:")
|
|
83
|
+
console.error(` 1. Scaffold into a new folder: create-exxat-app my-app`)
|
|
84
|
+
console.error(` 2. Allow merging existing files: create-exxat-app . --force`)
|
|
85
|
+
console.error("")
|
|
86
|
+
process.exit(1)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
console.log(`📦 Copying Exxat DS starter app into ${projectName}/ …`)
|
|
21
90
|
cpSync(templateDir, targetDir, { recursive: true })
|
|
22
91
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const targetPkgPath = resolve(targetDir,
|
|
26
|
-
const targetPkg = JSON.parse(readFileSync(targetPkgPath,
|
|
27
|
-
if (targetPkg.dependencies?.[
|
|
28
|
-
targetPkg.dependencies[
|
|
29
|
-
writeFileSync(targetPkgPath, `${JSON.stringify(targetPkg, null, 2)}\n`)
|
|
30
|
-
console.log(`📌 Pinned @exxatdesignux/ui to ^${selfVersion} (matches this scaffold).`)
|
|
92
|
+
// Pin DS to this CLI's published version so `latest` cache drift cannot
|
|
93
|
+
// trick the consumer into installing an older dist.
|
|
94
|
+
const targetPkgPath = resolve(targetDir, "package.json")
|
|
95
|
+
const targetPkg = JSON.parse(readFileSync(targetPkgPath, "utf8"))
|
|
96
|
+
if (targetPkg.dependencies?.["@exxatdesignux/ui"]) {
|
|
97
|
+
targetPkg.dependencies["@exxatdesignux/ui"] = `^${selfPkg.version}`
|
|
31
98
|
}
|
|
99
|
+
// Name the project after the target dir for nicer dev-server / process titles.
|
|
100
|
+
targetPkg.name = projectName.replace(/[^a-z0-9-_]/gi, "-").toLowerCase() || "my-exxat-app"
|
|
101
|
+
writeFileSync(targetPkgPath, `${JSON.stringify(targetPkg, null, 2)}\n`)
|
|
102
|
+
console.log(`📌 Pinned @exxatdesignux/ui to ^${selfPkg.version} and named the project "${targetPkg.name}".`)
|
|
32
103
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
console.log(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
console.
|
|
42
|
-
console.
|
|
43
|
-
console.
|
|
104
|
+
const pm = detectPackageManager()
|
|
105
|
+
if (skipInstall) {
|
|
106
|
+
console.log(`⏭ Skipped install (--no-install).`)
|
|
107
|
+
} else {
|
|
108
|
+
console.log(`📥 Installing dependencies with ${pm.label} …`)
|
|
109
|
+
try {
|
|
110
|
+
execSync(pm.installCmd, { stdio: "inherit", cwd: targetDir })
|
|
111
|
+
} catch (err) {
|
|
112
|
+
console.error("")
|
|
113
|
+
console.error(`❌ ${pm.label} install failed. You can retry manually:`)
|
|
114
|
+
console.error(` cd ${projectName} && ${pm.installCmd}`)
|
|
115
|
+
process.exit(1)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
console.log("")
|
|
120
|
+
console.log(`✅ Done! Your Exxat DS app is ready in ./${projectName}/`)
|
|
121
|
+
console.log("")
|
|
122
|
+
console.log(` cd ${projectName}`)
|
|
123
|
+
console.log(` ${pm.runCmd} dev # start dev server`)
|
|
124
|
+
console.log("")
|
|
125
|
+
console.log(" Optional — refresh Cursor skills + pattern docs:")
|
|
126
|
+
console.log(` ${pm.dlxCmd} --package=@exxatdesignux/ui@${selfPkg.version} exxat-ui sync-extras`)
|
|
127
|
+
console.log("")
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Detect the package manager that invoked us — npm_config_user_agent is set
|
|
131
|
+
* by every modern package-runner (npm, pnpm, yarn, bun) and looks like
|
|
132
|
+
* "pnpm/10.33.0 npm/? node/v22.0.0 darwin arm64". We fall back to npm.
|
|
133
|
+
*/
|
|
134
|
+
function detectPackageManager() {
|
|
135
|
+
const ua = process.env.npm_config_user_agent ?? ""
|
|
136
|
+
if (ua.startsWith("pnpm")) {
|
|
137
|
+
return { label: "pnpm", installCmd: "pnpm install", runCmd: "pnpm", dlxCmd: "pnpm dlx" }
|
|
138
|
+
}
|
|
139
|
+
if (ua.startsWith("yarn")) {
|
|
140
|
+
return { label: "yarn", installCmd: "yarn install", runCmd: "yarn", dlxCmd: "yarn dlx" }
|
|
141
|
+
}
|
|
142
|
+
if (ua.startsWith("bun")) {
|
|
143
|
+
return { label: "bun", installCmd: "bun install", runCmd: "bun", dlxCmd: "bunx" }
|
|
144
|
+
}
|
|
145
|
+
return { label: "npm", installCmd: "npm install", runCmd: "npm run", dlxCmd: "npx" }
|
|
146
|
+
}
|
|
@@ -4,7 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
6
|
declare const systemBannerVariants: (props?: ({
|
|
7
|
-
variant?: "
|
|
7
|
+
variant?: "success" | "warning" | "error" | "info" | "promo" | null | undefined;
|
|
8
8
|
emphasis?: "prominent" | "subtle" | null | undefined;
|
|
9
9
|
actionPosition?: "inline" | "bottom" | null | undefined;
|
|
10
10
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
@@ -32,7 +32,7 @@ interface SystemBannerProps extends React.HTMLAttributes<HTMLDivElement>, Varian
|
|
|
32
32
|
}
|
|
33
33
|
declare function SystemBanner({ children, title, variant, emphasis, dismissible, onDismiss, action, actionPosition, icon, decorativeOverlay, className, style, ...props }: SystemBannerProps): react_jsx_runtime.JSX.Element | null;
|
|
34
34
|
declare const localBannerVariants: (props?: ({
|
|
35
|
-
variant?: "
|
|
35
|
+
variant?: "success" | "warning" | "error" | "info" | "promo" | null | undefined;
|
|
36
36
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
37
37
|
interface LocalBannerProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof localBannerVariants> {
|
|
38
38
|
/** Banner title (optional) */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exxatdesignux/ui",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Exxat shared design system (components, hooks, tokens). Monorepo setup: clone repo then pnpm bootstrap at workspace root — see github.com/ExxatDesign/Exxat-DS-Workspace README.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "Exxat Design",
|
|
@@ -98,7 +98,8 @@
|
|
|
98
98
|
"src",
|
|
99
99
|
"bin",
|
|
100
100
|
"template",
|
|
101
|
-
"consumer-extras"
|
|
101
|
+
"consumer-extras",
|
|
102
|
+
"tokens"
|
|
102
103
|
],
|
|
103
104
|
"dependencies": {
|
|
104
105
|
"@hookform/resolvers": "^5.2.2",
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { defineConfig, globalIgnores } from "eslint/config"
|
|
2
|
-
import nextVitals from "eslint-config-next/core-web-vitals"
|
|
3
|
-
import nextTs from "eslint-config-next/typescript"
|
|
4
|
-
import exxatDs from "@exxatdesignux/eslint-plugin";
|
|
1
|
+
import { defineConfig, globalIgnores } from "eslint/config"
|
|
2
|
+
import nextVitals from "eslint-config-next/core-web-vitals"
|
|
3
|
+
import nextTs from "eslint-config-next/typescript"
|
|
5
4
|
|
|
5
|
+
// Consumer-facing ESLint config for a scaffolded Exxat DS app.
|
|
6
|
+
// The Exxat-DS guardrail plugin (`@exxatdesignux/eslint-plugin`) is
|
|
7
|
+
// currently workspace-internal — once it lands on npm you can add it
|
|
8
|
+
// alongside the blocks below and the same DS lint rules will run here.
|
|
6
9
|
const eslintConfig = defineConfig([
|
|
7
10
|
...nextVitals,
|
|
8
11
|
...nextTs,
|
|
9
|
-
// Override default ignores of eslint-config-next.
|
|
10
12
|
globalIgnores([
|
|
11
|
-
// Default ignores of eslint-config-next:
|
|
12
13
|
".next/**",
|
|
13
14
|
"out/**",
|
|
14
15
|
"build/**",
|
|
@@ -16,11 +17,6 @@ const eslintConfig = defineConfig([
|
|
|
16
17
|
]),
|
|
17
18
|
{
|
|
18
19
|
rules: {
|
|
19
|
-
// Allow intentionally-unused args / vars / destructured props /
|
|
20
|
-
// generics when prefixed with `_`. This is the standard escape hatch
|
|
21
|
-
// for "I'm satisfying a callback signature but don't need this slot"
|
|
22
|
-
// — common in cell renderers (`(value, _row) => …`), destructured
|
|
23
|
-
// tuples (`const [_, setX] = useState()`), and generic constraints.
|
|
24
20
|
"@typescript-eslint/no-unused-vars": [
|
|
25
21
|
"warn",
|
|
26
22
|
{
|
|
@@ -32,32 +28,6 @@ const eslintConfig = defineConfig([
|
|
|
32
28
|
],
|
|
33
29
|
},
|
|
34
30
|
},
|
|
35
|
-
|
|
36
|
-
// Exxat DS guardrails (@exxatdesignux/eslint-plugin — packages/eslint-plugin-exxat-ds).
|
|
37
|
-
// - no-hex-color: token discipline (no hex literals in JSX/style)
|
|
38
|
-
// - no-deprecated-tokens: reads @exxatdesignux/ui tokens/hooks-index.json
|
|
39
|
-
// - no-sonner-toast: enforces .cursor/rules/exxat-no-toast.mdc
|
|
40
|
-
// - no-slds-classes: enforces .cursor/rules/exxat-no-slds-leakage.mdc
|
|
41
|
-
// - no-lightning-elements: enforces .cursor/rules/exxat-no-slds-leakage.mdc
|
|
42
|
-
// -------------------------------------------------------------------------
|
|
43
|
-
{
|
|
44
|
-
files: ["app/**/*.{ts,tsx}", "components/**/*.{ts,tsx}", "lib/**/*.{ts,tsx}", "hooks/**/*.{ts,tsx}", "contexts/**/*.{ts,tsx}", "stores/**/*.{ts,tsx}"],
|
|
45
|
-
plugins: { "exxat-ds": exxatDs },
|
|
46
|
-
rules: {
|
|
47
|
-
"exxat-ds/no-hex-color": [
|
|
48
|
-
"warn",
|
|
49
|
-
{
|
|
50
|
-
// Files where hex is legitimately needed (CSS variable definitions,
|
|
51
|
-
// OS theme-color meta, etc.) are intentionally excluded by path.
|
|
52
|
-
allowFiles: ["/app/globals.css", "/packages/ui/src/globals.css", "/lib/theme-color", "/lib/windows-contrast-theme"],
|
|
53
|
-
},
|
|
54
|
-
],
|
|
55
|
-
"exxat-ds/no-deprecated-tokens": "error",
|
|
56
|
-
"exxat-ds/no-sonner-toast": "error",
|
|
57
|
-
"exxat-ds/no-slds-classes": "error",
|
|
58
|
-
"exxat-ds/no-lightning-elements": "error",
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
]);
|
|
31
|
+
])
|
|
62
32
|
|
|
63
|
-
export default eslintConfig
|
|
33
|
+
export default eslintConfig
|
package/template/package.json
CHANGED